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 here.
+ *
+ * \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..d964c58258da
--- /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
+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 = ""
+ 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. {
+ 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 " +
+ "here."
+ % 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 <
Class.Widget."gain" {
#
- # Pipeline ID for the gain widget object
+ ## Pipeline ID for the gain widget object
#
DefineAttribute."index" {}
#
- # gain object instance
+ ## gain object instance
#
DefineAttribute."instance" {}
@@ -35,9 +35,9 @@ Class.Widget."gain" {
#
#
- # 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.
+ ## 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"
@@ -56,7 +56,7 @@ Class.Widget."gain" {
}
#
- # Gain curve in milliseconds
+ ## Gain curve in milliseconds
#
DefineAttribute."curve_duration" {
# Token set reference name
@@ -71,8 +71,8 @@ Class.Widget."gain" {
# 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.
+ ## 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"
@@ -114,9 +114,9 @@ Class.Widget."gain" {
# gain widget mixer controls
#
Object.Control {
- # gain mixer control
+ ## gain mixer control
mixer."1" {
- #Channel register and shift for Front Left/Right
+ ## Channel register and shift for Front Left/Right
Object.Base.channel.1 {
name "fl"
shift 0
@@ -128,7 +128,7 @@ Class.Widget."gain" {
Object.Base.ops.1 {
name "ctl"
info "volsw"
- #256 binds the mixer control to volume get/put handlers
+ ## get = 256 binds the mixer control to volume get/put handlers
get 256
put 256
}
diff --git a/tools/topology/topology2/include/components/widget-common.conf b/tools/topology/topology2/include/components/widget-common.conf
index af87e4e70f7d..3c398300ef89 100644
--- a/tools/topology/topology2/include/components/widget-common.conf
+++ b/tools/topology/topology2/include/components/widget-common.conf
@@ -2,12 +2,12 @@
# Common widget attribute definitions
#
-# instance of the widget object
+## 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
+## 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"
@@ -20,26 +20,26 @@ DefineAttribute."no_pm" {
}
#
-# Widget Type - maps to the widget ID with values of type enum SND_SOC_TPLG_DAPM_*
+## 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
+## Stream name - maps to the DAPM widget's stream name
#
DefineAttribute."stream_name" {
type "string"
}
#
-# Event type widget binds to
+## Event type widget binds to
#
DefineAttribute.event_type {}
#
-# Widget event flags
+## Widget event flags
#
DefineAttribute.event_flags {}
@@ -47,7 +47,7 @@ DefineAttribute.event_flags {}
# Attributes with a "token_ref" value will be added to widget's private data
#
-# widget format
+## widget format
DefineAttribute."format" {
type "string"
# Token set reference name and type
@@ -62,49 +62,50 @@ DefineAttribute."format" {
}
}
-# ID of the core this widget should be scheduled on
+## 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
+## 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
+## 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
+## 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
+## 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
+## Number of supported source(output) audio formats
DefineAttribute."num_output_audio_formats" {
# Token set reference name and type
token_ref "comp.word"
}
-# Widget UUID
+## 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
diff --git a/tools/topology/topology2/include/controls/common.conf b/tools/topology/topology2/include/controls/common.conf
index 77593fccc1fb..0cf249914070 100644
--- a/tools/topology/topology2/include/controls/common.conf
+++ b/tools/topology/topology2/include/controls/common.conf
@@ -1,15 +1,19 @@
-# Common class definitions for controls
-
-#
-# Class for channel objects. These are instantiated as:
-# Object.Base.channel."fl" {
-# reg 1
-# shift 0
-# }
-#
+## \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
+ ## name of the channel
DefineAttribute."name" {
type "string"
}
@@ -33,13 +37,18 @@ Class.Base."channel" {
shift 1
}
-# Class definition for control ops. These are instantiated as:
-# Object.Base.ops."ctl" {
-# info "volsw"
-# get "259"
-# put "259"
-# }
-#
+## \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
@@ -68,13 +77,17 @@ Class.Base."ops" {
}
}
-# Class definition for control extops. These are instantiated as:
-# Object.Base.extops."ctl" {
-# info "volsw"
-# get "258"
-# put "258"
-# }
-#
+## \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
@@ -104,12 +117,15 @@ Class.Base."extops" {
}
}
-#
-# Class definition for scale objects. These are instantiated as follows:
-# Object.Base.scale."name" {
-# mute 1
-# }
-#
+## \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" {
@@ -139,11 +155,17 @@ Class.Base."scale" {
mute 1
}
-#
-# Class definition for tlv objects. These are instantiated as follows:
-# Object.Base.tlv."vtlv_m64s2" {
-# Object.Base.scale."0" {}
-# }
+## \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" {
diff --git a/tools/topology/topology2/include/controls/mixer.conf b/tools/topology/topology2/include/controls/mixer.conf
index 66b5085cf857..191230ec5bdc 100644
--- a/tools/topology/topology2/include/controls/mixer.conf
+++ b/tools/topology/topology2/include/controls/mixer.conf
@@ -1,41 +1,45 @@
-#
-# Mixer kcontrol 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"
-# mas 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"
-# }
-# }
-#
-# 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
+## \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
Class.Control."mixer" {
- #
- # Pipeline ID for the mixer object
- #
- DefineAttribute."index" {}
+ ##
+ ## @ Pipeline ID for the mixer object
+ ##
+ DefineAttribute."index" {} ##< Automatically given unique index
#
# Instance of mixer object in the same alsaconf node
diff --git a/tools/topology/topology2/include/dais/mic_extension.conf b/tools/topology/topology2/include/dais/mic_extension.conf
index 6dc12a1f21b2..31628e9b2241 100644
--- a/tools/topology/topology2/include/dais/mic_extension.conf
+++ b/tools/topology/topology2/include/dais/mic_extension.conf
@@ -1,3 +1,6 @@
+## \brief Mic extension class
+## \struct mic_extension
+
Class.Base."mic_extension" {
DefineAttribute."id" {}
diff --git a/tools/topology/topology2/include/dais/pdm_config.conf b/tools/topology/topology2/include/dais/pdm_config.conf
index 2a8759a7742c..3745bea7998e 100644
--- a/tools/topology/topology2/include/dais/pdm_config.conf
+++ b/tools/topology/topology2/include/dais/pdm_config.conf
@@ -1,3 +1,6 @@
+## \brief Class for PDM config
+## \struct pdm_config
+
Class.Base."pdm_config" {
DefineAttribute."instance" {}
#
diff --git a/tools/topology/topology2/include/pipelines/volume-playback.conf b/tools/topology/topology2/include/pipelines/volume-playback.conf
index d04830b2168a..fa007609ab4c 100644
--- a/tools/topology/topology2/include/pipelines/volume-playback.conf
+++ b/tools/topology/topology2/include/pipelines/volume-playback.conf
@@ -1,24 +1,26 @@
-#
-# 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"
-# channels 2
-# rate 48000
-# }
-#
-# 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)
-#
+## \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"
+## channels 2
+## rate 48000
+## }
+##
+## 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)
+##
@@ -31,7 +33,7 @@ Class.Pipeline."volume-playback" {
attributes {
- # pipeline name is constructed as "volume-playback.1"
+ ## pipeline name is constructed as "volume-playback.1"
!constructor [
"index"
]
@@ -49,9 +51,11 @@ Class.Pipeline."volume-playback" {
}
Object.Widget {
+ ## The pipeline object for captured playback
pipeline."1" {}
host."playback" {
+ ## "aif_in" is for playback
type "aif_in"
}
diff --git a/tools/topology/topology2/platform/intel/ssp_aux_config.conf b/tools/topology/topology2/platform/intel/ssp_aux_config.conf
index 1a814edef07e..c084faa4195c 100644
--- a/tools/topology/topology2/platform/intel/ssp_aux_config.conf
+++ b/tools/topology/topology2/platform/intel/ssp_aux_config.conf
@@ -1,3 +1,5 @@
+## \struct mn_config
+
Class.Base."mn_config" {
DefineAttribute."id" {}