~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/qcom/qdsp6/q6afe.c

Version: ~ [ linux-5.9 ] ~ [ linux-5.8.14 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.70 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.150 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.200 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.238 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.238 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
  3 // Copyright (c) 2018, Linaro Limited
  4 
  5 #include <linux/slab.h>
  6 #include <linux/kernel.h>
  7 #include <linux/uaccess.h>
  8 #include <linux/wait.h>
  9 #include <linux/jiffies.h>
 10 #include <linux/sched.h>
 11 #include <linux/module.h>
 12 #include <linux/kref.h>
 13 #include <linux/of.h>
 14 #include <linux/of_platform.h>
 15 #include <linux/spinlock.h>
 16 #include <linux/delay.h>
 17 #include <linux/soc/qcom/apr.h>
 18 #include <sound/soc.h>
 19 #include <sound/soc-dai.h>
 20 #include <sound/pcm.h>
 21 #include <sound/pcm_params.h>
 22 #include "q6dsp-errno.h"
 23 #include "q6core.h"
 24 #include "q6afe.h"
 25 
 26 /* AFE CMDs */
 27 #define AFE_PORT_CMD_DEVICE_START       0x000100E5
 28 #define AFE_PORT_CMD_DEVICE_STOP        0x000100E6
 29 #define AFE_PORT_CMD_SET_PARAM_V2       0x000100EF
 30 #define AFE_SVC_CMD_SET_PARAM           0x000100f3
 31 #define AFE_PORT_CMDRSP_GET_PARAM_V2    0x00010106
 32 #define AFE_PARAM_ID_HDMI_CONFIG        0x00010210
 33 #define AFE_MODULE_AUDIO_DEV_INTERFACE  0x0001020C
 34 #define AFE_MODULE_TDM                  0x0001028A
 35 
 36 #define AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG 0x00010235
 37 
 38 #define AFE_PARAM_ID_LPAIF_CLK_CONFIG   0x00010238
 39 #define AFE_PARAM_ID_INT_DIGITAL_CDC_CLK_CONFIG 0x00010239
 40 
 41 #define AFE_PARAM_ID_SLIMBUS_CONFIG    0x00010212
 42 #define AFE_PARAM_ID_I2S_CONFIG 0x0001020D
 43 #define AFE_PARAM_ID_TDM_CONFIG 0x0001029D
 44 #define AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG   0x00010297
 45 
 46 /* I2S config specific */
 47 #define AFE_API_VERSION_I2S_CONFIG      0x1
 48 #define AFE_PORT_I2S_SD0                0x1
 49 #define AFE_PORT_I2S_SD1                0x2
 50 #define AFE_PORT_I2S_SD2                0x3
 51 #define AFE_PORT_I2S_SD3                0x4
 52 #define AFE_PORT_I2S_SD0_MASK           BIT(0x1)
 53 #define AFE_PORT_I2S_SD1_MASK           BIT(0x2)
 54 #define AFE_PORT_I2S_SD2_MASK           BIT(0x3)
 55 #define AFE_PORT_I2S_SD3_MASK           BIT(0x4)
 56 #define AFE_PORT_I2S_SD0_1_MASK         GENMASK(2, 1)
 57 #define AFE_PORT_I2S_SD2_3_MASK         GENMASK(4, 3)
 58 #define AFE_PORT_I2S_SD0_1_2_MASK       GENMASK(3, 1)
 59 #define AFE_PORT_I2S_SD0_1_2_3_MASK     GENMASK(4, 1)
 60 #define AFE_PORT_I2S_QUAD01             0x5
 61 #define AFE_PORT_I2S_QUAD23             0x6
 62 #define AFE_PORT_I2S_6CHS               0x7
 63 #define AFE_PORT_I2S_8CHS               0x8
 64 #define AFE_PORT_I2S_MONO               0x0
 65 #define AFE_PORT_I2S_STEREO             0x1
 66 #define AFE_PORT_CONFIG_I2S_WS_SRC_EXTERNAL     0x0
 67 #define AFE_PORT_CONFIG_I2S_WS_SRC_INTERNAL     0x1
 68 #define AFE_LINEAR_PCM_DATA                             0x0
 69 
 70 
 71 /* Port IDs */
 72 #define AFE_API_VERSION_HDMI_CONFIG     0x1
 73 #define AFE_PORT_ID_MULTICHAN_HDMI_RX   0x100E
 74 
 75 #define AFE_API_VERSION_SLIMBUS_CONFIG 0x1
 76 /* Clock set API version */
 77 #define AFE_API_VERSION_CLOCK_SET 1
 78 #define Q6AFE_LPASS_CLK_CONFIG_API_VERSION      0x1
 79 #define AFE_MODULE_CLOCK_SET            0x0001028F
 80 #define AFE_PARAM_ID_CLOCK_SET          0x00010290
 81 
 82 /* SLIMbus Rx port on channel 0. */
 83 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX      0x4000
 84 /* SLIMbus Tx port on channel 0. */
 85 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_TX      0x4001
 86 /* SLIMbus Rx port on channel 1. */
 87 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX      0x4002
 88 /* SLIMbus Tx port on channel 1. */
 89 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_TX      0x4003
 90 /* SLIMbus Rx port on channel 2. */
 91 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX      0x4004
 92 /* SLIMbus Tx port on channel 2. */
 93 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_TX      0x4005
 94 /* SLIMbus Rx port on channel 3. */
 95 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_RX      0x4006
 96 /* SLIMbus Tx port on channel 3. */
 97 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_TX      0x4007
 98 /* SLIMbus Rx port on channel 4. */
 99 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX      0x4008
100 /* SLIMbus Tx port on channel 4. */
101 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX      0x4009
102 /* SLIMbus Rx port on channel 5. */
103 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX      0x400a
104 /* SLIMbus Tx port on channel 5. */
105 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX      0x400b
106 /* SLIMbus Rx port on channel 6. */
107 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX      0x400c
108 /* SLIMbus Tx port on channel 6. */
109 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_TX      0x400d
110 #define AFE_PORT_ID_PRIMARY_MI2S_RX         0x1000
111 #define AFE_PORT_ID_PRIMARY_MI2S_TX         0x1001
112 #define AFE_PORT_ID_SECONDARY_MI2S_RX       0x1002
113 #define AFE_PORT_ID_SECONDARY_MI2S_TX       0x1003
114 #define AFE_PORT_ID_TERTIARY_MI2S_RX        0x1004
115 #define AFE_PORT_ID_TERTIARY_MI2S_TX        0x1005
116 #define AFE_PORT_ID_QUATERNARY_MI2S_RX      0x1006
117 #define AFE_PORT_ID_QUATERNARY_MI2S_TX      0x1007
118 
119 /* Start of the range of port IDs for TDM devices. */
120 #define AFE_PORT_ID_TDM_PORT_RANGE_START        0x9000
121 
122 /* End of the range of port IDs for TDM devices. */
123 #define AFE_PORT_ID_TDM_PORT_RANGE_END \
124         (AFE_PORT_ID_TDM_PORT_RANGE_START+0x50-1)
125 
126 /* Size of the range of port IDs for TDM ports. */
127 #define AFE_PORT_ID_TDM_PORT_RANGE_SIZE \
128         (AFE_PORT_ID_TDM_PORT_RANGE_END - \
129         AFE_PORT_ID_TDM_PORT_RANGE_START+1)
130 
131 #define AFE_PORT_ID_PRIMARY_TDM_RX \
132         (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x00)
133 #define AFE_PORT_ID_PRIMARY_TDM_RX_1 \
134         (AFE_PORT_ID_PRIMARY_TDM_RX + 0x02)
135 #define AFE_PORT_ID_PRIMARY_TDM_RX_2 \
136         (AFE_PORT_ID_PRIMARY_TDM_RX + 0x04)
137 #define AFE_PORT_ID_PRIMARY_TDM_RX_3 \
138         (AFE_PORT_ID_PRIMARY_TDM_RX + 0x06)
139 #define AFE_PORT_ID_PRIMARY_TDM_RX_4 \
140         (AFE_PORT_ID_PRIMARY_TDM_RX + 0x08)
141 #define AFE_PORT_ID_PRIMARY_TDM_RX_5 \
142         (AFE_PORT_ID_PRIMARY_TDM_RX + 0x0A)
143 #define AFE_PORT_ID_PRIMARY_TDM_RX_6 \
144         (AFE_PORT_ID_PRIMARY_TDM_RX + 0x0C)
145 #define AFE_PORT_ID_PRIMARY_TDM_RX_7 \
146         (AFE_PORT_ID_PRIMARY_TDM_RX + 0x0E)
147 
148 #define AFE_PORT_ID_PRIMARY_TDM_TX \
149         (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x01)
150 #define AFE_PORT_ID_PRIMARY_TDM_TX_1 \
151         (AFE_PORT_ID_PRIMARY_TDM_TX + 0x02)
152 #define AFE_PORT_ID_PRIMARY_TDM_TX_2 \
153         (AFE_PORT_ID_PRIMARY_TDM_TX + 0x04)
154 #define AFE_PORT_ID_PRIMARY_TDM_TX_3 \
155         (AFE_PORT_ID_PRIMARY_TDM_TX + 0x06)
156 #define AFE_PORT_ID_PRIMARY_TDM_TX_4 \
157         (AFE_PORT_ID_PRIMARY_TDM_TX + 0x08)
158 #define AFE_PORT_ID_PRIMARY_TDM_TX_5 \
159         (AFE_PORT_ID_PRIMARY_TDM_TX + 0x0A)
160 #define AFE_PORT_ID_PRIMARY_TDM_TX_6 \
161         (AFE_PORT_ID_PRIMARY_TDM_TX + 0x0C)
162 #define AFE_PORT_ID_PRIMARY_TDM_TX_7 \
163         (AFE_PORT_ID_PRIMARY_TDM_TX + 0x0E)
164 
165 #define AFE_PORT_ID_SECONDARY_TDM_RX \
166         (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x10)
167 #define AFE_PORT_ID_SECONDARY_TDM_RX_1 \
168         (AFE_PORT_ID_SECONDARY_TDM_RX + 0x02)
169 #define AFE_PORT_ID_SECONDARY_TDM_RX_2 \
170         (AFE_PORT_ID_SECONDARY_TDM_RX + 0x04)
171 #define AFE_PORT_ID_SECONDARY_TDM_RX_3 \
172         (AFE_PORT_ID_SECONDARY_TDM_RX + 0x06)
173 #define AFE_PORT_ID_SECONDARY_TDM_RX_4 \
174         (AFE_PORT_ID_SECONDARY_TDM_RX + 0x08)
175 #define AFE_PORT_ID_SECONDARY_TDM_RX_5 \
176         (AFE_PORT_ID_SECONDARY_TDM_RX + 0x0A)
177 #define AFE_PORT_ID_SECONDARY_TDM_RX_6 \
178         (AFE_PORT_ID_SECONDARY_TDM_RX + 0x0C)
179 #define AFE_PORT_ID_SECONDARY_TDM_RX_7 \
180         (AFE_PORT_ID_SECONDARY_TDM_RX + 0x0E)
181 
182 #define AFE_PORT_ID_SECONDARY_TDM_TX \
183         (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x11)
184 #define AFE_PORT_ID_SECONDARY_TDM_TX_1 \
185         (AFE_PORT_ID_SECONDARY_TDM_TX + 0x02)
186 #define AFE_PORT_ID_SECONDARY_TDM_TX_2 \
187         (AFE_PORT_ID_SECONDARY_TDM_TX + 0x04)
188 #define AFE_PORT_ID_SECONDARY_TDM_TX_3 \
189         (AFE_PORT_ID_SECONDARY_TDM_TX + 0x06)
190 #define AFE_PORT_ID_SECONDARY_TDM_TX_4 \
191         (AFE_PORT_ID_SECONDARY_TDM_TX + 0x08)
192 #define AFE_PORT_ID_SECONDARY_TDM_TX_5 \
193         (AFE_PORT_ID_SECONDARY_TDM_TX + 0x0A)
194 #define AFE_PORT_ID_SECONDARY_TDM_TX_6 \
195         (AFE_PORT_ID_SECONDARY_TDM_TX + 0x0C)
196 #define AFE_PORT_ID_SECONDARY_TDM_TX_7 \
197         (AFE_PORT_ID_SECONDARY_TDM_TX + 0x0E)
198 
199 #define AFE_PORT_ID_TERTIARY_TDM_RX \
200         (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x20)
201 #define AFE_PORT_ID_TERTIARY_TDM_RX_1 \
202         (AFE_PORT_ID_TERTIARY_TDM_RX + 0x02)
203 #define AFE_PORT_ID_TERTIARY_TDM_RX_2 \
204         (AFE_PORT_ID_TERTIARY_TDM_RX + 0x04)
205 #define AFE_PORT_ID_TERTIARY_TDM_RX_3 \
206         (AFE_PORT_ID_TERTIARY_TDM_RX + 0x06)
207 #define AFE_PORT_ID_TERTIARY_TDM_RX_4 \
208         (AFE_PORT_ID_TERTIARY_TDM_RX + 0x08)
209 #define AFE_PORT_ID_TERTIARY_TDM_RX_5 \
210         (AFE_PORT_ID_TERTIARY_TDM_RX + 0x0A)
211 #define AFE_PORT_ID_TERTIARY_TDM_RX_6 \
212         (AFE_PORT_ID_TERTIARY_TDM_RX + 0x0C)
213 #define AFE_PORT_ID_TERTIARY_TDM_RX_7 \
214         (AFE_PORT_ID_TERTIARY_TDM_RX + 0x0E)
215 
216 #define AFE_PORT_ID_TERTIARY_TDM_TX \
217         (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x21)
218 #define AFE_PORT_ID_TERTIARY_TDM_TX_1 \
219         (AFE_PORT_ID_TERTIARY_TDM_TX + 0x02)
220 #define AFE_PORT_ID_TERTIARY_TDM_TX_2 \
221         (AFE_PORT_ID_TERTIARY_TDM_TX + 0x04)
222 #define AFE_PORT_ID_TERTIARY_TDM_TX_3 \
223         (AFE_PORT_ID_TERTIARY_TDM_TX + 0x06)
224 #define AFE_PORT_ID_TERTIARY_TDM_TX_4 \
225         (AFE_PORT_ID_TERTIARY_TDM_TX + 0x08)
226 #define AFE_PORT_ID_TERTIARY_TDM_TX_5 \
227         (AFE_PORT_ID_TERTIARY_TDM_TX + 0x0A)
228 #define AFE_PORT_ID_TERTIARY_TDM_TX_6 \
229         (AFE_PORT_ID_TERTIARY_TDM_TX + 0x0C)
230 #define AFE_PORT_ID_TERTIARY_TDM_TX_7 \
231         (AFE_PORT_ID_TERTIARY_TDM_TX + 0x0E)
232 
233 #define AFE_PORT_ID_QUATERNARY_TDM_RX \
234         (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x30)
235 #define AFE_PORT_ID_QUATERNARY_TDM_RX_1 \
236         (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x02)
237 #define AFE_PORT_ID_QUATERNARY_TDM_RX_2 \
238         (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x04)
239 #define AFE_PORT_ID_QUATERNARY_TDM_RX_3 \
240         (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x06)
241 #define AFE_PORT_ID_QUATERNARY_TDM_RX_4 \
242         (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x08)
243 #define AFE_PORT_ID_QUATERNARY_TDM_RX_5 \
244         (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x0A)
245 #define AFE_PORT_ID_QUATERNARY_TDM_RX_6 \
246         (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x0C)
247 #define AFE_PORT_ID_QUATERNARY_TDM_RX_7 \
248         (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x0E)
249 
250 #define AFE_PORT_ID_QUATERNARY_TDM_TX \
251         (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x31)
252 #define AFE_PORT_ID_QUATERNARY_TDM_TX_1 \
253         (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x02)
254 #define AFE_PORT_ID_QUATERNARY_TDM_TX_2 \
255         (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x04)
256 #define AFE_PORT_ID_QUATERNARY_TDM_TX_3 \
257         (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x06)
258 #define AFE_PORT_ID_QUATERNARY_TDM_TX_4 \
259         (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x08)
260 #define AFE_PORT_ID_QUATERNARY_TDM_TX_5 \
261         (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x0A)
262 #define AFE_PORT_ID_QUATERNARY_TDM_TX_6 \
263         (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x0C)
264 #define AFE_PORT_ID_QUATERNARY_TDM_TX_7 \
265         (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x0E)
266 
267 #define AFE_PORT_ID_QUINARY_TDM_RX \
268         (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x40)
269 #define AFE_PORT_ID_QUINARY_TDM_RX_1 \
270         (AFE_PORT_ID_QUINARY_TDM_RX + 0x02)
271 #define AFE_PORT_ID_QUINARY_TDM_RX_2 \
272         (AFE_PORT_ID_QUINARY_TDM_RX + 0x04)
273 #define AFE_PORT_ID_QUINARY_TDM_RX_3 \
274         (AFE_PORT_ID_QUINARY_TDM_RX + 0x06)
275 #define AFE_PORT_ID_QUINARY_TDM_RX_4 \
276         (AFE_PORT_ID_QUINARY_TDM_RX + 0x08)
277 #define AFE_PORT_ID_QUINARY_TDM_RX_5 \
278         (AFE_PORT_ID_QUINARY_TDM_RX + 0x0A)
279 #define AFE_PORT_ID_QUINARY_TDM_RX_6 \
280         (AFE_PORT_ID_QUINARY_TDM_RX + 0x0C)
281 #define AFE_PORT_ID_QUINARY_TDM_RX_7 \
282         (AFE_PORT_ID_QUINARY_TDM_RX + 0x0E)
283 
284 #define AFE_PORT_ID_QUINARY_TDM_TX \
285         (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x41)
286 #define AFE_PORT_ID_QUINARY_TDM_TX_1 \
287         (AFE_PORT_ID_QUINARY_TDM_TX + 0x02)
288 #define AFE_PORT_ID_QUINARY_TDM_TX_2 \
289         (AFE_PORT_ID_QUINARY_TDM_TX + 0x04)
290 #define AFE_PORT_ID_QUINARY_TDM_TX_3 \
291         (AFE_PORT_ID_QUINARY_TDM_TX + 0x06)
292 #define AFE_PORT_ID_QUINARY_TDM_TX_4 \
293         (AFE_PORT_ID_QUINARY_TDM_TX + 0x08)
294 #define AFE_PORT_ID_QUINARY_TDM_TX_5 \
295         (AFE_PORT_ID_QUINARY_TDM_TX + 0x0A)
296 #define AFE_PORT_ID_QUINARY_TDM_TX_6 \
297         (AFE_PORT_ID_QUINARY_TDM_TX + 0x0C)
298 #define AFE_PORT_ID_QUINARY_TDM_TX_7 \
299         (AFE_PORT_ID_QUINARY_TDM_TX + 0x0E)
300 
301 #define Q6AFE_LPASS_MODE_CLK1_VALID 1
302 #define Q6AFE_LPASS_MODE_CLK2_VALID 2
303 #define Q6AFE_LPASS_CLK_SRC_INTERNAL 1
304 #define Q6AFE_LPASS_CLK_ROOT_DEFAULT 0
305 #define AFE_API_VERSION_TDM_CONFIG              1
306 #define AFE_API_VERSION_SLOT_MAPPING_CONFIG     1
307 
308 #define TIMEOUT_MS 1000
309 #define AFE_CMD_RESP_AVAIL      0
310 #define AFE_CMD_RESP_NONE       1
311 
312 struct q6afe {
313         struct apr_device *apr;
314         struct device *dev;
315         struct q6core_svc_api_info ainfo;
316         struct mutex lock;
317         struct list_head port_list;
318         spinlock_t port_list_lock;
319         struct platform_device *pdev_dais;
320 };
321 
322 struct afe_port_cmd_device_start {
323         u16 port_id;
324         u16 reserved;
325 } __packed;
326 
327 struct afe_port_cmd_device_stop {
328         u16 port_id;
329         u16 reserved;
330 /* Reserved for 32-bit alignment. This field must be set to 0.*/
331 } __packed;
332 
333 struct afe_port_param_data_v2 {
334         u32 module_id;
335         u32 param_id;
336         u16 param_size;
337         u16 reserved;
338 } __packed;
339 
340 struct afe_svc_cmd_set_param {
341         uint32_t payload_size;
342         uint32_t payload_address_lsw;
343         uint32_t payload_address_msw;
344         uint32_t mem_map_handle;
345 } __packed;
346 
347 struct afe_port_cmd_set_param_v2 {
348         u16 port_id;
349         u16 payload_size;
350         u32 payload_address_lsw;
351         u32 payload_address_msw;
352         u32 mem_map_handle;
353 } __packed;
354 
355 struct afe_param_id_hdmi_multi_chan_audio_cfg {
356         u32 hdmi_cfg_minor_version;
357         u16 datatype;
358         u16 channel_allocation;
359         u32 sample_rate;
360         u16 bit_width;
361         u16 reserved;
362 } __packed;
363 
364 struct afe_param_id_slimbus_cfg {
365         u32                  sb_cfg_minor_version;
366 /* Minor version used for tracking the version of the SLIMBUS
367  * configuration interface.
368  * Supported values: #AFE_API_VERSION_SLIMBUS_CONFIG
369  */
370 
371         u16                  slimbus_dev_id;
372 /* SLIMbus hardware device ID, which is required to handle
373  * multiple SLIMbus hardware blocks.
374  * Supported values: - #AFE_SLIMBUS_DEVICE_1 - #AFE_SLIMBUS_DEVICE_2
375  */
376         u16                  bit_width;
377 /* Bit width of the sample.
378  * Supported values: 16, 24
379  */
380         u16                  data_format;
381 /* Data format supported by the SLIMbus hardware. The default is
382  * 0 (#AFE_SB_DATA_FORMAT_NOT_INDICATED), which indicates the
383  * hardware does not perform any format conversions before the data
384  * transfer.
385  */
386         u16                  num_channels;
387 /* Number of channels.
388  * Supported values: 1 to #AFE_PORT_MAX_AUDIO_CHAN_CNT
389  */
390         u8  shared_ch_mapping[AFE_PORT_MAX_AUDIO_CHAN_CNT];
391 /* Mapping of shared channel IDs (128 to 255) to which the
392  * master port is to be connected.
393  * Shared_channel_mapping[i] represents the shared channel assigned
394  * for audio channel i in multichannel audio data.
395  */
396         u32              sample_rate;
397 /* Sampling rate of the port.
398  * Supported values:
399  * - #AFE_PORT_SAMPLE_RATE_8K
400  * - #AFE_PORT_SAMPLE_RATE_16K
401  * - #AFE_PORT_SAMPLE_RATE_48K
402  * - #AFE_PORT_SAMPLE_RATE_96K
403  * - #AFE_PORT_SAMPLE_RATE_192K
404  */
405 } __packed;
406 
407 struct afe_clk_cfg {
408         u32                  i2s_cfg_minor_version;
409         u32                  clk_val1;
410         u32                  clk_val2;
411         u16                  clk_src;
412         u16                  clk_root;
413         u16                  clk_set_mode;
414         u16                  reserved;
415 } __packed;
416 
417 struct afe_digital_clk_cfg {
418         u32                  i2s_cfg_minor_version;
419         u32                  clk_val;
420         u16                  clk_root;
421         u16                  reserved;
422 } __packed;
423 
424 struct afe_param_id_i2s_cfg {
425         u32     i2s_cfg_minor_version;
426         u16     bit_width;
427         u16     channel_mode;
428         u16     mono_stereo;
429         u16     ws_src;
430         u32     sample_rate;
431         u16     data_format;
432         u16     reserved;
433 } __packed;
434 
435 struct afe_param_id_tdm_cfg {
436         u32     tdm_cfg_minor_version;
437         u32     num_channels;
438         u32     sample_rate;
439         u32     bit_width;
440         u16     data_format;
441         u16     sync_mode;
442         u16     sync_src;
443         u16     nslots_per_frame;
444         u16     ctrl_data_out_enable;
445         u16     ctrl_invert_sync_pulse;
446         u16     ctrl_sync_data_delay;
447         u16     slot_width;
448         u32     slot_mask;
449 } __packed;
450 
451 union afe_port_config {
452         struct afe_param_id_hdmi_multi_chan_audio_cfg hdmi_multi_ch;
453         struct afe_param_id_slimbus_cfg           slim_cfg;
454         struct afe_param_id_i2s_cfg     i2s_cfg;
455         struct afe_param_id_tdm_cfg     tdm_cfg;
456 } __packed;
457 
458 
459 struct afe_clk_set {
460         uint32_t clk_set_minor_version;
461         uint32_t clk_id;
462         uint32_t clk_freq_in_hz;
463         uint16_t clk_attri;
464         uint16_t clk_root;
465         uint32_t enable;
466 };
467 
468 struct afe_param_id_slot_mapping_cfg {
469         u32     minor_version;
470         u16     num_channels;
471         u16     bitwidth;
472         u32     data_align_type;
473         u16     ch_mapping[AFE_PORT_MAX_AUDIO_CHAN_CNT];
474 } __packed;
475 
476 struct q6afe_port {
477         wait_queue_head_t wait;
478         union afe_port_config port_cfg;
479         struct afe_param_id_slot_mapping_cfg *scfg;
480         struct aprv2_ibasic_rsp_result_t result;
481         int token;
482         int id;
483         int cfg_type;
484         struct q6afe *afe;
485         struct kref refcount;
486         struct list_head node;
487 };
488 
489 struct afe_port_map {
490         int port_id;
491         int token;
492         int is_rx;
493         int is_dig_pcm;
494 };
495 
496 /*
497  * Mapping between Virtual Port IDs to DSP AFE Port ID
498  * On B Family SoCs DSP Port IDs are consistent across multiple SoCs
499  * on A Family SoCs DSP port IDs are same as virtual Port IDs.
500  */
501 
502 static struct afe_port_map port_maps[AFE_PORT_MAX] = {
503         [HDMI_RX] = { AFE_PORT_ID_MULTICHAN_HDMI_RX, HDMI_RX, 1, 1},
504         [SLIMBUS_0_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX,
505                                 SLIMBUS_0_RX, 1, 1},
506         [SLIMBUS_1_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX,
507                                 SLIMBUS_1_RX, 1, 1},
508         [SLIMBUS_2_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX,
509                                 SLIMBUS_2_RX, 1, 1},
510         [SLIMBUS_3_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_RX,
511                                 SLIMBUS_3_RX, 1, 1},
512         [SLIMBUS_4_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX,
513                                 SLIMBUS_4_RX, 1, 1},
514         [SLIMBUS_5_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX,
515                                 SLIMBUS_5_RX, 1, 1},
516         [SLIMBUS_6_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX,
517                                 SLIMBUS_6_RX, 1, 1},
518         [PRIMARY_MI2S_RX] = { AFE_PORT_ID_PRIMARY_MI2S_RX,
519                                 PRIMARY_MI2S_RX, 1, 1},
520         [PRIMARY_MI2S_TX] = { AFE_PORT_ID_PRIMARY_MI2S_TX,
521                                 PRIMARY_MI2S_RX, 0, 1},
522         [SECONDARY_MI2S_RX] = { AFE_PORT_ID_SECONDARY_MI2S_RX,
523                                 SECONDARY_MI2S_RX, 1, 1},
524         [SECONDARY_MI2S_TX] = { AFE_PORT_ID_SECONDARY_MI2S_TX,
525                                 SECONDARY_MI2S_TX, 0, 1},
526         [TERTIARY_MI2S_RX] = { AFE_PORT_ID_TERTIARY_MI2S_RX,
527                                 TERTIARY_MI2S_RX, 1, 1},
528         [TERTIARY_MI2S_TX] = { AFE_PORT_ID_TERTIARY_MI2S_TX,
529                                 TERTIARY_MI2S_TX, 0, 1},
530         [QUATERNARY_MI2S_RX] = { AFE_PORT_ID_QUATERNARY_MI2S_RX,
531                                 QUATERNARY_MI2S_RX, 1, 1},
532         [QUATERNARY_MI2S_TX] = { AFE_PORT_ID_QUATERNARY_MI2S_TX,
533                                 QUATERNARY_MI2S_TX, 0, 1},
534         [PRIMARY_TDM_RX_0] =  { AFE_PORT_ID_PRIMARY_TDM_RX,
535                                 PRIMARY_TDM_RX_0, 1, 1},
536         [PRIMARY_TDM_TX_0] =  { AFE_PORT_ID_PRIMARY_TDM_TX,
537                                 PRIMARY_TDM_TX_0, 0, 1},
538         [PRIMARY_TDM_RX_1] =  { AFE_PORT_ID_PRIMARY_TDM_RX_1,
539                                 PRIMARY_TDM_RX_1, 1, 1},
540         [PRIMARY_TDM_TX_1] =  { AFE_PORT_ID_PRIMARY_TDM_TX_1,
541                                 PRIMARY_TDM_TX_1, 0, 1},
542         [PRIMARY_TDM_RX_2] =  { AFE_PORT_ID_PRIMARY_TDM_RX_2,
543                                 PRIMARY_TDM_RX_2, 1, 1},
544         [PRIMARY_TDM_TX_2] =  { AFE_PORT_ID_PRIMARY_TDM_TX_2,
545                                 PRIMARY_TDM_TX_2, 0, 1},
546         [PRIMARY_TDM_RX_3] =  { AFE_PORT_ID_PRIMARY_TDM_RX_3,
547                                 PRIMARY_TDM_RX_3, 1, 1},
548         [PRIMARY_TDM_TX_3] =  { AFE_PORT_ID_PRIMARY_TDM_TX_3,
549                                 PRIMARY_TDM_TX_3, 0, 1},
550         [PRIMARY_TDM_RX_4] =  { AFE_PORT_ID_PRIMARY_TDM_RX_4,
551                                 PRIMARY_TDM_RX_4, 1, 1},
552         [PRIMARY_TDM_TX_4] =  { AFE_PORT_ID_PRIMARY_TDM_TX_4,
553                                 PRIMARY_TDM_TX_4, 0, 1},
554         [PRIMARY_TDM_RX_5] =  { AFE_PORT_ID_PRIMARY_TDM_RX_5,
555                                 PRIMARY_TDM_RX_5, 1, 1},
556         [PRIMARY_TDM_TX_5] =  { AFE_PORT_ID_PRIMARY_TDM_TX_5,
557                                 PRIMARY_TDM_TX_5, 0, 1},
558         [PRIMARY_TDM_RX_6] =  { AFE_PORT_ID_PRIMARY_TDM_RX_6,
559                                 PRIMARY_TDM_RX_6, 1, 1},
560         [PRIMARY_TDM_TX_6] =  { AFE_PORT_ID_PRIMARY_TDM_TX_6,
561                                 PRIMARY_TDM_TX_6, 0, 1},
562         [PRIMARY_TDM_RX_7] =  { AFE_PORT_ID_PRIMARY_TDM_RX_7,
563                                 PRIMARY_TDM_RX_7, 1, 1},
564         [PRIMARY_TDM_TX_7] =  { AFE_PORT_ID_PRIMARY_TDM_TX_7,
565                                 PRIMARY_TDM_TX_7, 0, 1},
566         [SECONDARY_TDM_RX_0] =  { AFE_PORT_ID_SECONDARY_TDM_RX,
567                                 SECONDARY_TDM_RX_0, 1, 1},
568         [SECONDARY_TDM_TX_0] =  { AFE_PORT_ID_SECONDARY_TDM_TX,
569                                 SECONDARY_TDM_TX_0, 0, 1},
570         [SECONDARY_TDM_RX_1] =  { AFE_PORT_ID_SECONDARY_TDM_RX_1,
571                                 SECONDARY_TDM_RX_1, 1, 1},
572         [SECONDARY_TDM_TX_1] =  { AFE_PORT_ID_SECONDARY_TDM_TX_1,
573                                 SECONDARY_TDM_TX_1, 0, 1},
574         [SECONDARY_TDM_RX_2] =  { AFE_PORT_ID_SECONDARY_TDM_RX_2,
575                                 SECONDARY_TDM_RX_2, 1, 1},
576         [SECONDARY_TDM_TX_2] =  { AFE_PORT_ID_SECONDARY_TDM_TX_2,
577                                 SECONDARY_TDM_TX_2, 0, 1},
578         [SECONDARY_TDM_RX_3] =  { AFE_PORT_ID_SECONDARY_TDM_RX_3,
579                                 SECONDARY_TDM_RX_3, 1, 1},
580         [SECONDARY_TDM_TX_3] =  { AFE_PORT_ID_SECONDARY_TDM_TX_3,
581                                 SECONDARY_TDM_TX_3, 0, 1},
582         [SECONDARY_TDM_RX_4] =  { AFE_PORT_ID_SECONDARY_TDM_RX_4,
583                                 SECONDARY_TDM_RX_4, 1, 1},
584         [SECONDARY_TDM_TX_4] =  { AFE_PORT_ID_SECONDARY_TDM_TX_4,
585                                 SECONDARY_TDM_TX_4, 0, 1},
586         [SECONDARY_TDM_RX_5] =  { AFE_PORT_ID_SECONDARY_TDM_RX_5,
587                                 SECONDARY_TDM_RX_5, 1, 1},
588         [SECONDARY_TDM_TX_5] =  { AFE_PORT_ID_SECONDARY_TDM_TX_5,
589                                 SECONDARY_TDM_TX_5, 0, 1},
590         [SECONDARY_TDM_RX_6] =  { AFE_PORT_ID_SECONDARY_TDM_RX_6,
591                                 SECONDARY_TDM_RX_6, 1, 1},
592         [SECONDARY_TDM_TX_6] =  { AFE_PORT_ID_SECONDARY_TDM_TX_6,
593                                 SECONDARY_TDM_TX_6, 0, 1},
594         [SECONDARY_TDM_RX_7] =  { AFE_PORT_ID_SECONDARY_TDM_RX_7,
595                                 SECONDARY_TDM_RX_7, 1, 1},
596         [SECONDARY_TDM_TX_7] =  { AFE_PORT_ID_SECONDARY_TDM_TX_7,
597                                 SECONDARY_TDM_TX_7, 0, 1},
598         [TERTIARY_TDM_RX_0] =  { AFE_PORT_ID_TERTIARY_TDM_RX,
599                                 TERTIARY_TDM_RX_0, 1, 1},
600         [TERTIARY_TDM_TX_0] =  { AFE_PORT_ID_TERTIARY_TDM_TX,
601                                 TERTIARY_TDM_TX_0, 0, 1},
602         [TERTIARY_TDM_RX_1] =  { AFE_PORT_ID_TERTIARY_TDM_RX_1,
603                                 TERTIARY_TDM_RX_1, 1, 1},
604         [TERTIARY_TDM_TX_1] =  { AFE_PORT_ID_TERTIARY_TDM_TX_1,
605                                 TERTIARY_TDM_TX_1, 0, 1},
606         [TERTIARY_TDM_RX_2] =  { AFE_PORT_ID_TERTIARY_TDM_RX_2,
607                                 TERTIARY_TDM_RX_2, 1, 1},
608         [TERTIARY_TDM_TX_2] =  { AFE_PORT_ID_TERTIARY_TDM_TX_2,
609                                 TERTIARY_TDM_TX_2, 0, 1},
610         [TERTIARY_TDM_RX_3] =  { AFE_PORT_ID_TERTIARY_TDM_RX_3,
611                                 TERTIARY_TDM_RX_3, 1, 1},
612         [TERTIARY_TDM_TX_3] =  { AFE_PORT_ID_TERTIARY_TDM_TX_3,
613                                 TERTIARY_TDM_TX_3, 0, 1},
614         [TERTIARY_TDM_RX_4] =  { AFE_PORT_ID_TERTIARY_TDM_RX_4,
615                                 TERTIARY_TDM_RX_4, 1, 1},
616         [TERTIARY_TDM_TX_4] =  { AFE_PORT_ID_TERTIARY_TDM_TX_4,
617                                 TERTIARY_TDM_TX_4, 0, 1},
618         [TERTIARY_TDM_RX_5] =  { AFE_PORT_ID_TERTIARY_TDM_RX_5,
619                                 TERTIARY_TDM_RX_5, 1, 1},
620         [TERTIARY_TDM_TX_5] =  { AFE_PORT_ID_TERTIARY_TDM_TX_5,
621                                 TERTIARY_TDM_TX_5, 0, 1},
622         [TERTIARY_TDM_RX_6] =  { AFE_PORT_ID_TERTIARY_TDM_RX_6,
623                                 TERTIARY_TDM_RX_6, 1, 1},
624         [TERTIARY_TDM_TX_6] =  { AFE_PORT_ID_TERTIARY_TDM_TX_6,
625                                 TERTIARY_TDM_TX_6, 0, 1},
626         [TERTIARY_TDM_RX_7] =  { AFE_PORT_ID_TERTIARY_TDM_RX_7,
627                                 TERTIARY_TDM_RX_7, 1, 1},
628         [TERTIARY_TDM_TX_7] =  { AFE_PORT_ID_TERTIARY_TDM_TX_7,
629                                 TERTIARY_TDM_TX_7, 0, 1},
630         [QUATERNARY_TDM_RX_0] =  { AFE_PORT_ID_QUATERNARY_TDM_RX,
631                                 QUATERNARY_TDM_RX_0, 1, 1},
632         [QUATERNARY_TDM_TX_0] =  { AFE_PORT_ID_QUATERNARY_TDM_TX,
633                                 QUATERNARY_TDM_TX_0, 0, 1},
634         [QUATERNARY_TDM_RX_1] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_1,
635                                 QUATERNARY_TDM_RX_1, 1, 1},
636         [QUATERNARY_TDM_TX_1] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_1,
637                                 QUATERNARY_TDM_TX_1, 0, 1},
638         [QUATERNARY_TDM_RX_2] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_2,
639                                 QUATERNARY_TDM_RX_2, 1, 1},
640         [QUATERNARY_TDM_TX_2] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_2,
641                                 QUATERNARY_TDM_TX_2, 0, 1},
642         [QUATERNARY_TDM_RX_3] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_3,
643                                 QUATERNARY_TDM_RX_3, 1, 1},
644         [QUATERNARY_TDM_TX_3] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_3,
645                                 QUATERNARY_TDM_TX_3, 0, 1},
646         [QUATERNARY_TDM_RX_4] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_4,
647                                 QUATERNARY_TDM_RX_4, 1, 1},
648         [QUATERNARY_TDM_TX_4] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_4,
649                                 QUATERNARY_TDM_TX_4, 0, 1},
650         [QUATERNARY_TDM_RX_5] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_5,
651                                 QUATERNARY_TDM_RX_5, 1, 1},
652         [QUATERNARY_TDM_TX_5] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_5,
653                                 QUATERNARY_TDM_TX_5, 0, 1},
654         [QUATERNARY_TDM_RX_6] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_6,
655                                 QUATERNARY_TDM_RX_6, 1, 1},
656         [QUATERNARY_TDM_TX_6] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_6,
657                                 QUATERNARY_TDM_TX_6, 0, 1},
658         [QUATERNARY_TDM_RX_7] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_7,
659                                 QUATERNARY_TDM_RX_7, 1, 1},
660         [QUATERNARY_TDM_TX_7] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_7,
661                                 QUATERNARY_TDM_TX_7, 0, 1},
662         [QUINARY_TDM_RX_0] =  { AFE_PORT_ID_QUINARY_TDM_RX,
663                                 QUINARY_TDM_RX_0, 1, 1},
664         [QUINARY_TDM_TX_0] =  { AFE_PORT_ID_QUINARY_TDM_TX,
665                                 QUINARY_TDM_TX_0, 0, 1},
666         [QUINARY_TDM_RX_1] =  { AFE_PORT_ID_QUINARY_TDM_RX_1,
667                                 QUINARY_TDM_RX_1, 1, 1},
668         [QUINARY_TDM_TX_1] =  { AFE_PORT_ID_QUINARY_TDM_TX_1,
669                                 QUINARY_TDM_TX_1, 0, 1},
670         [QUINARY_TDM_RX_2] =  { AFE_PORT_ID_QUINARY_TDM_RX_2,
671                                 QUINARY_TDM_RX_2, 1, 1},
672         [QUINARY_TDM_TX_2] =  { AFE_PORT_ID_QUINARY_TDM_TX_2,
673                                 QUINARY_TDM_TX_2, 0, 1},
674         [QUINARY_TDM_RX_3] =  { AFE_PORT_ID_QUINARY_TDM_RX_3,
675                                 QUINARY_TDM_RX_3, 1, 1},
676         [QUINARY_TDM_TX_3] =  { AFE_PORT_ID_QUINARY_TDM_TX_3,
677                                 QUINARY_TDM_TX_3, 0, 1},
678         [QUINARY_TDM_RX_4] =  { AFE_PORT_ID_QUINARY_TDM_RX_4,
679                                 QUINARY_TDM_RX_4, 1, 1},
680         [QUINARY_TDM_TX_4] =  { AFE_PORT_ID_QUINARY_TDM_TX_4,
681                                 QUINARY_TDM_TX_4, 0, 1},
682         [QUINARY_TDM_RX_5] =  { AFE_PORT_ID_QUINARY_TDM_RX_5,
683                                 QUINARY_TDM_RX_5, 1, 1},
684         [QUINARY_TDM_TX_5] =  { AFE_PORT_ID_QUINARY_TDM_TX_5,
685                                 QUINARY_TDM_TX_5, 0, 1},
686         [QUINARY_TDM_RX_6] =  { AFE_PORT_ID_QUINARY_TDM_RX_6,
687                                 QUINARY_TDM_RX_6, 1, 1},
688         [QUINARY_TDM_TX_6] =  { AFE_PORT_ID_QUINARY_TDM_TX_6,
689                                 QUINARY_TDM_TX_6, 0, 1},
690         [QUINARY_TDM_RX_7] =  { AFE_PORT_ID_QUINARY_TDM_RX_7,
691                                 QUINARY_TDM_RX_7, 1, 1},
692         [QUINARY_TDM_TX_7] =  { AFE_PORT_ID_QUINARY_TDM_TX_7,
693                                 QUINARY_TDM_TX_7, 0, 1},
694 };
695 
696 static void q6afe_port_free(struct kref *ref)
697 {
698         struct q6afe_port *port;
699         struct q6afe *afe;
700         unsigned long flags;
701 
702         port = container_of(ref, struct q6afe_port, refcount);
703         afe = port->afe;
704         spin_lock_irqsave(&afe->port_list_lock, flags);
705         list_del(&port->node);
706         spin_unlock_irqrestore(&afe->port_list_lock, flags);
707         kfree(port->scfg);
708         kfree(port);
709 }
710 
711 static struct q6afe_port *q6afe_find_port(struct q6afe *afe, int token)
712 {
713         struct q6afe_port *p = NULL;
714         struct q6afe_port *ret = NULL;
715         unsigned long flags;
716 
717         spin_lock_irqsave(&afe->port_list_lock, flags);
718         list_for_each_entry(p, &afe->port_list, node)
719                 if (p->token == token) {
720                         ret = p;
721                         kref_get(&p->refcount);
722                         break;
723                 }
724 
725         spin_unlock_irqrestore(&afe->port_list_lock, flags);
726         return ret;
727 }
728 
729 static int q6afe_callback(struct apr_device *adev, struct apr_resp_pkt *data)
730 {
731         struct q6afe *afe = dev_get_drvdata(&adev->dev);
732         struct aprv2_ibasic_rsp_result_t *res;
733         struct apr_hdr *hdr = &data->hdr;
734         struct q6afe_port *port;
735 
736         if (!data->payload_size)
737                 return 0;
738 
739         res = data->payload;
740         switch (hdr->opcode) {
741         case APR_BASIC_RSP_RESULT: {
742                 if (res->status) {
743                         dev_err(afe->dev, "cmd = 0x%x returned error = 0x%x\n",
744                                 res->opcode, res->status);
745                 }
746                 switch (res->opcode) {
747                 case AFE_PORT_CMD_SET_PARAM_V2:
748                 case AFE_PORT_CMD_DEVICE_STOP:
749                 case AFE_PORT_CMD_DEVICE_START:
750                 case AFE_SVC_CMD_SET_PARAM:
751                         port = q6afe_find_port(afe, hdr->token);
752                         if (port) {
753                                 port->result = *res;
754                                 wake_up(&port->wait);
755                                 kref_put(&port->refcount, q6afe_port_free);
756                         }
757                         break;
758                 default:
759                         dev_err(afe->dev, "Unknown cmd 0x%x\n", res->opcode);
760                         break;
761                 }
762         }
763                 break;
764         default:
765                 break;
766         }
767 
768         return 0;
769 }
770 
771 /**
772  * q6afe_get_port_id() - Get port id from a given port index
773  *
774  * @index: port index
775  *
776  * Return: Will be an negative on error or valid port_id on success
777  */
778 int q6afe_get_port_id(int index)
779 {
780         if (index < 0 || index >= AFE_PORT_MAX)
781                 return -EINVAL;
782 
783         return port_maps[index].port_id;
784 }
785 EXPORT_SYMBOL_GPL(q6afe_get_port_id);
786 
787 static int afe_apr_send_pkt(struct q6afe *afe, struct apr_pkt *pkt,
788                             struct q6afe_port *port)
789 {
790         wait_queue_head_t *wait = &port->wait;
791         struct apr_hdr *hdr = &pkt->hdr;
792         int ret;
793 
794         mutex_lock(&afe->lock);
795         port->result.opcode = 0;
796         port->result.status = 0;
797 
798         ret = apr_send_pkt(afe->apr, pkt);
799         if (ret < 0) {
800                 dev_err(afe->dev, "packet not transmitted (%d)\n", ret);
801                 ret = -EINVAL;
802                 goto err;
803         }
804 
805         ret = wait_event_timeout(*wait, (port->result.opcode == hdr->opcode),
806                                  msecs_to_jiffies(TIMEOUT_MS));
807         if (!ret) {
808                 ret = -ETIMEDOUT;
809         } else if (port->result.status > 0) {
810                 dev_err(afe->dev, "DSP returned error[%x]\n",
811                         port->result.status);
812                 ret = -EINVAL;
813         } else {
814                 ret = 0;
815         }
816 
817 err:
818         mutex_unlock(&afe->lock);
819 
820         return ret;
821 }
822 
823 static int q6afe_port_set_param(struct q6afe_port *port, void *data,
824                                 int param_id, int module_id, int psize)
825 {
826         struct afe_svc_cmd_set_param *param;
827         struct afe_port_param_data_v2 *pdata;
828         struct q6afe *afe = port->afe;
829         struct apr_pkt *pkt;
830         u16 port_id = port->id;
831         int ret, pkt_size;
832         void *p, *pl;
833 
834         pkt_size = APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata) + psize;
835         p = kzalloc(pkt_size, GFP_KERNEL);
836         if (!p)
837                 return -ENOMEM;
838 
839         pkt = p;
840         param = p + APR_HDR_SIZE;
841         pdata = p + APR_HDR_SIZE + sizeof(*param);
842         pl = p + APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata);
843         memcpy(pl, data, psize);
844 
845         pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
846                                            APR_HDR_LEN(APR_HDR_SIZE),
847                                            APR_PKT_VER);
848         pkt->hdr.pkt_size = pkt_size;
849         pkt->hdr.src_port = 0;
850         pkt->hdr.dest_port = 0;
851         pkt->hdr.token = port->token;
852         pkt->hdr.opcode = AFE_SVC_CMD_SET_PARAM;
853 
854         param->payload_size = sizeof(*pdata) + psize;
855         param->payload_address_lsw = 0x00;
856         param->payload_address_msw = 0x00;
857         param->mem_map_handle = 0x00;
858         pdata->module_id = module_id;
859         pdata->param_id = param_id;
860         pdata->param_size = psize;
861 
862         ret = afe_apr_send_pkt(afe, pkt, port);
863         if (ret)
864                 dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
865                        port_id, ret);
866 
867         kfree(pkt);
868         return ret;
869 }
870 
871 static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data,
872                                    int param_id, int module_id, int psize)
873 {
874         struct afe_port_cmd_set_param_v2 *param;
875         struct afe_port_param_data_v2 *pdata;
876         struct q6afe *afe = port->afe;
877         struct apr_pkt *pkt;
878         u16 port_id = port->id;
879         int ret, pkt_size;
880         void *p, *pl;
881 
882         pkt_size = APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata) + psize;
883         p = kzalloc(pkt_size, GFP_KERNEL);
884         if (!p)
885                 return -ENOMEM;
886 
887         pkt = p;
888         param = p + APR_HDR_SIZE;
889         pdata = p + APR_HDR_SIZE + sizeof(*param);
890         pl = p + APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata);
891         memcpy(pl, data, psize);
892 
893         pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
894                                            APR_HDR_LEN(APR_HDR_SIZE),
895                                            APR_PKT_VER);
896         pkt->hdr.pkt_size = pkt_size;
897         pkt->hdr.src_port = 0;
898         pkt->hdr.dest_port = 0;
899         pkt->hdr.token = port->token;
900         pkt->hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
901 
902         param->port_id = port_id;
903         param->payload_size = sizeof(*pdata) + psize;
904         param->payload_address_lsw = 0x00;
905         param->payload_address_msw = 0x00;
906         param->mem_map_handle = 0x00;
907         pdata->module_id = module_id;
908         pdata->param_id = param_id;
909         pdata->param_size = psize;
910 
911         ret = afe_apr_send_pkt(afe, pkt, port);
912         if (ret)
913                 dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
914                        port_id, ret);
915 
916         kfree(pkt);
917         return ret;
918 }
919 
920 static int q6afe_set_lpass_clock(struct q6afe_port *port,
921                                  struct afe_clk_cfg *cfg)
922 {
923         return q6afe_port_set_param_v2(port, cfg,
924                                        AFE_PARAM_ID_LPAIF_CLK_CONFIG,
925                                        AFE_MODULE_AUDIO_DEV_INTERFACE,
926                                        sizeof(*cfg));
927 }
928 
929 static int q6afe_set_lpass_clock_v2(struct q6afe_port *port,
930                                  struct afe_clk_set *cfg)
931 {
932         return q6afe_port_set_param(port, cfg, AFE_PARAM_ID_CLOCK_SET,
933                                     AFE_MODULE_CLOCK_SET, sizeof(*cfg));
934 }
935 
936 static int q6afe_set_digital_codec_core_clock(struct q6afe_port *port,
937                                               struct afe_digital_clk_cfg *cfg)
938 {
939         return q6afe_port_set_param_v2(port, cfg,
940                                        AFE_PARAM_ID_INT_DIGITAL_CDC_CLK_CONFIG,
941                                        AFE_MODULE_AUDIO_DEV_INTERFACE,
942                                        sizeof(*cfg));
943 }
944 
945 int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id,
946                           int clk_src, int clk_root,
947                           unsigned int freq, int dir)
948 {
949         struct afe_clk_cfg ccfg = {0,};
950         struct afe_clk_set cset = {0,};
951         struct afe_digital_clk_cfg dcfg = {0,};
952         int ret;
953 
954         switch (clk_id) {
955         case LPAIF_DIG_CLK:
956                 dcfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
957                 dcfg.clk_val = freq;
958                 dcfg.clk_root = clk_root;
959                 ret = q6afe_set_digital_codec_core_clock(port, &dcfg);
960                 break;
961         case LPAIF_BIT_CLK:
962                 ccfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
963                 ccfg.clk_val1 = freq;
964                 ccfg.clk_src = clk_src;
965                 ccfg.clk_root = clk_root;
966                 ccfg.clk_set_mode = Q6AFE_LPASS_MODE_CLK1_VALID;
967                 ret = q6afe_set_lpass_clock(port, &ccfg);
968                 break;
969 
970         case LPAIF_OSR_CLK:
971                 ccfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
972                 ccfg.clk_val2 = freq;
973                 ccfg.clk_src = clk_src;
974                 ccfg.clk_root = clk_root;
975                 ccfg.clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID;
976                 ret = q6afe_set_lpass_clock(port, &ccfg);
977                 break;
978         case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR:
979         case Q6AFE_LPASS_CLK_ID_MCLK_1 ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1:
980         case Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT ... Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT:
981                 cset.clk_set_minor_version = AFE_API_VERSION_CLOCK_SET;
982                 cset.clk_id = clk_id;
983                 cset.clk_freq_in_hz = freq;
984                 cset.clk_attri = clk_src;
985                 cset.clk_root = clk_root;
986                 cset.enable = !!freq;
987                 ret = q6afe_set_lpass_clock_v2(port, &cset);
988                 break;
989         default:
990                 ret = -EINVAL;
991                 break;
992         }
993 
994         return ret;
995 }
996 EXPORT_SYMBOL_GPL(q6afe_port_set_sysclk);
997 
998 /**
999  * q6afe_port_stop() - Stop a afe port
1000  *
1001  * @port: Instance of port to stop
1002  *
1003  * Return: Will be an negative on packet size on success.
1004  */
1005 int q6afe_port_stop(struct q6afe_port *port)
1006 {
1007         struct afe_port_cmd_device_stop *stop;
1008         struct q6afe *afe = port->afe;
1009         struct apr_pkt *pkt;
1010         int port_id = port->id;
1011         int ret = 0;
1012         int index, pkt_size;
1013         void *p;
1014 
1015         port_id = port->id;
1016         index = port->token;
1017         if (index < 0 || index >= AFE_PORT_MAX) {
1018                 dev_err(afe->dev, "AFE port index[%d] invalid!\n", index);
1019                 return -EINVAL;
1020         }
1021 
1022         pkt_size = APR_HDR_SIZE + sizeof(*stop);
1023         p = kzalloc(pkt_size, GFP_KERNEL);
1024         if (!p)
1025                 return -ENOMEM;
1026 
1027         pkt = p;
1028         stop = p + APR_HDR_SIZE;
1029 
1030         pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1031                                            APR_HDR_LEN(APR_HDR_SIZE),
1032                                            APR_PKT_VER);
1033         pkt->hdr.pkt_size = pkt_size;
1034         pkt->hdr.src_port = 0;
1035         pkt->hdr.dest_port = 0;
1036         pkt->hdr.token = index;
1037         pkt->hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
1038         stop->port_id = port_id;
1039         stop->reserved = 0;
1040 
1041         ret = afe_apr_send_pkt(afe, pkt, port);
1042         if (ret)
1043                 dev_err(afe->dev, "AFE close failed %d\n", ret);
1044 
1045         kfree(pkt);
1046         return ret;
1047 }
1048 EXPORT_SYMBOL_GPL(q6afe_port_stop);
1049 
1050 /**
1051  * q6afe_slim_port_prepare() - Prepare slim afe port.
1052  *
1053  * @port: Instance of afe port
1054  * @cfg: SLIM configuration for the afe port
1055  *
1056  */
1057 void q6afe_slim_port_prepare(struct q6afe_port *port,
1058                              struct q6afe_slim_cfg *cfg)
1059 {
1060         union afe_port_config *pcfg = &port->port_cfg;
1061 
1062         pcfg->slim_cfg.sb_cfg_minor_version = AFE_API_VERSION_SLIMBUS_CONFIG;
1063         pcfg->slim_cfg.sample_rate = cfg->sample_rate;
1064         pcfg->slim_cfg.bit_width = cfg->bit_width;
1065         pcfg->slim_cfg.num_channels = cfg->num_channels;
1066         pcfg->slim_cfg.data_format = cfg->data_format;
1067         pcfg->slim_cfg.shared_ch_mapping[0] = cfg->ch_mapping[0];
1068         pcfg->slim_cfg.shared_ch_mapping[1] = cfg->ch_mapping[1];
1069         pcfg->slim_cfg.shared_ch_mapping[2] = cfg->ch_mapping[2];
1070         pcfg->slim_cfg.shared_ch_mapping[3] = cfg->ch_mapping[3];
1071 
1072 }
1073 EXPORT_SYMBOL_GPL(q6afe_slim_port_prepare);
1074 
1075 /**
1076  * q6afe_tdm_port_prepare() - Prepare tdm afe port.
1077  *
1078  * @port: Instance of afe port
1079  * @cfg: TDM configuration for the afe port
1080  *
1081  */
1082 void q6afe_tdm_port_prepare(struct q6afe_port *port,
1083                              struct q6afe_tdm_cfg *cfg)
1084 {
1085         union afe_port_config *pcfg = &port->port_cfg;
1086 
1087         pcfg->tdm_cfg.tdm_cfg_minor_version = AFE_API_VERSION_TDM_CONFIG;
1088         pcfg->tdm_cfg.num_channels = cfg->num_channels;
1089         pcfg->tdm_cfg.sample_rate = cfg->sample_rate;
1090         pcfg->tdm_cfg.bit_width = cfg->bit_width;
1091         pcfg->tdm_cfg.data_format = cfg->data_format;
1092         pcfg->tdm_cfg.sync_mode = cfg->sync_mode;
1093         pcfg->tdm_cfg.sync_src = cfg->sync_src;
1094         pcfg->tdm_cfg.nslots_per_frame = cfg->nslots_per_frame;
1095 
1096         pcfg->tdm_cfg.slot_width = cfg->slot_width;
1097         pcfg->tdm_cfg.slot_mask = cfg->slot_mask;
1098         port->scfg = kzalloc(sizeof(*port->scfg), GFP_KERNEL);
1099         if (!port->scfg)
1100                 return;
1101 
1102         port->scfg->minor_version = AFE_API_VERSION_SLOT_MAPPING_CONFIG;
1103         port->scfg->num_channels = cfg->num_channels;
1104         port->scfg->bitwidth = cfg->bit_width;
1105         port->scfg->data_align_type = cfg->data_align_type;
1106         memcpy(port->scfg->ch_mapping, cfg->ch_mapping,
1107                         sizeof(u16) * AFE_PORT_MAX_AUDIO_CHAN_CNT);
1108 }
1109 EXPORT_SYMBOL_GPL(q6afe_tdm_port_prepare);
1110 
1111 /**
1112  * q6afe_hdmi_port_prepare() - Prepare hdmi afe port.
1113  *
1114  * @port: Instance of afe port
1115  * @cfg: HDMI configuration for the afe port
1116  *
1117  */
1118 void q6afe_hdmi_port_prepare(struct q6afe_port *port,
1119                              struct q6afe_hdmi_cfg *cfg)
1120 {
1121         union afe_port_config *pcfg = &port->port_cfg;
1122 
1123         pcfg->hdmi_multi_ch.hdmi_cfg_minor_version =
1124                                         AFE_API_VERSION_HDMI_CONFIG;
1125         pcfg->hdmi_multi_ch.datatype = cfg->datatype;
1126         pcfg->hdmi_multi_ch.channel_allocation = cfg->channel_allocation;
1127         pcfg->hdmi_multi_ch.sample_rate = cfg->sample_rate;
1128         pcfg->hdmi_multi_ch.bit_width = cfg->bit_width;
1129 }
1130 EXPORT_SYMBOL_GPL(q6afe_hdmi_port_prepare);
1131 
1132 /**
1133  * q6afe_i2s_port_prepare() - Prepare i2s afe port.
1134  *
1135  * @port: Instance of afe port
1136  * @cfg: I2S configuration for the afe port
1137  * Return: Will be an negative on error and zero on success.
1138  */
1139 int q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg)
1140 {
1141         union afe_port_config *pcfg = &port->port_cfg;
1142         struct device *dev = port->afe->dev;
1143         int num_sd_lines;
1144 
1145         pcfg->i2s_cfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
1146         pcfg->i2s_cfg.sample_rate = cfg->sample_rate;
1147         pcfg->i2s_cfg.bit_width = cfg->bit_width;
1148         pcfg->i2s_cfg.data_format = AFE_LINEAR_PCM_DATA;
1149 
1150         switch (cfg->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1151         case SND_SOC_DAIFMT_CBS_CFS:
1152                 pcfg->i2s_cfg.ws_src = AFE_PORT_CONFIG_I2S_WS_SRC_INTERNAL;
1153                 break;
1154         case SND_SOC_DAIFMT_CBM_CFM:
1155                 /* CPU is slave */
1156                 pcfg->i2s_cfg.ws_src = AFE_PORT_CONFIG_I2S_WS_SRC_EXTERNAL;
1157                 break;
1158         default:
1159                 break;
1160         }
1161 
1162         num_sd_lines = hweight_long(cfg->sd_line_mask);
1163 
1164         switch (num_sd_lines) {
1165         case 0:
1166                 dev_err(dev, "no line is assigned\n");
1167                 return -EINVAL;
1168         case 1:
1169                 switch (cfg->sd_line_mask) {
1170                 case AFE_PORT_I2S_SD0_MASK:
1171                         pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD0;
1172                         break;
1173                 case AFE_PORT_I2S_SD1_MASK:
1174                         pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD1;
1175                         break;
1176                 case AFE_PORT_I2S_SD2_MASK:
1177                         pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD2;
1178                         break;
1179                 case AFE_PORT_I2S_SD3_MASK:
1180                         pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD3;
1181                         break;
1182                 default:
1183                         dev_err(dev, "Invalid SD lines\n");
1184                         return -EINVAL;
1185                 }
1186                 break;
1187         case 2:
1188                 switch (cfg->sd_line_mask) {
1189                 case AFE_PORT_I2S_SD0_1_MASK:
1190                         pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_QUAD01;
1191                         break;
1192                 case AFE_PORT_I2S_SD2_3_MASK:
1193                         pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_QUAD23;
1194                         break;
1195                 default:
1196                         dev_err(dev, "Invalid SD lines\n");
1197                         return -EINVAL;
1198                 }
1199                 break;
1200         case 3:
1201                 switch (cfg->sd_line_mask) {
1202                 case AFE_PORT_I2S_SD0_1_2_MASK:
1203                         pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_6CHS;
1204                         break;
1205                 default:
1206                         dev_err(dev, "Invalid SD lines\n");
1207                         return -EINVAL;
1208                 }
1209                 break;
1210         case 4:
1211                 switch (cfg->sd_line_mask) {
1212                 case AFE_PORT_I2S_SD0_1_2_3_MASK:
1213                         pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_8CHS;
1214 
1215                         break;
1216                 default:
1217                         dev_err(dev, "Invalid SD lines\n");
1218                         return -EINVAL;
1219                 }
1220                 break;
1221         default:
1222                 dev_err(dev, "Invalid SD lines\n");
1223                 return -EINVAL;
1224         }
1225 
1226         switch (cfg->num_channels) {
1227         case 1:
1228         case 2:
1229                 switch (pcfg->i2s_cfg.channel_mode) {
1230                 case AFE_PORT_I2S_QUAD01:
1231                 case AFE_PORT_I2S_6CHS:
1232                 case AFE_PORT_I2S_8CHS:
1233                         pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD0;
1234                         break;
1235                 case AFE_PORT_I2S_QUAD23:
1236                                 pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD2;
1237                         break;
1238                 }
1239 
1240                 if (cfg->num_channels == 2)
1241                         pcfg->i2s_cfg.mono_stereo = AFE_PORT_I2S_STEREO;
1242                 else
1243                         pcfg->i2s_cfg.mono_stereo = AFE_PORT_I2S_MONO;
1244 
1245                 break;
1246         case 3:
1247         case 4:
1248                 if (pcfg->i2s_cfg.channel_mode < AFE_PORT_I2S_QUAD01) {
1249                         dev_err(dev, "Invalid Channel mode\n");
1250                         return -EINVAL;
1251                 }
1252                 break;
1253         case 5:
1254         case 6:
1255                 if (pcfg->i2s_cfg.channel_mode < AFE_PORT_I2S_6CHS) {
1256                         dev_err(dev, "Invalid Channel mode\n");
1257                         return -EINVAL;
1258                 }
1259                 break;
1260         case 7:
1261         case 8:
1262                 if (pcfg->i2s_cfg.channel_mode < AFE_PORT_I2S_8CHS) {
1263                         dev_err(dev, "Invalid Channel mode\n");
1264                         return -EINVAL;
1265                 }
1266                 break;
1267         default:
1268                 break;
1269         }
1270 
1271         return 0;
1272 }
1273 EXPORT_SYMBOL_GPL(q6afe_i2s_port_prepare);
1274 
1275 /**
1276  * q6afe_port_start() - Start a afe port
1277  *
1278  * @port: Instance of port to start
1279  *
1280  * Return: Will be an negative on packet size on success.
1281  */
1282 int q6afe_port_start(struct q6afe_port *port)
1283 {
1284         struct afe_port_cmd_device_start *start;
1285         struct q6afe *afe = port->afe;
1286         int port_id = port->id;
1287         int ret, param_id = port->cfg_type;
1288         struct apr_pkt *pkt;
1289         int pkt_size;
1290         void *p;
1291 
1292         ret  = q6afe_port_set_param_v2(port, &port->port_cfg, param_id,
1293                                        AFE_MODULE_AUDIO_DEV_INTERFACE,
1294                                        sizeof(port->port_cfg));
1295         if (ret) {
1296                 dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
1297                         port_id, ret);
1298                 return ret;
1299         }
1300 
1301         if (port->scfg) {
1302                 ret  = q6afe_port_set_param_v2(port, port->scfg,
1303                                         AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG,
1304                                         AFE_MODULE_TDM, sizeof(*port->scfg));
1305                 if (ret) {
1306                         dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
1307                         port_id, ret);
1308                         return ret;
1309                 }
1310         }
1311 
1312         pkt_size = APR_HDR_SIZE + sizeof(*start);
1313         p = kzalloc(pkt_size, GFP_KERNEL);
1314         if (!p)
1315                 return -ENOMEM;
1316 
1317         pkt = p;
1318         start = p + APR_HDR_SIZE;
1319 
1320         pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1321                                             APR_HDR_LEN(APR_HDR_SIZE),
1322                                             APR_PKT_VER);
1323         pkt->hdr.pkt_size = pkt_size;
1324         pkt->hdr.src_port = 0;
1325         pkt->hdr.dest_port = 0;
1326         pkt->hdr.token = port->token;
1327         pkt->hdr.opcode = AFE_PORT_CMD_DEVICE_START;
1328 
1329         start->port_id = port_id;
1330 
1331         ret = afe_apr_send_pkt(afe, pkt, port);
1332         if (ret)
1333                 dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
1334                         port_id, ret);
1335 
1336         kfree(pkt);
1337         return ret;
1338 }
1339 EXPORT_SYMBOL_GPL(q6afe_port_start);
1340 
1341 /**
1342  * q6afe_port_get_from_id() - Get port instance from a port id
1343  *
1344  * @dev: Pointer to afe child device.
1345  * @id: port id
1346  *
1347  * Return: Will be an error pointer on error or a valid afe port
1348  * on success.
1349  */
1350 struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id)
1351 {
1352         int port_id;
1353         struct q6afe *afe = dev_get_drvdata(dev->parent);
1354         struct q6afe_port *port;
1355         unsigned long flags;
1356         int cfg_type;
1357 
1358         if (id < 0 || id >= AFE_PORT_MAX) {
1359                 dev_err(dev, "AFE port token[%d] invalid!\n", id);
1360                 return ERR_PTR(-EINVAL);
1361         }
1362 
1363         /* if port is multiple times bind/unbind before callback finishes */
1364         port = q6afe_find_port(afe, id);
1365         if (port) {
1366                 dev_err(dev, "AFE Port already open\n");
1367                 return port;
1368         }
1369 
1370         port_id = port_maps[id].port_id;
1371 
1372         switch (port_id) {
1373         case AFE_PORT_ID_MULTICHAN_HDMI_RX:
1374                 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
1375                 break;
1376         case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX:
1377         case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX:
1378         case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX:
1379         case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_RX:
1380         case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX:
1381         case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX:
1382         case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX:
1383                 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
1384                 break;
1385 
1386         case AFE_PORT_ID_PRIMARY_MI2S_RX:
1387         case AFE_PORT_ID_PRIMARY_MI2S_TX:
1388         case AFE_PORT_ID_SECONDARY_MI2S_RX:
1389         case AFE_PORT_ID_SECONDARY_MI2S_TX:
1390         case AFE_PORT_ID_TERTIARY_MI2S_RX:
1391         case AFE_PORT_ID_TERTIARY_MI2S_TX:
1392         case AFE_PORT_ID_QUATERNARY_MI2S_RX:
1393         case AFE_PORT_ID_QUATERNARY_MI2S_TX:
1394                 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
1395                 break;
1396         case AFE_PORT_ID_PRIMARY_TDM_RX ... AFE_PORT_ID_QUINARY_TDM_TX_7:
1397                 cfg_type = AFE_PARAM_ID_TDM_CONFIG;
1398                 break;
1399 
1400         default:
1401                 dev_err(dev, "Invalid port id 0x%x\n", port_id);
1402                 return ERR_PTR(-EINVAL);
1403         }
1404 
1405         port = kzalloc(sizeof(*port), GFP_KERNEL);
1406         if (!port)
1407                 return ERR_PTR(-ENOMEM);
1408 
1409         init_waitqueue_head(&port->wait);
1410 
1411         port->token = id;
1412         port->id = port_id;
1413         port->afe = afe;
1414         port->cfg_type = cfg_type;
1415         kref_init(&port->refcount);
1416 
1417         spin_lock_irqsave(&afe->port_list_lock, flags);
1418         list_add_tail(&port->node, &afe->port_list);
1419         spin_unlock_irqrestore(&afe->port_list_lock, flags);
1420 
1421         return port;
1422 
1423 }
1424 EXPORT_SYMBOL_GPL(q6afe_port_get_from_id);
1425 
1426 /**
1427  * q6afe_port_put() - Release port reference
1428  *
1429  * @port: Instance of port to put
1430  */
1431 void q6afe_port_put(struct q6afe_port *port)
1432 {
1433         kref_put(&port->refcount, q6afe_port_free);
1434 }
1435 EXPORT_SYMBOL_GPL(q6afe_port_put);
1436 
1437 static int q6afe_probe(struct apr_device *adev)
1438 {
1439         struct q6afe *afe;
1440         struct device *dev = &adev->dev;
1441         struct device_node *dais_np;
1442 
1443         afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL);
1444         if (!afe)
1445                 return -ENOMEM;
1446 
1447         q6core_get_svc_api_info(adev->svc_id, &afe->ainfo);
1448         afe->apr = adev;
1449         mutex_init(&afe->lock);
1450         afe->dev = dev;
1451         INIT_LIST_HEAD(&afe->port_list);
1452         spin_lock_init(&afe->port_list_lock);
1453 
1454         dev_set_drvdata(dev, afe);
1455 
1456         dais_np = of_get_child_by_name(dev->of_node, "dais");
1457         if (dais_np) {
1458                 afe->pdev_dais = of_platform_device_create(dais_np,
1459                                                            "q6afe-dai", dev);
1460                 of_node_put(dais_np);
1461         }
1462 
1463         return 0;
1464 }
1465 
1466 static int q6afe_remove(struct apr_device *adev)
1467 {
1468         struct q6afe *afe = dev_get_drvdata(&adev->dev);
1469 
1470         if (afe->pdev_dais)
1471                 of_platform_device_destroy(&afe->pdev_dais->dev, NULL);
1472 
1473         return 0;
1474 }
1475 
1476 static const struct of_device_id q6afe_device_id[]  = {
1477         { .compatible = "qcom,q6afe" },
1478         {},
1479 };
1480 MODULE_DEVICE_TABLE(of, q6afe_device_id);
1481 
1482 static struct apr_driver qcom_q6afe_driver = {
1483         .probe = q6afe_probe,
1484         .remove = q6afe_remove,
1485         .callback = q6afe_callback,
1486         .driver = {
1487                 .name = "qcom-q6afe",
1488                 .of_match_table = of_match_ptr(q6afe_device_id),
1489 
1490         },
1491 };
1492 
1493 module_apr_driver(qcom_q6afe_driver);
1494 MODULE_DESCRIPTION("Q6 Audio Front End");
1495 MODULE_LICENSE("GPL v2");
1496 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp