1 | /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ |
2 | /* |
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. |
5 | * |
6 | * Copyright(c) 2019 Intel Corporation. All rights reserved. |
7 | * |
8 | * Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> |
9 | */ |
10 | |
11 | #ifndef __SOUND_SOC_SOF_AUDIO_H |
12 | #define __SOUND_SOC_SOF_AUDIO_H |
13 | |
14 | #include <linux/workqueue.h> |
15 | |
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> |
22 | #include "sof-priv.h" |
23 | |
24 | #define SOF_AUDIO_PCM_DRV_NAME "sof-audio-component" |
25 | |
26 | /* |
27 | * The ipc4 firmware only supports up to 8 sink or source pins |
28 | * per widget, because only 3 bits are used for queue(pin) ID |
29 | * in ipc4 protocol. |
30 | */ |
31 | #define SOF_WIDGET_MAX_NUM_PINS 8 |
32 | |
33 | /* Widget pin type */ |
34 | #define SOF_PIN_TYPE_INPUT 0 |
35 | #define SOF_PIN_TYPE_OUTPUT 1 |
36 | |
37 | /* max number of FE PCMs before BEs */ |
38 | #define SOF_BE_PCM_BASE 16 |
39 | |
40 | #define DMA_CHAN_INVALID 0xFFFFFFFF |
41 | |
42 | #define WIDGET_IS_DAI(id) ((id) == snd_soc_dapm_dai_in || (id) == snd_soc_dapm_dai_out) |
43 | #define WIDGET_IS_AIF(id) ((id) == snd_soc_dapm_aif_in || (id) == snd_soc_dapm_aif_out) |
44 | #define WIDGET_IS_AIF_OR_DAI(id) (WIDGET_IS_DAI(id) || WIDGET_IS_AIF(id)) |
45 | #define WIDGET_IS_COPIER(id) (WIDGET_IS_AIF_OR_DAI(id) || (id) == snd_soc_dapm_buffer) |
46 | |
47 | #define SOF_DAI_CLK_INTEL_SSP_MCLK 0 |
48 | #define SOF_DAI_CLK_INTEL_SSP_BCLK 1 |
49 | |
50 | enum sof_widget_op { |
51 | SOF_WIDGET_PREPARE, |
52 | SOF_WIDGET_SETUP, |
53 | SOF_WIDGET_FREE, |
54 | SOF_WIDGET_UNPREPARE, |
55 | }; |
56 | |
57 | /* |
58 | * Volume fractional word length define to 16 sets |
59 | * the volume linear gain value to use Qx.16 format |
60 | */ |
61 | #define VOLUME_FWL 16 |
62 | |
63 | #define SOF_TLV_ITEMS 3 |
64 | |
65 | static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size) |
66 | { |
67 | if (value >= size) |
68 | return volume_map[size - 1]; |
69 | |
70 | return volume_map[value]; |
71 | } |
72 | |
73 | static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size) |
74 | { |
75 | int i; |
76 | |
77 | for (i = 0; i < size; i++) { |
78 | if (volume_map[i] >= value) |
79 | return i; |
80 | } |
81 | |
82 | return i - 1; |
83 | } |
84 | |
85 | struct snd_sof_widget; |
86 | struct snd_sof_route; |
87 | struct snd_sof_control; |
88 | struct snd_sof_dai; |
89 | struct snd_sof_pcm; |
90 | |
91 | struct snd_sof_dai_config_data { |
92 | int dai_index; |
93 | int dai_data; /* contains DAI-specific information */ |
94 | }; |
95 | |
96 | /** |
97 | * struct sof_ipc_pcm_ops - IPC-specific PCM ops |
98 | * @hw_params: Function pointer for hw_params |
99 | * @hw_free: Function pointer for hw_free |
100 | * @trigger: Function pointer for trigger |
101 | * @dai_link_fixup: Function pointer for DAI link fixup |
102 | * @pcm_setup: Function pointer for IPC-specific PCM set up that can be used for allocating |
103 | * additional memory in the SOF PCM stream structure |
104 | * @pcm_free: Function pointer for PCM free that can be used for freeing any |
105 | * additional memory in the SOF PCM stream structure |
106 | * @pointer: Function pointer for pcm pointer |
107 | * Note: the @pointer callback may return -EOPNOTSUPP which should be |
108 | * handled in a same way as if the callback is not provided |
109 | * @delay: Function pointer for pcm delay reporting |
110 | * @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the |
111 | * STOP pcm trigger |
112 | * @ipc_first_on_start: Send IPC before invoking platform trigger during |
113 | * START/PAUSE_RELEASE triggers |
114 | * @platform_stop_during_hw_free: Invoke the platform trigger during hw_free. This is needed for |
115 | * IPC4 where a pipeline is only paused during stop/pause/suspend |
116 | * triggers. The FW keeps the host DMA running in this case and |
117 | * therefore the host must do the same and should stop the DMA during |
118 | * hw_free. |
119 | */ |
120 | struct sof_ipc_pcm_ops { |
121 | int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, |
122 | struct snd_pcm_hw_params *params, |
123 | struct snd_sof_platform_stream_params *platform_params); |
124 | int (*hw_free)(struct snd_soc_component *component, struct snd_pcm_substream *substream); |
125 | int (*trigger)(struct snd_soc_component *component, struct snd_pcm_substream *substream, |
126 | int cmd); |
127 | int (*dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); |
128 | int (*pcm_setup)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm); |
129 | void (*pcm_free)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm); |
130 | int (*pointer)(struct snd_soc_component *component, |
131 | struct snd_pcm_substream *substream, |
132 | snd_pcm_uframes_t *pointer); |
133 | snd_pcm_sframes_t (*delay)(struct snd_soc_component *component, |
134 | struct snd_pcm_substream *substream); |
135 | bool reset_hw_params_during_stop; |
136 | bool ipc_first_on_start; |
137 | bool platform_stop_during_hw_free; |
138 | }; |
139 | |
140 | /** |
141 | * struct sof_ipc_tplg_control_ops - IPC-specific ops for topology kcontrol IO |
142 | */ |
143 | struct sof_ipc_tplg_control_ops { |
144 | bool (*volume_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); |
145 | int (*volume_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); |
146 | bool (*switch_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); |
147 | int (*switch_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); |
148 | bool (*enum_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); |
149 | int (*enum_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); |
150 | int (*bytes_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); |
151 | int (*bytes_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); |
152 | int (*bytes_ext_get)(struct snd_sof_control *scontrol, |
153 | const unsigned int __user *binary_data, unsigned int size); |
154 | int (*bytes_ext_volatile_get)(struct snd_sof_control *scontrol, |
155 | const unsigned int __user *binary_data, unsigned int size); |
156 | int (*bytes_ext_put)(struct snd_sof_control *scontrol, |
157 | const unsigned int __user *binary_data, unsigned int size); |
158 | /* update control data based on notification from the DSP */ |
159 | void (*update)(struct snd_sof_dev *sdev, void *ipc_control_message); |
160 | /* Optional callback to setup kcontrols associated with an swidget */ |
161 | int (*widget_kcontrol_setup)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); |
162 | /* mandatory callback to set up volume table for volume kcontrols */ |
163 | int (*set_up_volume_table)(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS], |
164 | int size); |
165 | }; |
166 | |
167 | /** |
168 | * struct sof_ipc_tplg_widget_ops - IPC-specific ops for topology widgets |
169 | * @ipc_setup: Function pointer for setting up widget IPC params |
170 | * @ipc_free: Function pointer for freeing widget IPC params |
171 | * @token_list: List of token ID's that should be parsed for the widget |
172 | * @token_list_size: number of elements in token_list |
173 | * @bind_event: Function pointer for binding events to the widget |
174 | * @ipc_prepare: Optional op for preparing a widget for set up |
175 | * @ipc_unprepare: Optional op for unpreparing a widget |
176 | */ |
177 | struct sof_ipc_tplg_widget_ops { |
178 | int (*ipc_setup)(struct snd_sof_widget *swidget); |
179 | void (*ipc_free)(struct snd_sof_widget *swidget); |
180 | enum sof_tokens *token_list; |
181 | int token_list_size; |
182 | int (*bind_event)(struct snd_soc_component *scomp, struct snd_sof_widget *swidget, |
183 | u16 event_type); |
184 | int (*ipc_prepare)(struct snd_sof_widget *swidget, |
185 | struct snd_pcm_hw_params *fe_params, |
186 | struct snd_sof_platform_stream_params *platform_params, |
187 | struct snd_pcm_hw_params *source_params, int dir); |
188 | void (*ipc_unprepare)(struct snd_sof_widget *swidget); |
189 | }; |
190 | |
191 | /** |
192 | * struct sof_ipc_tplg_ops - IPC-specific topology ops |
193 | * @widget: Array of pointers to IPC-specific ops for widgets. This should always be of size |
194 | * SND_SOF_DAPM_TYPE_COUNT i.e one per widget type. Unsupported widget types will be |
195 | * initialized to 0. |
196 | * @control: Pointer to the IPC-specific ops for topology kcontrol IO |
197 | * @route_setup: Function pointer for setting up pipeline connections |
198 | * @route_free: Function pointer for freeing pipeline connections. |
199 | * @token_list: List of all tokens supported by the IPC version. The size of the token_list |
200 | * array should be SOF_TOKEN_COUNT. The unused elements in the array will be |
201 | * initialized to 0. |
202 | * @control_setup: Function pointer for setting up kcontrol IPC-specific data |
203 | * @control_free: Function pointer for freeing kcontrol IPC-specific data |
204 | * @pipeline_complete: Function pointer for pipeline complete IPC |
205 | * @widget_setup: Function pointer for setting up setup in the DSP |
206 | * @widget_free: Function pointer for freeing widget in the DSP |
207 | * @dai_config: Function pointer for sending DAI config IPC to the DSP |
208 | * @dai_get_clk: Function pointer for getting the DAI clock setting |
209 | * @set_up_all_pipelines: Function pointer for setting up all topology pipelines |
210 | * @tear_down_all_pipelines: Function pointer for tearing down all topology pipelines |
211 | * @parse_manifest: Function pointer for ipc4 specific parsing of topology manifest |
212 | * @link_setup: Function pointer for IPC-specific DAI link set up |
213 | * |
214 | * Note: function pointers (ops) are optional |
215 | */ |
216 | struct sof_ipc_tplg_ops { |
217 | const struct sof_ipc_tplg_widget_ops *widget; |
218 | const struct sof_ipc_tplg_control_ops *control; |
219 | int (*route_setup)(struct snd_sof_dev *sdev, struct snd_sof_route *sroute); |
220 | int (*route_free)(struct snd_sof_dev *sdev, struct snd_sof_route *sroute); |
221 | const struct sof_token_info *token_list; |
222 | int (*control_setup)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol); |
223 | int (*control_free)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol); |
224 | int (*pipeline_complete)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); |
225 | int (*widget_setup)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); |
226 | int (*widget_free)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); |
227 | int (*dai_config)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, |
228 | unsigned int flags, struct snd_sof_dai_config_data *data); |
229 | int (*dai_get_clk)(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int clk_type); |
230 | int (*set_up_all_pipelines)(struct snd_sof_dev *sdev, bool verify); |
231 | int (*tear_down_all_pipelines)(struct snd_sof_dev *sdev, bool verify); |
232 | int (*parse_manifest)(struct snd_soc_component *scomp, int index, |
233 | struct snd_soc_tplg_manifest *man); |
234 | int (*link_setup)(struct snd_sof_dev *sdev, struct snd_soc_dai_link *link); |
235 | }; |
236 | |
237 | /** struct snd_sof_tuple - Tuple info |
238 | * @token: Token ID |
239 | * @value: union of a string or a u32 values |
240 | */ |
241 | struct snd_sof_tuple { |
242 | u32 token; |
243 | union { |
244 | u32 v; |
245 | const char *s; |
246 | } value; |
247 | }; |
248 | |
249 | /* |
250 | * List of SOF token ID's. The order of ID's does not matter as token arrays are looked up based on |
251 | * the ID. |
252 | */ |
253 | enum sof_tokens { |
254 | SOF_PCM_TOKENS, |
255 | SOF_PIPELINE_TOKENS, |
256 | SOF_SCHED_TOKENS, |
257 | SOF_ASRC_TOKENS, |
258 | SOF_SRC_TOKENS, |
259 | SOF_COMP_TOKENS, |
260 | SOF_BUFFER_TOKENS, |
261 | SOF_VOLUME_TOKENS, |
262 | SOF_PROCESS_TOKENS, |
263 | SOF_DAI_TOKENS, |
264 | SOF_DAI_LINK_TOKENS, |
265 | SOF_HDA_TOKENS, |
266 | SOF_SSP_TOKENS, |
267 | SOF_ALH_TOKENS, |
268 | SOF_DMIC_TOKENS, |
269 | SOF_DMIC_PDM_TOKENS, |
270 | SOF_ESAI_TOKENS, |
271 | SOF_SAI_TOKENS, |
272 | SOF_AFE_TOKENS, |
273 | SOF_CORE_TOKENS, |
274 | SOF_COMP_EXT_TOKENS, |
275 | SOF_IN_AUDIO_FORMAT_TOKENS, |
276 | SOF_OUT_AUDIO_FORMAT_TOKENS, |
277 | SOF_COPIER_DEEP_BUFFER_TOKENS, |
278 | SOF_COPIER_TOKENS, |
279 | SOF_AUDIO_FMT_NUM_TOKENS, |
280 | SOF_COPIER_FORMAT_TOKENS, |
281 | SOF_GAIN_TOKENS, |
282 | SOF_ACPDMIC_TOKENS, |
283 | SOF_ACPI2S_TOKENS, |
284 | SOF_MICFIL_TOKENS, |
285 | SOF_ACP_SDW_TOKENS, |
286 | |
287 | /* this should be the last */ |
288 | SOF_TOKEN_COUNT, |
289 | }; |
290 | |
291 | /** |
292 | * struct sof_topology_token - SOF topology token definition |
293 | * @token: Token number |
294 | * @type: Token type |
295 | * @get_token: Function pointer to parse the token value and save it in a object |
296 | * @offset: Offset within an object to save the token value into |
297 | */ |
298 | struct sof_topology_token { |
299 | u32 token; |
300 | u32 type; |
301 | int (*get_token)(void *elem, void *object, u32 offset); |
302 | u32 offset; |
303 | }; |
304 | |
305 | struct sof_token_info { |
306 | const char *name; |
307 | const struct sof_topology_token *tokens; |
308 | int count; |
309 | }; |
310 | |
311 | /** |
312 | * struct snd_sof_pcm_stream_pipeline_list - List of pipelines associated with a PCM stream |
313 | * @count: number of pipeline widgets in the @pipe_widgets array |
314 | * @pipelines: array of pipelines |
315 | */ |
316 | struct snd_sof_pcm_stream_pipeline_list { |
317 | u32 count; |
318 | struct snd_sof_pipeline **pipelines; |
319 | }; |
320 | |
321 | /* PCM stream, mapped to FW component */ |
322 | struct snd_sof_pcm_stream { |
323 | u32 comp_id; |
324 | struct snd_dma_buffer page_table; |
325 | struct sof_ipc_stream_posn posn; |
326 | struct snd_pcm_substream *substream; |
327 | struct snd_compr_stream *cstream; |
328 | struct work_struct period_elapsed_work; |
329 | struct snd_soc_dapm_widget_list *list; /* list of connected DAPM widgets */ |
330 | bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */ |
331 | unsigned int dsp_max_burst_size_in_ms; /* The maximum size of the host DMA burst in ms */ |
332 | /* |
333 | * flag to indicate that the DSP pipelines should be kept |
334 | * active or not while suspending the stream |
335 | */ |
336 | bool suspend_ignored; |
337 | struct snd_sof_pcm_stream_pipeline_list pipeline_list; |
338 | |
339 | /* used by IPC implementation and core does not touch it */ |
340 | void *private; |
341 | }; |
342 | |
343 | /* ALSA SOF PCM device */ |
344 | struct snd_sof_pcm { |
345 | struct snd_soc_component *scomp; |
346 | struct snd_soc_tplg_pcm pcm; |
347 | struct snd_sof_pcm_stream stream[2]; |
348 | struct list_head list; /* list in sdev pcm list */ |
349 | struct snd_pcm_hw_params params[2]; |
350 | bool prepared[2]; /* PCM_PARAMS set successfully */ |
351 | }; |
352 | |
353 | struct snd_sof_led_control { |
354 | unsigned int use_led; |
355 | unsigned int direction; |
356 | int led_value; |
357 | }; |
358 | |
359 | /* ALSA SOF Kcontrol device */ |
360 | struct snd_sof_control { |
361 | struct snd_soc_component *scomp; |
362 | const char *name; |
363 | int comp_id; |
364 | int min_volume_step; /* min volume step for volume_table */ |
365 | int max_volume_step; /* max volume step for volume_table */ |
366 | int num_channels; |
367 | unsigned int access; |
368 | int info_type; |
369 | int index; /* pipeline ID */ |
370 | void *priv; /* private data copied from topology */ |
371 | size_t priv_size; /* size of private data */ |
372 | size_t max_size; |
373 | void *ipc_control_data; |
374 | void *old_ipc_control_data; |
375 | int max; /* applicable to volume controls */ |
376 | u32 size; /* cdata size */ |
377 | u32 *volume_table; /* volume table computed from tlv data*/ |
378 | |
379 | struct list_head list; /* list in sdev control list */ |
380 | |
381 | struct snd_sof_led_control led_ctl; |
382 | |
383 | /* if true, the control's data needs to be updated from Firmware */ |
384 | bool comp_data_dirty; |
385 | }; |
386 | |
387 | /** struct snd_sof_dai_link - DAI link info |
388 | * @tuples: array of parsed tuples |
389 | * @num_tuples: number of tuples in the tuples array |
390 | * @link: Pointer to snd_soc_dai_link |
391 | * @hw_configs: Pointer to hw configs in topology |
392 | * @num_hw_configs: Number of hw configs in topology |
393 | * @default_hw_cfg_id: Default hw config ID |
394 | * @type: DAI type |
395 | * @list: item in snd_sof_dev dai_link list |
396 | */ |
397 | struct snd_sof_dai_link { |
398 | struct snd_sof_tuple *tuples; |
399 | int num_tuples; |
400 | struct snd_soc_dai_link *link; |
401 | struct snd_soc_tplg_hw_config *hw_configs; |
402 | int num_hw_configs; |
403 | int default_hw_cfg_id; |
404 | int type; |
405 | struct list_head list; |
406 | }; |
407 | |
408 | /* ASoC SOF DAPM widget */ |
409 | struct snd_sof_widget { |
410 | struct snd_soc_component *scomp; |
411 | int comp_id; |
412 | int pipeline_id; |
413 | /* |
414 | * the prepared flag is used to indicate that a widget has been prepared for getting set |
415 | * up in the DSP. |
416 | */ |
417 | bool prepared; |
418 | |
419 | struct mutex setup_mutex; /* to protect the swidget setup and free operations */ |
420 | |
421 | /* |
422 | * use_count is protected by the PCM mutex held by the core and the |
423 | * setup_mutex against non stream domain races (kcontrol access for |
424 | * example) |
425 | */ |
426 | int use_count; |
427 | |
428 | int core; |
429 | int id; /* id is the DAPM widget type */ |
430 | /* |
431 | * Instance ID is set dynamically when the widget gets set up in the FW. It should be |
432 | * unique for each module type across all pipelines. This will not be used in SOF_IPC. |
433 | */ |
434 | int instance_id; |
435 | |
436 | /* |
437 | * Flag indicating if the widget should be set up dynamically when a PCM is opened. |
438 | * This flag is only set for the scheduler type widget in topology. During topology |
439 | * loading, this flag is propagated to all the widgets belonging to the same pipeline. |
440 | * When this flag is not set, a widget is set up at the time of topology loading |
441 | * and retained until the DSP enters D3. It will need to be set up again when resuming |
442 | * from D3. |
443 | */ |
444 | bool dynamic_pipeline_widget; |
445 | |
446 | struct snd_soc_dapm_widget *widget; |
447 | struct list_head list; /* list in sdev widget list */ |
448 | struct snd_sof_pipeline *spipe; |
449 | void *module_info; |
450 | |
451 | const guid_t uuid; |
452 | |
453 | int num_tuples; |
454 | struct snd_sof_tuple *tuples; |
455 | |
456 | /* |
457 | * The allowed range for num_input/output_pins is [0, SOF_WIDGET_MAX_NUM_PINS]. |
458 | * Widgets may have zero input or output pins, for example the tone widget has |
459 | * zero input pins. |
460 | */ |
461 | u32 num_input_pins; |
462 | u32 num_output_pins; |
463 | |
464 | /* |
465 | * The input/output pin binding array, it takes the form of |
466 | * [widget_name_connected_to_pin0, widget_name_connected_to_pin1, ...], |
467 | * with the index as the queue ID. |
468 | * |
469 | * The array is used for special pin binding. Note that even if there |
470 | * is only one input/output pin requires special pin binding, pin binding |
471 | * should be defined for all input/output pins in topology, for pin(s) that |
472 | * are not used, give the value "NotConnected". |
473 | * |
474 | * If pin binding is not defined in topology, nothing to parse in the kernel, |
475 | * input_pin_binding and output_pin_binding shall be NULL. |
476 | */ |
477 | char **input_pin_binding; |
478 | char **output_pin_binding; |
479 | |
480 | struct ida output_queue_ida; |
481 | struct ida input_queue_ida; |
482 | |
483 | void *private; /* core does not touch this */ |
484 | }; |
485 | |
486 | /** struct snd_sof_pipeline - ASoC SOF pipeline |
487 | * @pipe_widget: Pointer to the pipeline widget |
488 | * @started_count: Count of number of PCM's that have started this pipeline |
489 | * @paused_count: Count of number of PCM's that have started and have currently paused this |
490 | pipeline |
491 | * @complete: flag used to indicate that pipeline set up is complete. |
492 | * @core_mask: Mask containing target cores for all modules in the pipeline |
493 | * @list: List item in sdev pipeline_list |
494 | */ |
495 | struct snd_sof_pipeline { |
496 | struct snd_sof_widget *pipe_widget; |
497 | int started_count; |
498 | int paused_count; |
499 | int complete; |
500 | unsigned long core_mask; |
501 | struct list_head list; |
502 | }; |
503 | |
504 | /* ASoC SOF DAPM route */ |
505 | struct snd_sof_route { |
506 | struct snd_soc_component *scomp; |
507 | |
508 | struct snd_soc_dapm_route *route; |
509 | struct list_head list; /* list in sdev route list */ |
510 | struct snd_sof_widget *src_widget; |
511 | struct snd_sof_widget *sink_widget; |
512 | bool setup; |
513 | |
514 | int src_queue_id; |
515 | int dst_queue_id; |
516 | |
517 | void *private; |
518 | }; |
519 | |
520 | /* ASoC DAI device */ |
521 | struct snd_sof_dai { |
522 | struct snd_soc_component *scomp; |
523 | const char *name; |
524 | u32 type; |
525 | |
526 | int number_configs; |
527 | int current_config; |
528 | struct list_head list; /* list in sdev dai list */ |
529 | /* core should not touch this */ |
530 | const void *platform_private; |
531 | void *private; |
532 | }; |
533 | |
534 | /* |
535 | * Kcontrols. |
536 | */ |
537 | |
538 | int snd_sof_volume_get(struct snd_kcontrol *kcontrol, |
539 | struct snd_ctl_elem_value *ucontrol); |
540 | int snd_sof_volume_put(struct snd_kcontrol *kcontrol, |
541 | struct snd_ctl_elem_value *ucontrol); |
542 | int snd_sof_volume_info(struct snd_kcontrol *kcontrol, |
543 | struct snd_ctl_elem_info *uinfo); |
544 | int snd_sof_switch_get(struct snd_kcontrol *kcontrol, |
545 | struct snd_ctl_elem_value *ucontrol); |
546 | int snd_sof_switch_put(struct snd_kcontrol *kcontrol, |
547 | struct snd_ctl_elem_value *ucontrol); |
548 | int snd_sof_enum_get(struct snd_kcontrol *kcontrol, |
549 | struct snd_ctl_elem_value *ucontrol); |
550 | int snd_sof_enum_put(struct snd_kcontrol *kcontrol, |
551 | struct snd_ctl_elem_value *ucontrol); |
552 | int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, |
553 | struct snd_ctl_elem_value *ucontrol); |
554 | int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, |
555 | struct snd_ctl_elem_value *ucontrol); |
556 | int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, |
557 | const unsigned int __user *binary_data, |
558 | unsigned int size); |
559 | int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, |
560 | unsigned int __user *binary_data, |
561 | unsigned int size); |
562 | int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data, |
563 | unsigned int size); |
564 | void snd_sof_control_notify(struct snd_sof_dev *sdev, |
565 | struct sof_ipc_ctrl_data *cdata); |
566 | |
567 | /* |
568 | * Topology. |
569 | * There is no snd_sof_free_topology since topology components will |
570 | * be freed by snd_soc_unregister_component, |
571 | */ |
572 | int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file); |
573 | |
574 | /* |
575 | * Stream IPC |
576 | */ |
577 | int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp, |
578 | struct snd_sof_pcm *spcm, int direction, |
579 | struct sof_ipc_stream_posn *posn); |
580 | |
581 | struct snd_sof_widget *snd_sof_find_swidget(struct snd_soc_component *scomp, |
582 | const char *name); |
583 | struct snd_sof_widget * |
584 | snd_sof_find_swidget_sname(struct snd_soc_component *scomp, |
585 | const char *pcm_name, int dir); |
586 | struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, |
587 | const char *name); |
588 | |
589 | static inline |
590 | struct snd_sof_pcm *snd_sof_find_spcm_dai(struct snd_soc_component *scomp, |
591 | struct snd_soc_pcm_runtime *rtd) |
592 | { |
593 | struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(c: scomp); |
594 | struct snd_sof_pcm *spcm; |
595 | |
596 | list_for_each_entry(spcm, &sdev->pcm_list, list) { |
597 | if (le32_to_cpu(spcm->pcm.dai_id) == rtd->dai_link->id) |
598 | return spcm; |
599 | } |
600 | |
601 | return NULL; |
602 | } |
603 | |
604 | struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_soc_component *scomp, |
605 | const char *name); |
606 | struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp, |
607 | unsigned int comp_id, |
608 | int *direction); |
609 | void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream); |
610 | void snd_sof_pcm_init_elapsed_work(struct work_struct *work); |
611 | |
612 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) |
613 | void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream); |
614 | void snd_sof_compr_init_elapsed_work(struct work_struct *work); |
615 | #else |
616 | static inline void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream) { } |
617 | static inline void snd_sof_compr_init_elapsed_work(struct work_struct *work) { } |
618 | #endif |
619 | |
620 | /* DAI link fixup */ |
621 | int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); |
622 | |
623 | /* PM */ |
624 | bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev); |
625 | bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev); |
626 | |
627 | /* Machine driver enumeration */ |
628 | int sof_machine_register(struct snd_sof_dev *sdev, void *pdata); |
629 | void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata); |
630 | |
631 | int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); |
632 | int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); |
633 | int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsource, |
634 | struct snd_soc_dapm_widget *wsink); |
635 | |
636 | /* PCM */ |
637 | int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, |
638 | struct snd_pcm_hw_params *fe_params, |
639 | struct snd_sof_platform_stream_params *platform_params, |
640 | int dir); |
641 | int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir); |
642 | int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, struct snd_sof_dev *sdev, |
643 | struct snd_sof_pcm *spcm); |
644 | int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, |
645 | struct snd_sof_pcm *spcm, int dir, bool free_widget_list); |
646 | int get_token_u32(void *elem, void *object, u32 offset); |
647 | int get_token_u16(void *elem, void *object, u32 offset); |
648 | int get_token_comp_format(void *elem, void *object, u32 offset); |
649 | int get_token_dai_type(void *elem, void *object, u32 offset); |
650 | int get_token_uuid(void *elem, void *object, u32 offset); |
651 | int get_token_string(void *elem, void *object, u32 offset); |
652 | int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum sof_tokens token_id, |
653 | struct snd_sof_tuple *tuples, int num_tuples, |
654 | size_t object_size, int token_instance_num); |
655 | u32 vol_compute_gain(u32 value, int *tlv); |
656 | #endif |
657 | |