162306a36Sopenharmony_ci/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license. When using or 462306a36Sopenharmony_ci * redistributing this file, you may do so under either license. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright(c) 2019 Intel Corporation. All rights reserved. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#ifndef __SOUND_SOC_SOF_AUDIO_H 1262306a36Sopenharmony_ci#define __SOUND_SOC_SOF_AUDIO_H 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/workqueue.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <sound/soc.h> 1762306a36Sopenharmony_ci#include <sound/control.h> 1862306a36Sopenharmony_ci#include <sound/sof/stream.h> /* needs to be included before control.h */ 1962306a36Sopenharmony_ci#include <sound/sof/control.h> 2062306a36Sopenharmony_ci#include <sound/sof/dai.h> 2162306a36Sopenharmony_ci#include <sound/sof/topology.h> 2262306a36Sopenharmony_ci#include "sof-priv.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define SOF_AUDIO_PCM_DRV_NAME "sof-audio-component" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* 2762306a36Sopenharmony_ci * The ipc4 firmware only supports up to 8 sink or source pins 2862306a36Sopenharmony_ci * per widget, because only 3 bits are used for queue(pin) ID 2962306a36Sopenharmony_ci * in ipc4 protocol. 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_ci#define SOF_WIDGET_MAX_NUM_PINS 8 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* Widget pin type */ 3462306a36Sopenharmony_ci#define SOF_PIN_TYPE_INPUT 0 3562306a36Sopenharmony_ci#define SOF_PIN_TYPE_OUTPUT 1 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* max number of FE PCMs before BEs */ 3862306a36Sopenharmony_ci#define SOF_BE_PCM_BASE 16 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define DMA_CHAN_INVALID 0xFFFFFFFF 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define WIDGET_IS_DAI(id) ((id) == snd_soc_dapm_dai_in || (id) == snd_soc_dapm_dai_out) 4362306a36Sopenharmony_ci#define WIDGET_IS_AIF(id) ((id) == snd_soc_dapm_aif_in || (id) == snd_soc_dapm_aif_out) 4462306a36Sopenharmony_ci#define WIDGET_IS_AIF_OR_DAI(id) (WIDGET_IS_DAI(id) || WIDGET_IS_AIF(id)) 4562306a36Sopenharmony_ci#define WIDGET_IS_COPIER(id) (WIDGET_IS_AIF_OR_DAI(id) || (id) == snd_soc_dapm_buffer) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define SOF_DAI_CLK_INTEL_SSP_MCLK 0 4862306a36Sopenharmony_ci#define SOF_DAI_CLK_INTEL_SSP_BCLK 1 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cienum sof_widget_op { 5162306a36Sopenharmony_ci SOF_WIDGET_PREPARE, 5262306a36Sopenharmony_ci SOF_WIDGET_SETUP, 5362306a36Sopenharmony_ci SOF_WIDGET_FREE, 5462306a36Sopenharmony_ci SOF_WIDGET_UNPREPARE, 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* 5862306a36Sopenharmony_ci * Volume fractional word length define to 16 sets 5962306a36Sopenharmony_ci * the volume linear gain value to use Qx.16 format 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_ci#define VOLUME_FWL 16 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define SOF_TLV_ITEMS 3 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci if (value >= size) 6862306a36Sopenharmony_ci return volume_map[size - 1]; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci return volume_map[value]; 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci int i; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci for (i = 0; i < size; i++) { 7862306a36Sopenharmony_ci if (volume_map[i] >= value) 7962306a36Sopenharmony_ci return i; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci return i - 1; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistruct snd_sof_widget; 8662306a36Sopenharmony_cistruct snd_sof_route; 8762306a36Sopenharmony_cistruct snd_sof_control; 8862306a36Sopenharmony_cistruct snd_sof_dai; 8962306a36Sopenharmony_cistruct snd_sof_pcm; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistruct snd_sof_dai_config_data { 9262306a36Sopenharmony_ci int dai_index; 9362306a36Sopenharmony_ci int dai_data; /* contains DAI-specific information */ 9462306a36Sopenharmony_ci}; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/** 9762306a36Sopenharmony_ci * struct sof_ipc_pcm_ops - IPC-specific PCM ops 9862306a36Sopenharmony_ci * @hw_params: Function pointer for hw_params 9962306a36Sopenharmony_ci * @hw_free: Function pointer for hw_free 10062306a36Sopenharmony_ci * @trigger: Function pointer for trigger 10162306a36Sopenharmony_ci * @dai_link_fixup: Function pointer for DAI link fixup 10262306a36Sopenharmony_ci * @pcm_setup: Function pointer for IPC-specific PCM set up that can be used for allocating 10362306a36Sopenharmony_ci * additional memory in the SOF PCM stream structure 10462306a36Sopenharmony_ci * @pcm_free: Function pointer for PCM free that can be used for freeing any 10562306a36Sopenharmony_ci * additional memory in the SOF PCM stream structure 10662306a36Sopenharmony_ci * @delay: Function pointer for pcm delay calculation 10762306a36Sopenharmony_ci * @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the 10862306a36Sopenharmony_ci * STOP pcm trigger 10962306a36Sopenharmony_ci * @ipc_first_on_start: Send IPC before invoking platform trigger during 11062306a36Sopenharmony_ci * START/PAUSE_RELEASE triggers 11162306a36Sopenharmony_ci * @platform_stop_during_hw_free: Invoke the platform trigger during hw_free. This is needed for 11262306a36Sopenharmony_ci * IPC4 where a pipeline is only paused during stop/pause/suspend 11362306a36Sopenharmony_ci * triggers. The FW keeps the host DMA running in this case and 11462306a36Sopenharmony_ci * therefore the host must do the same and should stop the DMA during 11562306a36Sopenharmony_ci * hw_free. 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_cistruct sof_ipc_pcm_ops { 11862306a36Sopenharmony_ci int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, 11962306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 12062306a36Sopenharmony_ci struct snd_sof_platform_stream_params *platform_params); 12162306a36Sopenharmony_ci int (*hw_free)(struct snd_soc_component *component, struct snd_pcm_substream *substream); 12262306a36Sopenharmony_ci int (*trigger)(struct snd_soc_component *component, struct snd_pcm_substream *substream, 12362306a36Sopenharmony_ci int cmd); 12462306a36Sopenharmony_ci int (*dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); 12562306a36Sopenharmony_ci int (*pcm_setup)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm); 12662306a36Sopenharmony_ci void (*pcm_free)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm); 12762306a36Sopenharmony_ci snd_pcm_sframes_t (*delay)(struct snd_soc_component *component, 12862306a36Sopenharmony_ci struct snd_pcm_substream *substream); 12962306a36Sopenharmony_ci bool reset_hw_params_during_stop; 13062306a36Sopenharmony_ci bool ipc_first_on_start; 13162306a36Sopenharmony_ci bool platform_stop_during_hw_free; 13262306a36Sopenharmony_ci}; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/** 13562306a36Sopenharmony_ci * struct sof_ipc_tplg_control_ops - IPC-specific ops for topology kcontrol IO 13662306a36Sopenharmony_ci */ 13762306a36Sopenharmony_cistruct sof_ipc_tplg_control_ops { 13862306a36Sopenharmony_ci bool (*volume_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); 13962306a36Sopenharmony_ci int (*volume_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); 14062306a36Sopenharmony_ci bool (*switch_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); 14162306a36Sopenharmony_ci int (*switch_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); 14262306a36Sopenharmony_ci bool (*enum_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); 14362306a36Sopenharmony_ci int (*enum_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); 14462306a36Sopenharmony_ci int (*bytes_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); 14562306a36Sopenharmony_ci int (*bytes_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); 14662306a36Sopenharmony_ci int (*bytes_ext_get)(struct snd_sof_control *scontrol, 14762306a36Sopenharmony_ci const unsigned int __user *binary_data, unsigned int size); 14862306a36Sopenharmony_ci int (*bytes_ext_volatile_get)(struct snd_sof_control *scontrol, 14962306a36Sopenharmony_ci const unsigned int __user *binary_data, unsigned int size); 15062306a36Sopenharmony_ci int (*bytes_ext_put)(struct snd_sof_control *scontrol, 15162306a36Sopenharmony_ci const unsigned int __user *binary_data, unsigned int size); 15262306a36Sopenharmony_ci /* update control data based on notification from the DSP */ 15362306a36Sopenharmony_ci void (*update)(struct snd_sof_dev *sdev, void *ipc_control_message); 15462306a36Sopenharmony_ci /* Optional callback to setup kcontrols associated with an swidget */ 15562306a36Sopenharmony_ci int (*widget_kcontrol_setup)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); 15662306a36Sopenharmony_ci /* mandatory callback to set up volume table for volume kcontrols */ 15762306a36Sopenharmony_ci int (*set_up_volume_table)(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS], 15862306a36Sopenharmony_ci int size); 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/** 16262306a36Sopenharmony_ci * struct sof_ipc_tplg_widget_ops - IPC-specific ops for topology widgets 16362306a36Sopenharmony_ci * @ipc_setup: Function pointer for setting up widget IPC params 16462306a36Sopenharmony_ci * @ipc_free: Function pointer for freeing widget IPC params 16562306a36Sopenharmony_ci * @token_list: List of token ID's that should be parsed for the widget 16662306a36Sopenharmony_ci * @token_list_size: number of elements in token_list 16762306a36Sopenharmony_ci * @bind_event: Function pointer for binding events to the widget 16862306a36Sopenharmony_ci * @ipc_prepare: Optional op for preparing a widget for set up 16962306a36Sopenharmony_ci * @ipc_unprepare: Optional op for unpreparing a widget 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_cistruct sof_ipc_tplg_widget_ops { 17262306a36Sopenharmony_ci int (*ipc_setup)(struct snd_sof_widget *swidget); 17362306a36Sopenharmony_ci void (*ipc_free)(struct snd_sof_widget *swidget); 17462306a36Sopenharmony_ci enum sof_tokens *token_list; 17562306a36Sopenharmony_ci int token_list_size; 17662306a36Sopenharmony_ci int (*bind_event)(struct snd_soc_component *scomp, struct snd_sof_widget *swidget, 17762306a36Sopenharmony_ci u16 event_type); 17862306a36Sopenharmony_ci int (*ipc_prepare)(struct snd_sof_widget *swidget, 17962306a36Sopenharmony_ci struct snd_pcm_hw_params *fe_params, 18062306a36Sopenharmony_ci struct snd_sof_platform_stream_params *platform_params, 18162306a36Sopenharmony_ci struct snd_pcm_hw_params *source_params, int dir); 18262306a36Sopenharmony_ci void (*ipc_unprepare)(struct snd_sof_widget *swidget); 18362306a36Sopenharmony_ci}; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/** 18662306a36Sopenharmony_ci * struct sof_ipc_tplg_ops - IPC-specific topology ops 18762306a36Sopenharmony_ci * @widget: Array of pointers to IPC-specific ops for widgets. This should always be of size 18862306a36Sopenharmony_ci * SND_SOF_DAPM_TYPE_COUNT i.e one per widget type. Unsupported widget types will be 18962306a36Sopenharmony_ci * initialized to 0. 19062306a36Sopenharmony_ci * @control: Pointer to the IPC-specific ops for topology kcontrol IO 19162306a36Sopenharmony_ci * @route_setup: Function pointer for setting up pipeline connections 19262306a36Sopenharmony_ci * @route_free: Function pointer for freeing pipeline connections. 19362306a36Sopenharmony_ci * @token_list: List of all tokens supported by the IPC version. The size of the token_list 19462306a36Sopenharmony_ci * array should be SOF_TOKEN_COUNT. The unused elements in the array will be 19562306a36Sopenharmony_ci * initialized to 0. 19662306a36Sopenharmony_ci * @control_setup: Function pointer for setting up kcontrol IPC-specific data 19762306a36Sopenharmony_ci * @control_free: Function pointer for freeing kcontrol IPC-specific data 19862306a36Sopenharmony_ci * @pipeline_complete: Function pointer for pipeline complete IPC 19962306a36Sopenharmony_ci * @widget_setup: Function pointer for setting up setup in the DSP 20062306a36Sopenharmony_ci * @widget_free: Function pointer for freeing widget in the DSP 20162306a36Sopenharmony_ci * @dai_config: Function pointer for sending DAI config IPC to the DSP 20262306a36Sopenharmony_ci * @dai_get_clk: Function pointer for getting the DAI clock setting 20362306a36Sopenharmony_ci * @set_up_all_pipelines: Function pointer for setting up all topology pipelines 20462306a36Sopenharmony_ci * @tear_down_all_pipelines: Function pointer for tearing down all topology pipelines 20562306a36Sopenharmony_ci * @parse_manifest: Function pointer for ipc4 specific parsing of topology manifest 20662306a36Sopenharmony_ci * @link_setup: Function pointer for IPC-specific DAI link set up 20762306a36Sopenharmony_ci * 20862306a36Sopenharmony_ci * Note: function pointers (ops) are optional 20962306a36Sopenharmony_ci */ 21062306a36Sopenharmony_cistruct sof_ipc_tplg_ops { 21162306a36Sopenharmony_ci const struct sof_ipc_tplg_widget_ops *widget; 21262306a36Sopenharmony_ci const struct sof_ipc_tplg_control_ops *control; 21362306a36Sopenharmony_ci int (*route_setup)(struct snd_sof_dev *sdev, struct snd_sof_route *sroute); 21462306a36Sopenharmony_ci int (*route_free)(struct snd_sof_dev *sdev, struct snd_sof_route *sroute); 21562306a36Sopenharmony_ci const struct sof_token_info *token_list; 21662306a36Sopenharmony_ci int (*control_setup)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol); 21762306a36Sopenharmony_ci int (*control_free)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol); 21862306a36Sopenharmony_ci int (*pipeline_complete)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); 21962306a36Sopenharmony_ci int (*widget_setup)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); 22062306a36Sopenharmony_ci int (*widget_free)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); 22162306a36Sopenharmony_ci int (*dai_config)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, 22262306a36Sopenharmony_ci unsigned int flags, struct snd_sof_dai_config_data *data); 22362306a36Sopenharmony_ci int (*dai_get_clk)(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int clk_type); 22462306a36Sopenharmony_ci int (*set_up_all_pipelines)(struct snd_sof_dev *sdev, bool verify); 22562306a36Sopenharmony_ci int (*tear_down_all_pipelines)(struct snd_sof_dev *sdev, bool verify); 22662306a36Sopenharmony_ci int (*parse_manifest)(struct snd_soc_component *scomp, int index, 22762306a36Sopenharmony_ci struct snd_soc_tplg_manifest *man); 22862306a36Sopenharmony_ci int (*link_setup)(struct snd_sof_dev *sdev, struct snd_soc_dai_link *link); 22962306a36Sopenharmony_ci}; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci/** struct snd_sof_tuple - Tuple info 23262306a36Sopenharmony_ci * @token: Token ID 23362306a36Sopenharmony_ci * @value: union of a string or a u32 values 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_cistruct snd_sof_tuple { 23662306a36Sopenharmony_ci u32 token; 23762306a36Sopenharmony_ci union { 23862306a36Sopenharmony_ci u32 v; 23962306a36Sopenharmony_ci const char *s; 24062306a36Sopenharmony_ci } value; 24162306a36Sopenharmony_ci}; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci/* 24462306a36Sopenharmony_ci * List of SOF token ID's. The order of ID's does not matter as token arrays are looked up based on 24562306a36Sopenharmony_ci * the ID. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_cienum sof_tokens { 24862306a36Sopenharmony_ci SOF_PCM_TOKENS, 24962306a36Sopenharmony_ci SOF_PIPELINE_TOKENS, 25062306a36Sopenharmony_ci SOF_SCHED_TOKENS, 25162306a36Sopenharmony_ci SOF_ASRC_TOKENS, 25262306a36Sopenharmony_ci SOF_SRC_TOKENS, 25362306a36Sopenharmony_ci SOF_COMP_TOKENS, 25462306a36Sopenharmony_ci SOF_BUFFER_TOKENS, 25562306a36Sopenharmony_ci SOF_VOLUME_TOKENS, 25662306a36Sopenharmony_ci SOF_PROCESS_TOKENS, 25762306a36Sopenharmony_ci SOF_DAI_TOKENS, 25862306a36Sopenharmony_ci SOF_DAI_LINK_TOKENS, 25962306a36Sopenharmony_ci SOF_HDA_TOKENS, 26062306a36Sopenharmony_ci SOF_SSP_TOKENS, 26162306a36Sopenharmony_ci SOF_ALH_TOKENS, 26262306a36Sopenharmony_ci SOF_DMIC_TOKENS, 26362306a36Sopenharmony_ci SOF_DMIC_PDM_TOKENS, 26462306a36Sopenharmony_ci SOF_ESAI_TOKENS, 26562306a36Sopenharmony_ci SOF_SAI_TOKENS, 26662306a36Sopenharmony_ci SOF_AFE_TOKENS, 26762306a36Sopenharmony_ci SOF_CORE_TOKENS, 26862306a36Sopenharmony_ci SOF_COMP_EXT_TOKENS, 26962306a36Sopenharmony_ci SOF_IN_AUDIO_FORMAT_TOKENS, 27062306a36Sopenharmony_ci SOF_OUT_AUDIO_FORMAT_TOKENS, 27162306a36Sopenharmony_ci SOF_COPIER_DEEP_BUFFER_TOKENS, 27262306a36Sopenharmony_ci SOF_COPIER_TOKENS, 27362306a36Sopenharmony_ci SOF_AUDIO_FMT_NUM_TOKENS, 27462306a36Sopenharmony_ci SOF_COPIER_FORMAT_TOKENS, 27562306a36Sopenharmony_ci SOF_GAIN_TOKENS, 27662306a36Sopenharmony_ci SOF_ACPDMIC_TOKENS, 27762306a36Sopenharmony_ci SOF_ACPI2S_TOKENS, 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* this should be the last */ 28062306a36Sopenharmony_ci SOF_TOKEN_COUNT, 28162306a36Sopenharmony_ci}; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci/** 28462306a36Sopenharmony_ci * struct sof_topology_token - SOF topology token definition 28562306a36Sopenharmony_ci * @token: Token number 28662306a36Sopenharmony_ci * @type: Token type 28762306a36Sopenharmony_ci * @get_token: Function pointer to parse the token value and save it in a object 28862306a36Sopenharmony_ci * @offset: Offset within an object to save the token value into 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_cistruct sof_topology_token { 29162306a36Sopenharmony_ci u32 token; 29262306a36Sopenharmony_ci u32 type; 29362306a36Sopenharmony_ci int (*get_token)(void *elem, void *object, u32 offset); 29462306a36Sopenharmony_ci u32 offset; 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistruct sof_token_info { 29862306a36Sopenharmony_ci const char *name; 29962306a36Sopenharmony_ci const struct sof_topology_token *tokens; 30062306a36Sopenharmony_ci int count; 30162306a36Sopenharmony_ci}; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci/** 30462306a36Sopenharmony_ci * struct snd_sof_pcm_stream_pipeline_list - List of pipelines associated with a PCM stream 30562306a36Sopenharmony_ci * @count: number of pipeline widgets in the @pipe_widgets array 30662306a36Sopenharmony_ci * @pipelines: array of pipelines 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_cistruct snd_sof_pcm_stream_pipeline_list { 30962306a36Sopenharmony_ci u32 count; 31062306a36Sopenharmony_ci struct snd_sof_pipeline **pipelines; 31162306a36Sopenharmony_ci}; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci/* PCM stream, mapped to FW component */ 31462306a36Sopenharmony_cistruct snd_sof_pcm_stream { 31562306a36Sopenharmony_ci u32 comp_id; 31662306a36Sopenharmony_ci struct snd_dma_buffer page_table; 31762306a36Sopenharmony_ci struct sof_ipc_stream_posn posn; 31862306a36Sopenharmony_ci struct snd_pcm_substream *substream; 31962306a36Sopenharmony_ci struct snd_compr_stream *cstream; 32062306a36Sopenharmony_ci struct work_struct period_elapsed_work; 32162306a36Sopenharmony_ci struct snd_soc_dapm_widget_list *list; /* list of connected DAPM widgets */ 32262306a36Sopenharmony_ci bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */ 32362306a36Sopenharmony_ci /* 32462306a36Sopenharmony_ci * flag to indicate that the DSP pipelines should be kept 32562306a36Sopenharmony_ci * active or not while suspending the stream 32662306a36Sopenharmony_ci */ 32762306a36Sopenharmony_ci bool suspend_ignored; 32862306a36Sopenharmony_ci struct snd_sof_pcm_stream_pipeline_list pipeline_list; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* used by IPC implementation and core does not touch it */ 33162306a36Sopenharmony_ci void *private; 33262306a36Sopenharmony_ci}; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci/* ALSA SOF PCM device */ 33562306a36Sopenharmony_cistruct snd_sof_pcm { 33662306a36Sopenharmony_ci struct snd_soc_component *scomp; 33762306a36Sopenharmony_ci struct snd_soc_tplg_pcm pcm; 33862306a36Sopenharmony_ci struct snd_sof_pcm_stream stream[2]; 33962306a36Sopenharmony_ci struct list_head list; /* list in sdev pcm list */ 34062306a36Sopenharmony_ci struct snd_pcm_hw_params params[2]; 34162306a36Sopenharmony_ci bool prepared[2]; /* PCM_PARAMS set successfully */ 34262306a36Sopenharmony_ci}; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistruct snd_sof_led_control { 34562306a36Sopenharmony_ci unsigned int use_led; 34662306a36Sopenharmony_ci unsigned int direction; 34762306a36Sopenharmony_ci int led_value; 34862306a36Sopenharmony_ci}; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci/* ALSA SOF Kcontrol device */ 35162306a36Sopenharmony_cistruct snd_sof_control { 35262306a36Sopenharmony_ci struct snd_soc_component *scomp; 35362306a36Sopenharmony_ci const char *name; 35462306a36Sopenharmony_ci int comp_id; 35562306a36Sopenharmony_ci int min_volume_step; /* min volume step for volume_table */ 35662306a36Sopenharmony_ci int max_volume_step; /* max volume step for volume_table */ 35762306a36Sopenharmony_ci int num_channels; 35862306a36Sopenharmony_ci unsigned int access; 35962306a36Sopenharmony_ci int info_type; 36062306a36Sopenharmony_ci int index; /* pipeline ID */ 36162306a36Sopenharmony_ci void *priv; /* private data copied from topology */ 36262306a36Sopenharmony_ci size_t priv_size; /* size of private data */ 36362306a36Sopenharmony_ci size_t max_size; 36462306a36Sopenharmony_ci void *ipc_control_data; 36562306a36Sopenharmony_ci void *old_ipc_control_data; 36662306a36Sopenharmony_ci int max; /* applicable to volume controls */ 36762306a36Sopenharmony_ci u32 size; /* cdata size */ 36862306a36Sopenharmony_ci u32 *volume_table; /* volume table computed from tlv data*/ 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci struct list_head list; /* list in sdev control list */ 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci struct snd_sof_led_control led_ctl; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* if true, the control's data needs to be updated from Firmware */ 37562306a36Sopenharmony_ci bool comp_data_dirty; 37662306a36Sopenharmony_ci}; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci/** struct snd_sof_dai_link - DAI link info 37962306a36Sopenharmony_ci * @tuples: array of parsed tuples 38062306a36Sopenharmony_ci * @num_tuples: number of tuples in the tuples array 38162306a36Sopenharmony_ci * @link: Pointer to snd_soc_dai_link 38262306a36Sopenharmony_ci * @hw_configs: Pointer to hw configs in topology 38362306a36Sopenharmony_ci * @num_hw_configs: Number of hw configs in topology 38462306a36Sopenharmony_ci * @default_hw_cfg_id: Default hw config ID 38562306a36Sopenharmony_ci * @type: DAI type 38662306a36Sopenharmony_ci * @list: item in snd_sof_dev dai_link list 38762306a36Sopenharmony_ci */ 38862306a36Sopenharmony_cistruct snd_sof_dai_link { 38962306a36Sopenharmony_ci struct snd_sof_tuple *tuples; 39062306a36Sopenharmony_ci int num_tuples; 39162306a36Sopenharmony_ci struct snd_soc_dai_link *link; 39262306a36Sopenharmony_ci struct snd_soc_tplg_hw_config *hw_configs; 39362306a36Sopenharmony_ci int num_hw_configs; 39462306a36Sopenharmony_ci int default_hw_cfg_id; 39562306a36Sopenharmony_ci int type; 39662306a36Sopenharmony_ci struct list_head list; 39762306a36Sopenharmony_ci}; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci/* ASoC SOF DAPM widget */ 40062306a36Sopenharmony_cistruct snd_sof_widget { 40162306a36Sopenharmony_ci struct snd_soc_component *scomp; 40262306a36Sopenharmony_ci int comp_id; 40362306a36Sopenharmony_ci int pipeline_id; 40462306a36Sopenharmony_ci /* 40562306a36Sopenharmony_ci * the prepared flag is used to indicate that a widget has been prepared for getting set 40662306a36Sopenharmony_ci * up in the DSP. 40762306a36Sopenharmony_ci */ 40862306a36Sopenharmony_ci bool prepared; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci struct mutex setup_mutex; /* to protect the swidget setup and free operations */ 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci /* 41362306a36Sopenharmony_ci * use_count is protected by the PCM mutex held by the core and the 41462306a36Sopenharmony_ci * setup_mutex against non stream domain races (kcontrol access for 41562306a36Sopenharmony_ci * example) 41662306a36Sopenharmony_ci */ 41762306a36Sopenharmony_ci int use_count; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci int core; 42062306a36Sopenharmony_ci int id; /* id is the DAPM widget type */ 42162306a36Sopenharmony_ci /* 42262306a36Sopenharmony_ci * Instance ID is set dynamically when the widget gets set up in the FW. It should be 42362306a36Sopenharmony_ci * unique for each module type across all pipelines. This will not be used in SOF_IPC. 42462306a36Sopenharmony_ci */ 42562306a36Sopenharmony_ci int instance_id; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci /* 42862306a36Sopenharmony_ci * Flag indicating if the widget should be set up dynamically when a PCM is opened. 42962306a36Sopenharmony_ci * This flag is only set for the scheduler type widget in topology. During topology 43062306a36Sopenharmony_ci * loading, this flag is propagated to all the widgets belonging to the same pipeline. 43162306a36Sopenharmony_ci * When this flag is not set, a widget is set up at the time of topology loading 43262306a36Sopenharmony_ci * and retained until the DSP enters D3. It will need to be set up again when resuming 43362306a36Sopenharmony_ci * from D3. 43462306a36Sopenharmony_ci */ 43562306a36Sopenharmony_ci bool dynamic_pipeline_widget; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci struct snd_soc_dapm_widget *widget; 43862306a36Sopenharmony_ci struct list_head list; /* list in sdev widget list */ 43962306a36Sopenharmony_ci struct snd_sof_pipeline *spipe; 44062306a36Sopenharmony_ci void *module_info; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci const guid_t uuid; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci int num_tuples; 44562306a36Sopenharmony_ci struct snd_sof_tuple *tuples; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci /* 44862306a36Sopenharmony_ci * The allowed range for num_input/output_pins is [0, SOF_WIDGET_MAX_NUM_PINS]. 44962306a36Sopenharmony_ci * Widgets may have zero input or output pins, for example the tone widget has 45062306a36Sopenharmony_ci * zero input pins. 45162306a36Sopenharmony_ci */ 45262306a36Sopenharmony_ci u32 num_input_pins; 45362306a36Sopenharmony_ci u32 num_output_pins; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /* 45662306a36Sopenharmony_ci * The input/output pin binding array, it takes the form of 45762306a36Sopenharmony_ci * [widget_name_connected_to_pin0, widget_name_connected_to_pin1, ...], 45862306a36Sopenharmony_ci * with the index as the queue ID. 45962306a36Sopenharmony_ci * 46062306a36Sopenharmony_ci * The array is used for special pin binding. Note that even if there 46162306a36Sopenharmony_ci * is only one input/output pin requires special pin binding, pin binding 46262306a36Sopenharmony_ci * should be defined for all input/output pins in topology, for pin(s) that 46362306a36Sopenharmony_ci * are not used, give the value "NotConnected". 46462306a36Sopenharmony_ci * 46562306a36Sopenharmony_ci * If pin binding is not defined in topology, nothing to parse in the kernel, 46662306a36Sopenharmony_ci * input_pin_binding and output_pin_binding shall be NULL. 46762306a36Sopenharmony_ci */ 46862306a36Sopenharmony_ci char **input_pin_binding; 46962306a36Sopenharmony_ci char **output_pin_binding; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci struct ida output_queue_ida; 47262306a36Sopenharmony_ci struct ida input_queue_ida; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci void *private; /* core does not touch this */ 47562306a36Sopenharmony_ci}; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci/** struct snd_sof_pipeline - ASoC SOF pipeline 47862306a36Sopenharmony_ci * @pipe_widget: Pointer to the pipeline widget 47962306a36Sopenharmony_ci * @started_count: Count of number of PCM's that have started this pipeline 48062306a36Sopenharmony_ci * @paused_count: Count of number of PCM's that have started and have currently paused this 48162306a36Sopenharmony_ci pipeline 48262306a36Sopenharmony_ci * @complete: flag used to indicate that pipeline set up is complete. 48362306a36Sopenharmony_ci * @core_mask: Mask containing target cores for all modules in the pipeline 48462306a36Sopenharmony_ci * @list: List item in sdev pipeline_list 48562306a36Sopenharmony_ci */ 48662306a36Sopenharmony_cistruct snd_sof_pipeline { 48762306a36Sopenharmony_ci struct snd_sof_widget *pipe_widget; 48862306a36Sopenharmony_ci int started_count; 48962306a36Sopenharmony_ci int paused_count; 49062306a36Sopenharmony_ci int complete; 49162306a36Sopenharmony_ci unsigned long core_mask; 49262306a36Sopenharmony_ci struct list_head list; 49362306a36Sopenharmony_ci}; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci/* ASoC SOF DAPM route */ 49662306a36Sopenharmony_cistruct snd_sof_route { 49762306a36Sopenharmony_ci struct snd_soc_component *scomp; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci struct snd_soc_dapm_route *route; 50062306a36Sopenharmony_ci struct list_head list; /* list in sdev route list */ 50162306a36Sopenharmony_ci struct snd_sof_widget *src_widget; 50262306a36Sopenharmony_ci struct snd_sof_widget *sink_widget; 50362306a36Sopenharmony_ci bool setup; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci int src_queue_id; 50662306a36Sopenharmony_ci int dst_queue_id; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci void *private; 50962306a36Sopenharmony_ci}; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci/* ASoC DAI device */ 51262306a36Sopenharmony_cistruct snd_sof_dai { 51362306a36Sopenharmony_ci struct snd_soc_component *scomp; 51462306a36Sopenharmony_ci const char *name; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci int number_configs; 51762306a36Sopenharmony_ci int current_config; 51862306a36Sopenharmony_ci struct list_head list; /* list in sdev dai list */ 51962306a36Sopenharmony_ci /* core should not touch this */ 52062306a36Sopenharmony_ci const void *platform_private; 52162306a36Sopenharmony_ci void *private; 52262306a36Sopenharmony_ci}; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci/* 52562306a36Sopenharmony_ci * Kcontrols. 52662306a36Sopenharmony_ci */ 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ciint snd_sof_volume_get(struct snd_kcontrol *kcontrol, 52962306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 53062306a36Sopenharmony_ciint snd_sof_volume_put(struct snd_kcontrol *kcontrol, 53162306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 53262306a36Sopenharmony_ciint snd_sof_volume_info(struct snd_kcontrol *kcontrol, 53362306a36Sopenharmony_ci struct snd_ctl_elem_info *uinfo); 53462306a36Sopenharmony_ciint snd_sof_switch_get(struct snd_kcontrol *kcontrol, 53562306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 53662306a36Sopenharmony_ciint snd_sof_switch_put(struct snd_kcontrol *kcontrol, 53762306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 53862306a36Sopenharmony_ciint snd_sof_enum_get(struct snd_kcontrol *kcontrol, 53962306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 54062306a36Sopenharmony_ciint snd_sof_enum_put(struct snd_kcontrol *kcontrol, 54162306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 54262306a36Sopenharmony_ciint snd_sof_bytes_get(struct snd_kcontrol *kcontrol, 54362306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 54462306a36Sopenharmony_ciint snd_sof_bytes_put(struct snd_kcontrol *kcontrol, 54562306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 54662306a36Sopenharmony_ciint snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, 54762306a36Sopenharmony_ci const unsigned int __user *binary_data, 54862306a36Sopenharmony_ci unsigned int size); 54962306a36Sopenharmony_ciint snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, 55062306a36Sopenharmony_ci unsigned int __user *binary_data, 55162306a36Sopenharmony_ci unsigned int size); 55262306a36Sopenharmony_ciint snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data, 55362306a36Sopenharmony_ci unsigned int size); 55462306a36Sopenharmony_civoid snd_sof_control_notify(struct snd_sof_dev *sdev, 55562306a36Sopenharmony_ci struct sof_ipc_ctrl_data *cdata); 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci/* 55862306a36Sopenharmony_ci * Topology. 55962306a36Sopenharmony_ci * There is no snd_sof_free_topology since topology components will 56062306a36Sopenharmony_ci * be freed by snd_soc_unregister_component, 56162306a36Sopenharmony_ci */ 56262306a36Sopenharmony_ciint snd_sof_load_topology(struct snd_soc_component *scomp, const char *file); 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci/* 56562306a36Sopenharmony_ci * Stream IPC 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ciint snd_sof_ipc_stream_posn(struct snd_soc_component *scomp, 56862306a36Sopenharmony_ci struct snd_sof_pcm *spcm, int direction, 56962306a36Sopenharmony_ci struct sof_ipc_stream_posn *posn); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistruct snd_sof_widget *snd_sof_find_swidget(struct snd_soc_component *scomp, 57262306a36Sopenharmony_ci const char *name); 57362306a36Sopenharmony_cistruct snd_sof_widget * 57462306a36Sopenharmony_cisnd_sof_find_swidget_sname(struct snd_soc_component *scomp, 57562306a36Sopenharmony_ci const char *pcm_name, int dir); 57662306a36Sopenharmony_cistruct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, 57762306a36Sopenharmony_ci const char *name); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_cistatic inline 58062306a36Sopenharmony_cistruct snd_sof_pcm *snd_sof_find_spcm_dai(struct snd_soc_component *scomp, 58162306a36Sopenharmony_ci struct snd_soc_pcm_runtime *rtd) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 58462306a36Sopenharmony_ci struct snd_sof_pcm *spcm; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci list_for_each_entry(spcm, &sdev->pcm_list, list) { 58762306a36Sopenharmony_ci if (le32_to_cpu(spcm->pcm.dai_id) == rtd->dai_link->id) 58862306a36Sopenharmony_ci return spcm; 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci return NULL; 59262306a36Sopenharmony_ci} 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_cistruct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_soc_component *scomp, 59562306a36Sopenharmony_ci const char *name); 59662306a36Sopenharmony_cistruct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp, 59762306a36Sopenharmony_ci unsigned int comp_id, 59862306a36Sopenharmony_ci int *direction); 59962306a36Sopenharmony_civoid snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream); 60062306a36Sopenharmony_civoid snd_sof_pcm_init_elapsed_work(struct work_struct *work); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) 60362306a36Sopenharmony_civoid snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream); 60462306a36Sopenharmony_civoid snd_sof_compr_init_elapsed_work(struct work_struct *work); 60562306a36Sopenharmony_ci#else 60662306a36Sopenharmony_cistatic inline void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream) { } 60762306a36Sopenharmony_cistatic inline void snd_sof_compr_init_elapsed_work(struct work_struct *work) { } 60862306a36Sopenharmony_ci#endif 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci/* DAI link fixup */ 61162306a36Sopenharmony_ciint sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci/* PM */ 61462306a36Sopenharmony_cibool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev); 61562306a36Sopenharmony_cibool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci/* Machine driver enumeration */ 61862306a36Sopenharmony_ciint sof_machine_register(struct snd_sof_dev *sdev, void *pdata); 61962306a36Sopenharmony_civoid sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ciint sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); 62262306a36Sopenharmony_ciint sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); 62362306a36Sopenharmony_ciint sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsource, 62462306a36Sopenharmony_ci struct snd_soc_dapm_widget *wsink); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci/* PCM */ 62762306a36Sopenharmony_ciint sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, 62862306a36Sopenharmony_ci struct snd_pcm_hw_params *fe_params, 62962306a36Sopenharmony_ci struct snd_sof_platform_stream_params *platform_params, 63062306a36Sopenharmony_ci int dir); 63162306a36Sopenharmony_ciint sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir); 63262306a36Sopenharmony_ciint sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, struct snd_sof_dev *sdev, 63362306a36Sopenharmony_ci struct snd_sof_pcm *spcm); 63462306a36Sopenharmony_ciint sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, 63562306a36Sopenharmony_ci struct snd_sof_pcm *spcm, int dir, bool free_widget_list); 63662306a36Sopenharmony_ciint get_token_u32(void *elem, void *object, u32 offset); 63762306a36Sopenharmony_ciint get_token_u16(void *elem, void *object, u32 offset); 63862306a36Sopenharmony_ciint get_token_comp_format(void *elem, void *object, u32 offset); 63962306a36Sopenharmony_ciint get_token_dai_type(void *elem, void *object, u32 offset); 64062306a36Sopenharmony_ciint get_token_uuid(void *elem, void *object, u32 offset); 64162306a36Sopenharmony_ciint get_token_string(void *elem, void *object, u32 offset); 64262306a36Sopenharmony_ciint sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum sof_tokens token_id, 64362306a36Sopenharmony_ci struct snd_sof_tuple *tuples, int num_tuples, 64462306a36Sopenharmony_ci size_t object_size, int token_instance_num); 64562306a36Sopenharmony_ciu32 vol_compute_gain(u32 value, int *tlv); 64662306a36Sopenharmony_ci#endif 647