/* * * 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 * * Copyright (C) 2015 Intel Corporation * */ #ifndef __ALSA_TOPOLOGY_H #define __ALSA_TOPOLOGY_H #ifdef __cplusplus extern "C" { #endif /** * \defgroup topology Topology Interface * \{ */ /*! \page topology ALSA Topology Interface * * The topology interface allows developers to define DSP topologies in a text * file format and to convert the text topology to a binary topology * representation that can be understood by the kernel. The topology core * currently recognises the following object types :- * * * Controls (mixer, enumerated and byte) including TLV data. * * PCMs (FE and BE configurations and capabilities) * * DAPM widgets * * DAPM graph elements. * * Private data for each object type. * * Manifest (containing count of each object type) * *
*
* ops."ctl" {
* info "volsw"
* get "257"
* put "257"
* }
*
*
*
* This mapping shows info() using the standard "volsw" info callback whilst
* the get() and put() are mapped to bespoke driver callbacks.
* scale {
* min "-9000"
* step "300"
* mute "1"
* }
*
*
* Where the meanings and values for min, step and mute are exactly the same
* as defined in driver code.
*
*
* channel."name" {
* reg "0"
* shift "0"
* }
*
*
* The channel map reg is the register offset for the control, shift is the
* bit shift within the register for the channel and the section name is the
* channel name and can be one of the following :-
*
* * * mono # mono stream * * fl # front left * * fr # front right * * rl # rear left * * rr # rear right * * fc # front center * * lfe # LFE * * sl # side left * * sr # side right * * rc # rear center * * flc # front left center * * frc # front right center * * rlc # rear left center * * rrc # rear right center * * flw # front left wide * * frw # front right wide * * flh # front left high * * fch # front center high * * frh # front right high * * tc # top center * * tfl # top front left * * tfr # top front right * * tfc # top front center * * trl # top rear left * * trr # top rear right * * trc # top rear center * * tflc # top front left center * * tfrc # top front right center * * tsl # top side left * * tsr # top side right * * llfe # left LFE * * rlfe # right LFE * * bc # bottom center * * blc # bottom left center * * brc # bottom right center ** *
* SectionData."pdata for EQU1" {
* file "/path/to/file"
* bytes "0x12,0x34,0x56,0x78"
* shorts "0x1122,0x3344,0x5566,0x7788"
* words "0xaabbccdd,0x11223344,0x66aa77bb,0xefef1234"
* };
*
* The file, bytes, shorts and words keywords are all mutually exclusive as
* the private data should only be taken from one source. The private data can
* either be read from a separate file or defined in the topology file using
* the bytes, shorts or words keywords.
*
*
* SectionControlMixer."mixer name" {
* comment "optional comments"
*
* index "1" # Index number
*
* channel."name" { # Channel maps
* ....
* }
*
* ops."ctl" { # Ops callback functions
* ....
* }
*
* max "32" # Max control value
* invert "0" # Whether control values are inverted
*
* tlv "tld_data" # optional TLV data
*
* data "pdata for mixer1" # optional private data
* }
*
*
* The section name is used to define the mixer name. The index number can be
* used to identify topology objects groups. This allows driver operations on
* objects with index number N and can be used to add/remove pipelines of
* objects whilst other objects are unaffected.
*
*
* SectionControlBytes."name" {
* comment "optional comments"
*
* index "1" # Index number
*
* channel."name" { # Channel maps
* ....
* }
*
* ops."ctl" { # Ops callback functions
* ....
* }
*
* base "0" # Register base
* num_regs "16" # Number of registers
* mask "0xff" # Mask
* max "255" # Maximum value
*
* tlv "tld_data" # optional TLV data
*
* data "pdata for mixer1" # optional private data
* }
*
*
*
* SectionText."name" {
*
* Values [
* "value1"
* "value2"
"value3"
* ]
* }
*
*
* All the enumerated text values are listed in the values list.
* SectionControlMixer."name" {
* comment "optional comments"
*
* index "1" # Index number
*
* texts "EQU1" # Enumerated text items
*
* channel."name" { # Channel maps
* ....
* }
*
* ops."ctl" { # Ops callback functions
* ....
* }
*
* data "pdata for mixer1" # optional private data
* }
*
*
*
* SectionGraph."dsp" {
* index "1" # Index number
*
* lines [
* "sink1, control, source1"
* "sink2, , source2"
* ]
* }
*
*
* The lines in the graph are defined as a variable size list of sinks,
* controls and sources. The control name is optional as some graph lines have
* no associated controls. The section name can be used to differentiate the
* graph with other graphs, it's not used by the kernel atm.
*
*
* SectionWidget."name" {
*
* index "1" # Index number
*
* type "aif_in" # Widget type - detailed above
*
* no_pm "true" # No PM control bit.
* reg "20" # PM bit register offset
* shift "0" # PM bit register shift
* invert "1 # PM bit is inverted
* subseq "8" # subsequence number
*
* event_type "1" # DAPM widget event type
* event_flags "1" # DAPM widget event flags
*
* mixer "name" # Optional Mixer Control
* enum "name" # Optional Enum Control
*
* data "name" # optional private data
* }
*
*
* The section name is the widget name. The mixer and enum fields are mutually
* exclusive and used to include controls into the widget. The index and data
* fields are the same for widgets as they are for controls whilst the other
* fields map on very closely to the driver widget fields.
*
*
* SectionPCMCapabilities."name" {
*
* formats "S24_LE,S16_LE" # Supported formats
* rate_min "48000" # Max supported sample rate
* rate_max "48000" # Min supported sample rate
* channels_min "2" # Min number of channels
* channels_max "2" # max number of channels
* }
*
* The supported formats use the same naming convention as the driver macros.
* The PCM capabilities name can be referred to and included by BE, PCM and
* Codec <-> codec topology sections.
*
*
* SectionPCMConfig."name" {
*
* config."playback" { # playback config
* format "S16_LE" # playback format
* rate "48000" # playback sample rate
* channels "2" # playback channels
* tdm_slot "0xf" # playback TDM slot
* }
*
* config."capture" { # capture config
* format "S16_LE" # capture format
* rate "48000" # capture sample rate
* channels "2" # capture channels
* tdm_slot "0xf" # capture TDM slot
* }
* }
*
*
* The supported formats use the same naming convention as the driver macros.
* The PCM configuration name can be referred to and included by BE, PCM and
* Codec <-> codec topology sections.
*
*
* SectionPCM."name" {
* ....
* }
* SectionBE."name" {
* ....
* }
* SectionCC."name" {
* ....
* }
*
*
* The section types above should be used for PCMs, Back Ends and Codec to Codec
* links respectively.
* SectionPCM."name" {
*
* index "1" # Index number
*
* id "0" # used for binding to the PCM
*
* pcm."playback" {
* capabilities "capabilities1" # capabilities for playback
*
* configs [ # supported configs for playback
* "config1"
* "config2"
* ]
* }
*
* pcm."capture" {
* capabilities "capabilities2" # capabilities for capture
*
* configs [ # supported configs for capture
* "config1"
* "config2"
* "config3"
* ]
* }
* }
*
*
*/
/** Maximum number of channels supported in one control */
#define SND_TPLG_MAX_CHAN 8
/** Topology context */
typedef struct snd_tplg snd_tplg_t;
/** Topology object types */
enum snd_tplg_type {
SND_TPLG_TYPE_TLV = 0, /*!< TLV Data */
SND_TPLG_TYPE_MIXER, /*!< Mixer control*/
SND_TPLG_TYPE_ENUM, /*!< Enumerated control */
SND_TPLG_TYPE_TEXT, /*!< Text data */
SND_TPLG_TYPE_DATA, /*!< Private data */
SND_TPLG_TYPE_BYTES, /*!< Byte control */
SND_TPLG_TYPE_STREAM_CONFIG, /*!< PCM Stream configuration */
SND_TPLG_TYPE_STREAM_CAPS, /*!< PCM Stream capabilities */
SND_TPLG_TYPE_PCM, /*!< PCM stream device */
SND_TPLG_TYPE_DAPM_WIDGET, /*!< DAPM widget */
SND_TPLG_TYPE_DAPM_GRAPH, /*!< DAPM graph elements */
SND_TPLG_TYPE_BE, /*!< BE DAI link */
SND_TPLG_TYPE_CC, /*!< Hostless codec <-> codec link */
SND_TPLG_TYPE_MANIFEST, /*!< Topology manifest */
};
/**
* \brief Create a new topology parser instance.
* \return New topology parser instance
*/
snd_tplg_t *snd_tplg_new(void);
/**
* \brief Free a topology parser instance.
* \param tplg Topology parser instance
*/
void snd_tplg_free(snd_tplg_t *tplg);
/**
* \brief Parse and build topology text file into binary file.
* \param tplg Topology instance.
* \param infile Topology text input file to be parsed
* \param outfile Binary topology output file.
* \return Zero on success, otherwise a negative error code
*/
int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile,
const char *outfile);
/**
* \brief Enable verbose reporting of binary file output
* \param tplg Topology Instance
* \param verbose Enable verbose output level if non zero
*/
void snd_tplg_verbose(snd_tplg_t *tplg, int verbose);
/** \struct snd_tplg_tlv_template
* \brief Template type for all TLV objects.
*/
struct snd_tplg_tlv_template {
int type; /*!< TLV type SNDRV_CTL_TLVT_ */
};
/** \struct snd_tplg_tlv_dbscale_template
* \brief Template type for TLV Scale objects.
*/
struct snd_tplg_tlv_dbscale_template {
struct snd_tplg_tlv_template hdr; /*!< TLV type header */
int min; /*!< dB minimum value in 0.1dB */
int step; /*!< dB step size in 0.1dB */
int mute; /*!< is min dB value mute ? */
};
/** \struct snd_tplg_channel_template
* \brief Template type for single channel mapping.
*/
struct snd_tplg_channel_elem {
int size; /*!< size in bytes of this structure */
int reg; /*!< channel control register */
int shift; /*!< channel shift for control bits */
int id; /*!< ID maps to Left, Right, LFE etc */
};
/** \struct snd_tplg_channel_map_template
* \brief Template type for channel mapping.
*/
struct snd_tplg_channel_map_template {
int num_channels; /*!< number of channel mappings */
struct snd_tplg_channel_elem channel[SND_TPLG_MAX_CHAN]; /*!< mapping */
};
/** \struct snd_tplg_pdata_template
* \brief Template type for private data objects.
*/
struct snd_tplg_pdata_template {
unsigned int length; /*!< data length */
const void *data; /*!< data */
};
/** \struct snd_tplg_io_ops_template
* \brief Template type for object operations mapping.
*/
struct snd_tplg_io_ops_template {
int get; /*!< get callback ID */
int put; /*!< put callback ID */
int info; /*!< info callback ID */
};
/** \struct snd_tplg_ctl_template
* \brief Template type for control objects.
*/
struct snd_tplg_ctl_template {
int type; /*!< Control type */
const char *name; /*!< Control name */
int access; /*!< Control access */
struct snd_tplg_io_ops_template ops; /*!< operations */
struct snd_tplg_tlv_template *tlv; /*!< non NULL means we have TLV data */
};
/** \struct snd_tplg_mixer_template
* \brief Template type for mixer control objects.
*/
struct snd_tplg_mixer_template {
struct snd_tplg_ctl_template hdr; /*!< control type header */
struct snd_tplg_channel_map_template *map; /*!< channel map */
int min; /*!< min value for mixer */
int max; /*!< max value for mixer */
int platform_max; /*!< max value for platform control */
int invert; /*!< whether controls bits are inverted */
struct snd_soc_tplg_private *priv; /*!< control private data */
};
/** \struct snd_tplg_enum_template
* \brief Template type for enumerated control objects.
*/
struct snd_tplg_enum_template {
struct snd_tplg_ctl_template hdr; /*!< control type header */
struct snd_tplg_channel_map_template *map; /*!< channel map */
int items; /*!< number of enumerated items in control */
int mask; /*!< register mask size */
const char **texts; /*!< control text items */
const int **values; /*!< control value items */
struct snd_soc_tplg_private *priv; /*!< control private data */
};
/** \struct snd_tplg_bytes_template
* \brief Template type for TLV Scale objects.
*/
struct snd_tplg_bytes_template {
struct snd_tplg_ctl_template hdr; /*!< control type header */
int max; /*!< max byte control value */
int mask; /*!< byte control mask */
int base; /*!< base register */
int num_regs; /*!< number of registers */
struct snd_tplg_io_ops_template ext_ops; /*!< ops mapping */
struct snd_soc_tplg_private *priv; /*!< control private data */
};
/** \struct snd_tplg_graph_elem
* \brief Template type for single DAPM graph element.
*/
struct snd_tplg_graph_elem {
const char *src; /*!< source widget name */
const char *ctl; /*!< control name or NULL if no control */
const char *sink; /*!< sink widget name */
};
/** \struct snd_tplg_graph_template
* \brief Template type for array of DAPM graph elements.
*/
struct snd_tplg_graph_template {
int count; /*!< Number of graph elements */
struct snd_tplg_graph_elem elem[0]; /*!< graph elements */
};
/** \struct snd_tplg_widget_template
* \brief Template type for DAPM widget objects.
*/
struct snd_tplg_widget_template {
int id; /*!< SND_SOC_DAPM_CTL */
const char *name; /*!< widget name */
const char *sname; /*!< stream name (certain widgets only) */
int reg; /*!< negative reg = no direct dapm */
int shift; /*!< bits to shift */
int mask; /*!< non-shifted mask */
int subseq; /*!< sort within widget type */
unsigned int invert; /*!< invert the power bit */
unsigned int ignore_suspend; /*!< kept enabled over suspend */
unsigned short event_flags; /*!< PM event sequence flags */
unsigned short event_type; /*!< PM event sequence type */
struct snd_soc_tplg_private *priv; /*!< widget private data */
int num_ctls; /*!< Number of controls used by widget */
struct snd_tplg_ctl_template *ctl[0]; /*!< array of widget controls */
};
/** \struct snd_tplg_obj_template
* \brief Generic Template Object
*/
typedef struct snd_tplg_obj_template {
enum snd_tplg_type type; /*!< template object type */
int index; /*!< group index for object */
int version; /*!< optional vendor specific version details */
int vendor_type; /*!< optional vendor specific type info */
union {
struct snd_tplg_widget_template *widget; /*!< DAPM widget */
struct snd_tplg_mixer_template *mixer; /*!< Mixer control */
struct snd_tplg_bytes_template *bytes_ctl; /*!< Bytes control */
struct snd_tplg_enum_template *enum_ctl; /*!< Enum control */
struct snd_tplg_graph_template *graph; /*!< Graph elements */
};
} snd_tplg_obj_template_t;
/**
* \brief Register topology template object.
* \param tplg Topology instance.
* \param t Template object.
* \return Zero on success, otherwise a negative error code
*/
int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
/**
* \brief Build all registered topology data into binary file.
* \param tplg Topology instance.
* \param outfile Binary topology output file.
* \return Zero on success, otherwise a negative error code
*/
int snd_tplg_build(snd_tplg_t *tplg, const char *outfile);
/**
* \brief Attach private data to topology manifest.
* \param tplg Topology instance.
* \param data Private data.
* \param len Length of data in bytes.
* \return Zero on success, otherwise a negative error code
*/
int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len);
/* \} */
#ifdef __cplusplus
}
#endif
#endif /* __ALSA_TOPOLOGY_H */