1*4882a593Smuzhiyun /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * This file is provided under a dual BSD/GPLv2 license. When using or
4*4882a593Smuzhiyun * redistributing this file, you may do so under either license.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright(c) 2019 Intel Corporation. All rights reserved.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #ifndef __SOUND_SOC_SOF_AUDIO_H
12*4882a593Smuzhiyun #define __SOUND_SOC_SOF_AUDIO_H
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <linux/workqueue.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <sound/soc.h>
17*4882a593Smuzhiyun #include <sound/control.h>
18*4882a593Smuzhiyun #include <sound/sof/stream.h> /* needs to be included before control.h */
19*4882a593Smuzhiyun #include <sound/sof/control.h>
20*4882a593Smuzhiyun #include <sound/sof/dai.h>
21*4882a593Smuzhiyun #include <sound/sof/topology.h>
22*4882a593Smuzhiyun #include "sof-priv.h"
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define SOF_AUDIO_PCM_DRV_NAME "sof-audio-component"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /* max number of FE PCMs before BEs */
27*4882a593Smuzhiyun #define SOF_BE_PCM_BASE 16
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define DMA_CHAN_INVALID 0xFFFFFFFF
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /* PCM stream, mapped to FW component */
32*4882a593Smuzhiyun struct snd_sof_pcm_stream {
33*4882a593Smuzhiyun u32 comp_id;
34*4882a593Smuzhiyun struct snd_dma_buffer page_table;
35*4882a593Smuzhiyun struct sof_ipc_stream_posn posn;
36*4882a593Smuzhiyun struct snd_pcm_substream *substream;
37*4882a593Smuzhiyun struct work_struct period_elapsed_work;
38*4882a593Smuzhiyun bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */
39*4882a593Smuzhiyun /*
40*4882a593Smuzhiyun * flag to indicate that the DSP pipelines should be kept
41*4882a593Smuzhiyun * active or not while suspending the stream
42*4882a593Smuzhiyun */
43*4882a593Smuzhiyun bool suspend_ignored;
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* ALSA SOF PCM device */
47*4882a593Smuzhiyun struct snd_sof_pcm {
48*4882a593Smuzhiyun struct snd_soc_component *scomp;
49*4882a593Smuzhiyun struct snd_soc_tplg_pcm pcm;
50*4882a593Smuzhiyun struct snd_sof_pcm_stream stream[2];
51*4882a593Smuzhiyun struct list_head list; /* list in sdev pcm list */
52*4882a593Smuzhiyun struct snd_pcm_hw_params params[2];
53*4882a593Smuzhiyun bool prepared[2]; /* PCM_PARAMS set successfully */
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun struct snd_sof_led_control {
57*4882a593Smuzhiyun unsigned int use_led;
58*4882a593Smuzhiyun unsigned int direction;
59*4882a593Smuzhiyun int led_value;
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun /* ALSA SOF Kcontrol device */
63*4882a593Smuzhiyun struct snd_sof_control {
64*4882a593Smuzhiyun struct snd_soc_component *scomp;
65*4882a593Smuzhiyun int comp_id;
66*4882a593Smuzhiyun int min_volume_step; /* min volume step for volume_table */
67*4882a593Smuzhiyun int max_volume_step; /* max volume step for volume_table */
68*4882a593Smuzhiyun int num_channels;
69*4882a593Smuzhiyun u32 readback_offset; /* offset to mmapped data if used */
70*4882a593Smuzhiyun struct sof_ipc_ctrl_data *control_data;
71*4882a593Smuzhiyun u32 size; /* cdata size */
72*4882a593Smuzhiyun enum sof_ipc_ctrl_cmd cmd;
73*4882a593Smuzhiyun u32 *volume_table; /* volume table computed from tlv data*/
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun struct list_head list; /* list in sdev control list */
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun struct snd_sof_led_control led_ctl;
78*4882a593Smuzhiyun };
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /* ASoC SOF DAPM widget */
81*4882a593Smuzhiyun struct snd_sof_widget {
82*4882a593Smuzhiyun struct snd_soc_component *scomp;
83*4882a593Smuzhiyun int comp_id;
84*4882a593Smuzhiyun int pipeline_id;
85*4882a593Smuzhiyun int complete;
86*4882a593Smuzhiyun int core;
87*4882a593Smuzhiyun int id;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun struct snd_soc_dapm_widget *widget;
90*4882a593Smuzhiyun struct list_head list; /* list in sdev widget list */
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /* extended data for UUID components */
93*4882a593Smuzhiyun struct sof_ipc_comp_ext comp_ext;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun void *private; /* core does not touch this */
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /* ASoC SOF DAPM route */
99*4882a593Smuzhiyun struct snd_sof_route {
100*4882a593Smuzhiyun struct snd_soc_component *scomp;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun struct snd_soc_dapm_route *route;
103*4882a593Smuzhiyun struct list_head list; /* list in sdev route list */
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun void *private;
106*4882a593Smuzhiyun };
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun /* ASoC DAI device */
109*4882a593Smuzhiyun struct snd_sof_dai {
110*4882a593Smuzhiyun struct snd_soc_component *scomp;
111*4882a593Smuzhiyun const char *name;
112*4882a593Smuzhiyun const char *cpu_dai_name;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun struct sof_ipc_comp_dai comp_dai;
115*4882a593Smuzhiyun struct sof_ipc_dai_config *dai_config;
116*4882a593Smuzhiyun struct list_head list; /* list in sdev dai list */
117*4882a593Smuzhiyun };
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /*
120*4882a593Smuzhiyun * Kcontrols.
121*4882a593Smuzhiyun */
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
124*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
125*4882a593Smuzhiyun int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
126*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
127*4882a593Smuzhiyun int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
128*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
129*4882a593Smuzhiyun int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
130*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
131*4882a593Smuzhiyun int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
132*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
133*4882a593Smuzhiyun int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
134*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
135*4882a593Smuzhiyun int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
136*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
137*4882a593Smuzhiyun int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
138*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
139*4882a593Smuzhiyun int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
140*4882a593Smuzhiyun const unsigned int __user *binary_data,
141*4882a593Smuzhiyun unsigned int size);
142*4882a593Smuzhiyun int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
143*4882a593Smuzhiyun unsigned int __user *binary_data,
144*4882a593Smuzhiyun unsigned int size);
145*4882a593Smuzhiyun int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data,
146*4882a593Smuzhiyun unsigned int size);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun /*
149*4882a593Smuzhiyun * Topology.
150*4882a593Smuzhiyun * There is no snd_sof_free_topology since topology components will
151*4882a593Smuzhiyun * be freed by snd_soc_unregister_component,
152*4882a593Smuzhiyun */
153*4882a593Smuzhiyun int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file);
154*4882a593Smuzhiyun int snd_sof_complete_pipeline(struct device *dev,
155*4882a593Smuzhiyun struct snd_sof_widget *swidget);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun int sof_load_pipeline_ipc(struct device *dev,
158*4882a593Smuzhiyun struct sof_ipc_pipe_new *pipeline,
159*4882a593Smuzhiyun struct sof_ipc_comp_reply *r);
160*4882a593Smuzhiyun int sof_pipeline_core_enable(struct snd_sof_dev *sdev,
161*4882a593Smuzhiyun const struct snd_sof_widget *swidget);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /*
164*4882a593Smuzhiyun * Stream IPC
165*4882a593Smuzhiyun */
166*4882a593Smuzhiyun int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp,
167*4882a593Smuzhiyun struct snd_sof_pcm *spcm, int direction,
168*4882a593Smuzhiyun struct sof_ipc_stream_posn *posn);
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun struct snd_sof_widget *snd_sof_find_swidget(struct snd_soc_component *scomp,
171*4882a593Smuzhiyun const char *name);
172*4882a593Smuzhiyun struct snd_sof_widget *
173*4882a593Smuzhiyun snd_sof_find_swidget_sname(struct snd_soc_component *scomp,
174*4882a593Smuzhiyun const char *pcm_name, int dir);
175*4882a593Smuzhiyun struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp,
176*4882a593Smuzhiyun const char *name);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun static inline
snd_sof_find_spcm_dai(struct snd_soc_component * scomp,struct snd_soc_pcm_runtime * rtd)179*4882a593Smuzhiyun struct snd_sof_pcm *snd_sof_find_spcm_dai(struct snd_soc_component *scomp,
180*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun struct snd_sof_pcm *spcm = NULL;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun list_for_each_entry(spcm, &sdev->pcm_list, list) {
187*4882a593Smuzhiyun if (le32_to_cpu(spcm->pcm.dai_id) == rtd->dai_link->id)
188*4882a593Smuzhiyun return spcm;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun return NULL;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_soc_component *scomp,
195*4882a593Smuzhiyun const char *name);
196*4882a593Smuzhiyun struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp,
197*4882a593Smuzhiyun unsigned int comp_id,
198*4882a593Smuzhiyun int *direction);
199*4882a593Smuzhiyun struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_soc_component *scomp,
200*4882a593Smuzhiyun unsigned int pcm_id);
201*4882a593Smuzhiyun const struct sof_ipc_pipe_new *snd_sof_pipeline_find(struct snd_sof_dev *sdev,
202*4882a593Smuzhiyun int pipeline_id);
203*4882a593Smuzhiyun void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream);
204*4882a593Smuzhiyun void snd_sof_pcm_period_elapsed_work(struct work_struct *work);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun /*
207*4882a593Smuzhiyun * Mixer IPC
208*4882a593Smuzhiyun */
209*4882a593Smuzhiyun int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol,
210*4882a593Smuzhiyun u32 ipc_cmd,
211*4882a593Smuzhiyun enum sof_ipc_ctrl_type ctrl_type,
212*4882a593Smuzhiyun enum sof_ipc_ctrl_cmd ctrl_cmd,
213*4882a593Smuzhiyun bool send);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /* PM */
216*4882a593Smuzhiyun int sof_restore_pipelines(struct device *dev);
217*4882a593Smuzhiyun int sof_set_hw_params_upon_resume(struct device *dev);
218*4882a593Smuzhiyun bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev);
219*4882a593Smuzhiyun bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /* Machine driver enumeration */
222*4882a593Smuzhiyun int sof_machine_register(struct snd_sof_dev *sdev, void *pdata);
223*4882a593Smuzhiyun void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun #endif
226