1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
6 * Copyright(c) 2019 Intel Corporation. All rights reserved.
8 * Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
11 #ifndef __SOUND_SOC_SOF_AUDIO_H
12 #define __SOUND_SOC_SOF_AUDIO_H
14 #include <linux/workqueue.h>
16 #include <sound/soc.h>
17 #include <sound/control.h>
18 #include <sound/sof/stream.h> /* needs to be included before control.h */
19 #include <sound/sof/control.h>
20 #include <sound/sof/dai.h>
21 #include <sound/sof/topology.h>
24 #define SOF_AUDIO_PCM_DRV_NAME "sof-audio-component"
26 /* max number of FE PCMs before BEs */
27 #define SOF_BE_PCM_BASE 16
29 #define DMA_CHAN_INVALID 0xFFFFFFFF
31 #define WIDGET_IS_DAI(id) ((id) == snd_soc_dapm_dai_in || (id) == snd_soc_dapm_dai_out)
34 * Volume fractional word length define to 16 sets
35 * the volume linear gain value to use Qx.16 format
39 struct snd_sof_widget;
41 struct snd_sof_control;
44 * struct sof_ipc_tplg_widget_ops - IPC-specific ops for topology widgets
45 * @ipc_setup: Function pointer for setting up widget IPC params
46 * @ipc_free: Function pointer for freeing widget IPC params
47 * @token_list: List of token ID's that should be parsed for the widget
48 * @token_list_size: number of elements in token_list
49 * @bind_event: Function pointer for binding events to the widget
51 struct sof_ipc_tplg_widget_ops {
52 int (*ipc_setup)(struct snd_sof_widget *swidget);
53 void (*ipc_free)(struct snd_sof_widget *swidget);
54 enum sof_tokens *token_list;
56 int (*bind_event)(struct snd_soc_component *scomp, struct snd_sof_widget *swidget,
61 * struct sof_ipc_tplg_ops - IPC-specific topology ops
62 * @widget: Array of pointers to IPC-specific ops for widgets. This should always be of size
63 * SND_SOF_DAPM_TYPE_COUNT i.e one per widget type. Unsupported widget types will be
65 * @route_setup: Function pointer for setting up pipeline connections
66 * @token_list: List of all tokens supported by the IPC version. The size of the token_list
67 * array should be SOF_TOKEN_COUNT. The unused elements in the array will be
69 * @control_setup: Function pointer for setting up kcontrol IPC-specific data
70 * @control_free: Function pointer for freeing kcontrol IPC-specific data
72 struct sof_ipc_tplg_ops {
73 const struct sof_ipc_tplg_widget_ops *widget;
74 int (*route_setup)(struct snd_sof_dev *sdev, struct snd_sof_route *sroute);
75 const struct sof_token_info *token_list;
76 int (*control_setup)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol);
77 int (*control_free)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol);
80 /** struct snd_sof_tuple - Tuple info
82 * @value: union of a string or a u32 values
84 struct snd_sof_tuple {
93 * List of SOF token ID's. The order of ID's does not matter as token arrays are looked up based on
119 /* this should be the last */
124 * struct sof_topology_token - SOF topology token definition
125 * @token: Token number
127 * @get_token: Function pointer to parse the token value and save it in a object
128 * @offset: Offset within an object to save the token value into
130 struct sof_topology_token {
133 int (*get_token)(void *elem, void *object, u32 offset);
137 struct sof_token_info {
139 const struct sof_topology_token *tokens;
143 /* PCM stream, mapped to FW component */
144 struct snd_sof_pcm_stream {
146 struct snd_dma_buffer page_table;
147 struct sof_ipc_stream_posn posn;
148 struct snd_pcm_substream *substream;
149 struct snd_compr_stream *cstream;
150 struct work_struct period_elapsed_work;
151 struct snd_soc_dapm_widget_list *list; /* list of connected DAPM widgets */
152 bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */
154 * flag to indicate that the DSP pipelines should be kept
155 * active or not while suspending the stream
157 bool suspend_ignored;
160 /* ALSA SOF PCM device */
162 struct snd_soc_component *scomp;
163 struct snd_soc_tplg_pcm pcm;
164 struct snd_sof_pcm_stream stream[2];
165 struct list_head list; /* list in sdev pcm list */
166 struct snd_pcm_hw_params params[2];
167 bool prepared[2]; /* PCM_PARAMS set successfully */
170 struct snd_sof_led_control {
171 unsigned int use_led;
172 unsigned int direction;
176 /* ALSA SOF Kcontrol device */
177 struct snd_sof_control {
178 struct snd_soc_component *scomp;
181 int min_volume_step; /* min volume step for volume_table */
182 int max_volume_step; /* max volume step for volume_table */
185 u32 readback_offset; /* offset to mmapped data if used */
187 int index; /* pipeline ID */
188 void *priv; /* private data copied from topology */
189 size_t priv_size; /* size of private data */
191 void *ipc_control_data;
192 int max; /* applicable to volume controls */
193 u32 size; /* cdata size */
194 u32 *volume_table; /* volume table computed from tlv data*/
196 struct list_head list; /* list in sdev control list */
198 struct snd_sof_led_control led_ctl;
200 /* if true, the control's data needs to be updated from Firmware */
201 bool comp_data_dirty;
204 /** struct snd_sof_dai_link - DAI link info
205 * @tuples: array of parsed tuples
206 * @num_tuples: number of tuples in the tuples array
207 * @link: Pointer to snd_soc_dai_link
208 * @hw_configs: Pointer to hw configs in topology
209 * @num_hw_configs: Number of hw configs in topology
210 * @default_hw_cfg_id: Default hw config ID
212 * @list: item in snd_sof_dev dai_link list
214 struct snd_sof_dai_link {
215 struct snd_sof_tuple *tuples;
217 struct snd_soc_dai_link *link;
218 struct snd_soc_tplg_hw_config *hw_configs;
220 int default_hw_cfg_id;
222 struct list_head list;
225 /* ASoC SOF DAPM widget */
226 struct snd_sof_widget {
227 struct snd_soc_component *scomp;
231 int use_count; /* use_count will be protected by the PCM mutex held by the core */
236 * Flag indicating if the widget should be set up dynamically when a PCM is opened.
237 * This flag is only set for the scheduler type widget in topology. During topology
238 * loading, this flag is propagated to all the widgets belonging to the same pipeline.
239 * When this flag is not set, a widget is set up at the time of topology loading
240 * and retained until the DSP enters D3. It will need to be set up again when resuming
243 bool dynamic_pipeline_widget;
245 struct snd_soc_dapm_widget *widget;
246 struct list_head list; /* list in sdev widget list */
247 struct snd_sof_widget *pipe_widget;
252 struct snd_sof_tuple *tuples;
254 void *private; /* core does not touch this */
257 /* ASoC SOF DAPM route */
258 struct snd_sof_route {
259 struct snd_soc_component *scomp;
261 struct snd_soc_dapm_route *route;
262 struct list_head list; /* list in sdev route list */
263 struct snd_sof_widget *src_widget;
264 struct snd_sof_widget *sink_widget;
270 /* ASoC DAI device */
272 struct snd_soc_component *scomp;
277 bool configured; /* DAI configured during BE hw_params */
278 struct list_head list; /* list in sdev dai list */
286 int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
287 struct snd_ctl_elem_value *ucontrol);
288 int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
289 struct snd_ctl_elem_value *ucontrol);
290 int snd_sof_volume_info(struct snd_kcontrol *kcontrol,
291 struct snd_ctl_elem_info *uinfo);
292 int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
293 struct snd_ctl_elem_value *ucontrol);
294 int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
295 struct snd_ctl_elem_value *ucontrol);
296 int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
297 struct snd_ctl_elem_value *ucontrol);
298 int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
299 struct snd_ctl_elem_value *ucontrol);
300 int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
301 struct snd_ctl_elem_value *ucontrol);
302 int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
303 struct snd_ctl_elem_value *ucontrol);
304 int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
305 const unsigned int __user *binary_data,
307 int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
308 unsigned int __user *binary_data,
310 int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data,
312 void snd_sof_control_notify(struct snd_sof_dev *sdev,
313 struct sof_ipc_ctrl_data *cdata);
317 * There is no snd_sof_free_topology since topology components will
318 * be freed by snd_soc_unregister_component,
320 int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file);
321 int snd_sof_complete_pipeline(struct snd_sof_dev *sdev,
322 struct snd_sof_widget *swidget);
327 int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp,
328 struct snd_sof_pcm *spcm, int direction,
329 struct sof_ipc_stream_posn *posn);
331 struct snd_sof_widget *snd_sof_find_swidget(struct snd_soc_component *scomp,
333 struct snd_sof_widget *
334 snd_sof_find_swidget_sname(struct snd_soc_component *scomp,
335 const char *pcm_name, int dir);
336 struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp,
340 struct snd_sof_pcm *snd_sof_find_spcm_dai(struct snd_soc_component *scomp,
341 struct snd_soc_pcm_runtime *rtd)
343 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
345 struct snd_sof_pcm *spcm = NULL;
347 list_for_each_entry(spcm, &sdev->pcm_list, list) {
348 if (le32_to_cpu(spcm->pcm.dai_id) == rtd->dai_link->id)
355 struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_soc_component *scomp,
357 struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp,
358 unsigned int comp_id,
360 void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream);
361 void snd_sof_pcm_init_elapsed_work(struct work_struct *work);
363 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS)
364 void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream);
365 void snd_sof_compr_init_elapsed_work(struct work_struct *work);
367 static inline void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream) { }
368 static inline void snd_sof_compr_init_elapsed_work(struct work_struct *work) { }
374 int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set);
377 int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params);
380 int sof_set_up_pipelines(struct snd_sof_dev *sdev, bool verify);
381 int sof_tear_down_pipelines(struct snd_sof_dev *sdev, bool verify);
382 int sof_set_hw_params_upon_resume(struct device *dev);
383 bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev);
384 bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev);
386 /* Machine driver enumeration */
387 int sof_machine_register(struct snd_sof_dev *sdev, void *pdata);
388 void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata);
390 int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget);
391 int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget);
394 int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir);
395 int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir);
396 int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, struct snd_sof_dev *sdev,
397 struct snd_sof_pcm *spcm);
398 int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
399 struct snd_sof_pcm *spcm, int dir, bool free_widget_list);
400 int get_token_u32(void *elem, void *object, u32 offset);
401 int get_token_u16(void *elem, void *object, u32 offset);
402 int get_token_comp_format(void *elem, void *object, u32 offset);
403 int get_token_dai_type(void *elem, void *object, u32 offset);
404 int get_token_uuid(void *elem, void *object, u32 offset);
405 int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum sof_tokens token_id,
406 struct snd_sof_tuple *tuples, int num_tuples,
407 size_t object_size, int token_instance_num);