blob: e1ce947cba4841582ce3200890d87e322be65102 [file] [log] [blame]
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/slab.h>
13#include <linux/debugfs.h>
14#include <linux/kernel.h>
15#include <linux/kthread.h>
16#include <linux/uaccess.h>
17#include <linux/wait.h>
18#include <linux/wakelock.h>
19#include <linux/jiffies.h>
20#include <linux/sched.h>
21#include <linux/msm_audio_ion.h>
22#include <linux/delay.h>
23#include <sound/apr_audio-v2.h>
24#include <sound/q6afe-v2.h>
25#include <sound/q6audio-v2.h>
26#include "msm-pcm-routing-v2.h"
27#include <sound/audio_cal_utils.h>
28#include <sound/adsp_err.h>
29#include <linux/qdsp6v2/apr_tal.h>
30
31#define WAKELOCK_TIMEOUT 5000
32enum {
33 AFE_COMMON_RX_CAL = 0,
34 AFE_COMMON_TX_CAL,
35 AFE_AANC_CAL,
36 AFE_FB_SPKR_PROT_CAL,
37 AFE_HW_DELAY_CAL,
38 AFE_SIDETONE_CAL,
Siena Richardd83d83f2016-12-15 13:49:41 -080039 AFE_SIDETONE_IIR_CAL,
Banajit Goswami0530e2f2016-12-09 21:34:37 -080040 AFE_TOPOLOGY_CAL,
41 AFE_CUST_TOPOLOGY_CAL,
42 AFE_FB_SPKR_PROT_TH_VI_CAL,
43 AFE_FB_SPKR_PROT_EX_VI_CAL,
44 MAX_AFE_CAL_TYPES
45};
46
47enum fbsp_state {
48 FBSP_INCORRECT_OP_MODE,
49 FBSP_INACTIVE,
50 FBSP_WARMUP,
51 FBSP_IN_PROGRESS,
52 FBSP_SUCCESS,
53 FBSP_FAILED,
54 MAX_FBSP_STATE
55};
56
57static char fbsp_state[MAX_FBSP_STATE][50] = {
58 [FBSP_INCORRECT_OP_MODE] = "incorrect operation mode",
59 [FBSP_INACTIVE] = "port not started",
60 [FBSP_WARMUP] = "waiting for warmup",
61 [FBSP_IN_PROGRESS] = "in progress state",
62 [FBSP_SUCCESS] = "success",
63 [FBSP_FAILED] = "failed"
64};
65
66enum {
67 USE_CALIBRATED_R0TO,
68 USE_SAFE_R0TO
69};
70
71enum {
72 QUICK_CALIB_DISABLE,
73 QUICK_CALIB_ENABLE
74};
75
76enum {
77 Q6AFE_MSM_SPKR_PROCESSING = 0,
78 Q6AFE_MSM_SPKR_CALIBRATION,
79 Q6AFE_MSM_SPKR_FTM_MODE
80};
81
82struct wlock {
83 struct wakeup_source ws;
84};
85
86static struct wlock wl;
87
88struct afe_ctl {
89 void *apr;
90 atomic_t state;
91 atomic_t status;
92 wait_queue_head_t wait[AFE_MAX_PORTS];
93 struct task_struct *task;
94 void (*tx_cb)(uint32_t opcode,
95 uint32_t token, uint32_t *payload, void *priv);
96 void (*rx_cb)(uint32_t opcode,
97 uint32_t token, uint32_t *payload, void *priv);
98 void *tx_private_data;
99 void *rx_private_data;
100 uint32_t mmap_handle;
101
102 int topology[AFE_MAX_PORTS];
103 struct cal_type_data *cal_data[MAX_AFE_CAL_TYPES];
104
105 atomic_t mem_map_cal_handles[MAX_AFE_CAL_TYPES];
106 atomic_t mem_map_cal_index;
107 u32 afe_cal_mode[AFE_MAX_PORTS];
108
109 u16 dtmf_gen_rx_portid;
110 struct audio_cal_info_spk_prot_cfg prot_cfg;
111 struct afe_spkr_prot_calib_get_resp calib_data;
112 struct audio_cal_info_sp_th_vi_ftm_cfg th_ftm_cfg;
113 struct audio_cal_info_sp_ex_vi_ftm_cfg ex_ftm_cfg;
114 struct afe_sp_th_vi_get_param_resp th_vi_resp;
115 struct afe_sp_ex_vi_get_param_resp ex_vi_resp;
Manish Dewangan1903ffb2016-12-20 12:56:24 +0530116 struct afe_av_dev_drift_get_param_resp av_dev_drift_resp;
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800117 int vi_tx_port;
118 int vi_rx_port;
119 uint32_t afe_sample_rates[AFE_MAX_PORTS];
120 struct aanc_data aanc_info;
121 struct mutex afe_cmd_lock;
122 int set_custom_topology;
Siena Richard23364c92017-01-11 16:20:55 -0800123 int dev_acdb_id[AFE_MAX_PORTS];
124 routing_cb rt_cb;
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800125};
126
127static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
128static unsigned long afe_configured_cmd;
129
130static struct afe_ctl this_afe;
131
132#define TIMEOUT_MS 1000
133#define Q6AFE_MAX_VOLUME 0x3FFF
134
135static int pcm_afe_instance[2];
136static int proxy_afe_instance[2];
137bool afe_close_done[2] = {true, true};
138
139#define SIZEOF_CFG_CMD(y) \
140 (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
141
142static int afe_get_cal_hw_delay(int32_t path,
143 struct audio_cal_hw_delay_entry *entry);
144static int remap_cal_data(struct cal_block_data *cal_block, int cal_index);
145
146int afe_get_topology(int port_id)
147{
148 int topology;
149 int port_index = afe_get_port_index(port_id);
150
Xiaoyu Ye38ae2252017-01-26 18:20:06 -0800151 if ((port_index < 0) || (port_index >= AFE_MAX_PORTS)) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800152 pr_err("%s: Invalid port index %d\n", __func__, port_index);
153 topology = -EINVAL;
154 goto done;
155 }
156
157 topology = this_afe.topology[port_index];
158done:
159 return topology;
160}
161
162void afe_set_aanc_info(struct aanc_data *q6_aanc_info)
163{
164 this_afe.aanc_info.aanc_active = q6_aanc_info->aanc_active;
165 this_afe.aanc_info.aanc_rx_port = q6_aanc_info->aanc_rx_port;
166 this_afe.aanc_info.aanc_tx_port = q6_aanc_info->aanc_tx_port;
167
168 pr_debug("%s: aanc active is %d rx port is 0x%x, tx port is 0x%x\n",
169 __func__,
170 this_afe.aanc_info.aanc_active,
171 this_afe.aanc_info.aanc_rx_port,
172 this_afe.aanc_info.aanc_tx_port);
173}
174
175static void afe_callback_debug_print(struct apr_client_data *data)
176{
177 uint32_t *payload;
178
179 payload = data->payload;
180
181 if (data->payload_size >= 8)
182 pr_debug("%s: code = 0x%x PL#0[0x%x], PL#1[0x%x], size = %d\n",
183 __func__, data->opcode, payload[0], payload[1],
184 data->payload_size);
185 else if (data->payload_size >= 4)
186 pr_debug("%s: code = 0x%x PL#0[0x%x], size = %d\n",
187 __func__, data->opcode, payload[0],
188 data->payload_size);
189 else
190 pr_debug("%s: code = 0x%x, size = %d\n",
191 __func__, data->opcode, data->payload_size);
192}
193
Manish Dewangan1903ffb2016-12-20 12:56:24 +0530194static void av_dev_drift_afe_cb_handler(uint32_t *payload,
195 uint32_t payload_size)
196{
197 u32 param_id;
198 struct afe_av_dev_drift_get_param_resp *resp =
199 (struct afe_av_dev_drift_get_param_resp *) payload;
200
201 if (!(&(resp->pdata))) {
202 pr_err("%s: Error: resp pdata is NULL\n", __func__);
203 return;
204 }
205
206 param_id = resp->pdata.param_id;
207 if (param_id == AFE_PARAM_ID_DEV_TIMING_STATS) {
208 if (payload_size < sizeof(this_afe.av_dev_drift_resp)) {
209 pr_err("%s: Error: received size %d, resp size %zu\n",
210 __func__, payload_size,
211 sizeof(this_afe.av_dev_drift_resp));
212 return;
213 }
214 memcpy(&this_afe.av_dev_drift_resp, payload,
215 sizeof(this_afe.av_dev_drift_resp));
216 if (!this_afe.av_dev_drift_resp.status) {
217 atomic_set(&this_afe.state, 0);
218 } else {
219 pr_debug("%s: av_dev_drift_resp status: %d", __func__,
220 this_afe.av_dev_drift_resp.status);
221 atomic_set(&this_afe.state, -1);
222 }
223 }
224}
225
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800226static int32_t sp_make_afe_callback(uint32_t *payload, uint32_t payload_size)
227{
228 u32 param_id;
229 struct afe_spkr_prot_calib_get_resp *resp =
230 (struct afe_spkr_prot_calib_get_resp *) payload;
231
232 if (!(&(resp->pdata))) {
233 pr_err("%s: Error: resp pdata is NULL\n", __func__);
234 return -EINVAL;
235 }
236
237 param_id = resp->pdata.param_id;
238 if (param_id == AFE_PARAM_ID_CALIB_RES_CFG_V2) {
239 if (payload_size < sizeof(this_afe.calib_data)) {
240 pr_err("%s: Error: received size %d, calib_data size %zu\n",
241 __func__, payload_size,
242 sizeof(this_afe.calib_data));
243 return -EINVAL;
244 }
245 memcpy(&this_afe.calib_data, payload,
246 sizeof(this_afe.calib_data));
247 if (!this_afe.calib_data.status) {
248 atomic_set(&this_afe.state, 0);
249 } else {
250 pr_debug("%s: calib resp status: %d", __func__,
251 this_afe.calib_data.status);
252 atomic_set(&this_afe.state, -1);
253 }
254 }
255 if (param_id == AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS) {
256 if (payload_size < sizeof(this_afe.th_vi_resp)) {
257 pr_err("%s: Error: received size %d, th_vi_resp size %zu\n",
258 __func__, payload_size,
259 sizeof(this_afe.th_vi_resp));
260 return -EINVAL;
261 }
262 memcpy(&this_afe.th_vi_resp, payload,
263 sizeof(this_afe.th_vi_resp));
264 if (!this_afe.th_vi_resp.status) {
265 atomic_set(&this_afe.state, 0);
266 } else {
267 pr_debug("%s: th vi resp status: %d", __func__,
268 this_afe.th_vi_resp.status);
269 atomic_set(&this_afe.state, -1);
270 }
271 }
272 if (param_id == AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS) {
273 if (payload_size < sizeof(this_afe.ex_vi_resp)) {
274 pr_err("%s: Error: received size %d, ex_vi_resp size %zu\n",
275 __func__, payload_size,
276 sizeof(this_afe.ex_vi_resp));
277 return -EINVAL;
278 }
279 memcpy(&this_afe.ex_vi_resp, payload,
280 sizeof(this_afe.ex_vi_resp));
281 if (!this_afe.ex_vi_resp.status) {
282 atomic_set(&this_afe.state, 0);
283 } else {
284 pr_debug("%s: ex vi resp status: %d", __func__,
285 this_afe.ex_vi_resp.status);
286 atomic_set(&this_afe.state, -1);
287 }
288 }
289
290 return 0;
291}
292
293static int32_t afe_callback(struct apr_client_data *data, void *priv)
294{
295 if (!data) {
296 pr_err("%s: Invalid param data\n", __func__);
297 return -EINVAL;
298 }
299 if (data->opcode == RESET_EVENTS) {
300 pr_debug("%s: reset event = %d %d apr[%pK]\n",
301 __func__,
302 data->reset_event, data->reset_proc, this_afe.apr);
303
304 cal_utils_clear_cal_block_q6maps(MAX_AFE_CAL_TYPES,
305 this_afe.cal_data);
306
307 /* Reset the custom topology mode: to resend again to AFE. */
308 mutex_lock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
309 this_afe.set_custom_topology = 1;
310 mutex_unlock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
Vidyakumar Athota3cf42302017-02-06 13:53:10 -0800311 rtac_clear_mapping(AFE_RTAC_CAL);
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800312
313 if (this_afe.apr) {
314 apr_reset(this_afe.apr);
315 atomic_set(&this_afe.state, 0);
316 this_afe.apr = NULL;
317 rtac_set_afe_handle(this_afe.apr);
318 }
319 /* send info to user */
320 if (this_afe.task == NULL)
321 this_afe.task = current;
322 pr_debug("%s: task_name = %s pid = %d\n",
323 __func__,
324 this_afe.task->comm, this_afe.task->pid);
325
326 /*
327 * Pass reset events to proxy driver, if cb is registered
328 */
329 if (this_afe.tx_cb) {
330 this_afe.tx_cb(data->opcode, data->token,
331 data->payload,
332 this_afe.tx_private_data);
333 this_afe.tx_cb = NULL;
334 }
335 if (this_afe.rx_cb) {
336 this_afe.rx_cb(data->opcode, data->token,
337 data->payload,
338 this_afe.rx_private_data);
339 this_afe.rx_cb = NULL;
340 }
341
342 return 0;
343 }
344 afe_callback_debug_print(data);
345 if (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V2) {
Manish Dewangan1903ffb2016-12-20 12:56:24 +0530346 uint32_t *payload = data->payload;
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800347
348 if (!payload || (data->token >= AFE_MAX_PORTS)) {
349 pr_err("%s: Error: size %d payload %pK token %d\n",
350 __func__, data->payload_size,
351 payload, data->token);
352 return -EINVAL;
353 }
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800354
Manish Dewangan1903ffb2016-12-20 12:56:24 +0530355 if (payload[2] == AFE_PARAM_ID_DEV_TIMING_STATS) {
356 av_dev_drift_afe_cb_handler(data->payload,
357 data->payload_size);
358 } else {
359 if (rtac_make_afe_callback(data->payload,
360 data->payload_size))
361 return 0;
362
363 if (sp_make_afe_callback(data->payload,
364 data->payload_size))
365 return -EINVAL;
366 }
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800367 wake_up(&this_afe.wait[data->token]);
368 } else if (data->payload_size) {
369 uint32_t *payload;
370 uint16_t port_id = 0;
371
372 payload = data->payload;
373 if (data->opcode == APR_BASIC_RSP_RESULT) {
374 pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x token=%d\n",
375 __func__, data->opcode,
376 payload[0], payload[1], data->token);
377 /* payload[1] contains the error status for response */
378 if (payload[1] != 0) {
379 atomic_set(&this_afe.status, payload[1]);
380 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
381 __func__, payload[0], payload[1]);
382 }
383 switch (payload[0]) {
384 case AFE_PORT_CMD_SET_PARAM_V2:
385 if (rtac_make_afe_callback(payload,
386 data->payload_size))
387 return 0;
388 case AFE_PORT_CMD_DEVICE_STOP:
389 case AFE_PORT_CMD_DEVICE_START:
390 case AFE_PSEUDOPORT_CMD_START:
391 case AFE_PSEUDOPORT_CMD_STOP:
392 case AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS:
393 case AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS:
394 case AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER:
395 case AFE_PORTS_CMD_DTMF_CTL:
396 case AFE_SVC_CMD_SET_PARAM:
397 atomic_set(&this_afe.state, 0);
398 wake_up(&this_afe.wait[data->token]);
399 break;
400 case AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER:
401 break;
402 case AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2:
403 port_id = RT_PROXY_PORT_001_TX;
404 break;
405 case AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2:
406 port_id = RT_PROXY_PORT_001_RX;
407 break;
408 case AFE_CMD_ADD_TOPOLOGIES:
409 atomic_set(&this_afe.state, 0);
410 wake_up(&this_afe.wait[data->token]);
411 pr_debug("%s: AFE_CMD_ADD_TOPOLOGIES cmd 0x%x\n",
412 __func__, payload[1]);
413 break;
414 default:
415 pr_err("%s: Unknown cmd 0x%x\n", __func__,
416 payload[0]);
417 break;
418 }
419 } else if (data->opcode ==
420 AFE_SERVICE_CMDRSP_SHARED_MEM_MAP_REGIONS) {
421 pr_debug("%s: mmap_handle: 0x%x, cal index %d\n",
422 __func__, payload[0],
423 atomic_read(&this_afe.mem_map_cal_index));
424 if (atomic_read(&this_afe.mem_map_cal_index) != -1)
425 atomic_set(&this_afe.mem_map_cal_handles[
426 atomic_read(
427 &this_afe.mem_map_cal_index)],
428 (uint32_t)payload[0]);
429 else
430 this_afe.mmap_handle = payload[0];
431 atomic_set(&this_afe.state, 0);
432 wake_up(&this_afe.wait[data->token]);
433 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
434 port_id = (uint16_t)(0x0000FFFF & payload[0]);
435 }
436 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
437 switch (port_id) {
438 case RT_PROXY_PORT_001_TX: {
439 if (this_afe.tx_cb) {
440 this_afe.tx_cb(data->opcode, data->token,
441 data->payload,
442 this_afe.tx_private_data);
443 }
444 break;
445 }
446 case RT_PROXY_PORT_001_RX: {
447 if (this_afe.rx_cb) {
448 this_afe.rx_cb(data->opcode, data->token,
449 data->payload,
450 this_afe.rx_private_data);
451 }
452 break;
453 }
454 default:
455 pr_debug("%s: default case 0x%x\n", __func__, port_id);
456 break;
457 }
458 }
459 return 0;
460}
461
462int afe_get_port_type(u16 port_id)
463{
464 int ret;
465
466 switch (port_id) {
467 case PRIMARY_I2S_RX:
468 case SECONDARY_I2S_RX:
469 case MI2S_RX:
470 case HDMI_RX:
471 case DISPLAY_PORT_RX:
472 case AFE_PORT_ID_SPDIF_RX:
473 case SLIMBUS_0_RX:
474 case SLIMBUS_1_RX:
475 case SLIMBUS_2_RX:
476 case SLIMBUS_3_RX:
477 case SLIMBUS_4_RX:
478 case SLIMBUS_5_RX:
479 case SLIMBUS_6_RX:
480 case SLIMBUS_7_RX:
481 case SLIMBUS_8_RX:
482 case INT_BT_SCO_RX:
483 case INT_BT_A2DP_RX:
484 case INT_FM_RX:
485 case VOICE_PLAYBACK_TX:
486 case VOICE2_PLAYBACK_TX:
487 case RT_PROXY_PORT_001_RX:
488 case AUDIO_PORT_ID_I2S_RX:
489 case AFE_PORT_ID_PRIMARY_MI2S_RX:
490 case AFE_PORT_ID_SECONDARY_MI2S_RX:
491 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
492 case AFE_PORT_ID_TERTIARY_MI2S_RX:
493 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
494 case AFE_PORT_ID_QUINARY_MI2S_RX:
495 case AFE_PORT_ID_PRIMARY_PCM_RX:
496 case AFE_PORT_ID_SECONDARY_PCM_RX:
497 case AFE_PORT_ID_TERTIARY_PCM_RX:
498 case AFE_PORT_ID_QUATERNARY_PCM_RX:
499 case AFE_PORT_ID_PRIMARY_TDM_RX:
500 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
501 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
502 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
503 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
504 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
505 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
506 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
507 case AFE_PORT_ID_SECONDARY_TDM_RX:
508 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
509 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
510 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
511 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
512 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
513 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
514 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
515 case AFE_PORT_ID_TERTIARY_TDM_RX:
516 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
517 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
518 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
519 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
520 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
521 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
522 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
523 case AFE_PORT_ID_QUATERNARY_TDM_RX:
524 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
525 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
526 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
527 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
528 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
529 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
530 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
531 case AFE_PORT_ID_USB_RX:
532 case AFE_PORT_ID_INT0_MI2S_RX:
533 case AFE_PORT_ID_INT1_MI2S_RX:
534 case AFE_PORT_ID_INT2_MI2S_RX:
535 case AFE_PORT_ID_INT3_MI2S_RX:
536 case AFE_PORT_ID_INT4_MI2S_RX:
537 case AFE_PORT_ID_INT5_MI2S_RX:
538 case AFE_PORT_ID_INT6_MI2S_RX:
539 ret = MSM_AFE_PORT_TYPE_RX;
540 break;
541
542 case PRIMARY_I2S_TX:
543 case SECONDARY_I2S_TX:
544 case MI2S_TX:
545 case DIGI_MIC_TX:
546 case VOICE_RECORD_TX:
547 case SLIMBUS_0_TX:
548 case SLIMBUS_1_TX:
549 case SLIMBUS_2_TX:
550 case SLIMBUS_3_TX:
551 case SLIMBUS_4_TX:
552 case SLIMBUS_5_TX:
553 case SLIMBUS_6_TX:
554 case SLIMBUS_7_TX:
555 case SLIMBUS_8_TX:
556 case INT_FM_TX:
557 case VOICE_RECORD_RX:
558 case INT_BT_SCO_TX:
559 case RT_PROXY_PORT_001_TX:
560 case AFE_PORT_ID_PRIMARY_MI2S_TX:
561 case AFE_PORT_ID_SECONDARY_MI2S_TX:
562 case AFE_PORT_ID_TERTIARY_MI2S_TX:
563 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
564 case AFE_PORT_ID_QUINARY_MI2S_TX:
565 case AFE_PORT_ID_SENARY_MI2S_TX:
566 case AFE_PORT_ID_PRIMARY_PCM_TX:
567 case AFE_PORT_ID_SECONDARY_PCM_TX:
568 case AFE_PORT_ID_TERTIARY_PCM_TX:
569 case AFE_PORT_ID_QUATERNARY_PCM_TX:
570 case AFE_PORT_ID_PRIMARY_TDM_TX:
571 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
572 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
573 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
574 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
575 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
576 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
577 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
578 case AFE_PORT_ID_SECONDARY_TDM_TX:
579 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
580 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
581 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
582 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
583 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
584 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
585 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
586 case AFE_PORT_ID_TERTIARY_TDM_TX:
587 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
588 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
589 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
590 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
591 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
592 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
593 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
594 case AFE_PORT_ID_QUATERNARY_TDM_TX:
595 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
596 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
597 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
598 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
599 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
600 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
601 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
602 case AFE_PORT_ID_USB_TX:
603 case AFE_PORT_ID_INT0_MI2S_TX:
604 case AFE_PORT_ID_INT1_MI2S_TX:
605 case AFE_PORT_ID_INT2_MI2S_TX:
606 case AFE_PORT_ID_INT3_MI2S_TX:
607 case AFE_PORT_ID_INT4_MI2S_TX:
608 case AFE_PORT_ID_INT5_MI2S_TX:
609 case AFE_PORT_ID_INT6_MI2S_TX:
610 ret = MSM_AFE_PORT_TYPE_TX;
611 break;
612
613 default:
614 WARN_ON(1);
615 pr_err("%s: Invalid port id = 0x%x\n",
616 __func__, port_id);
617 ret = -EINVAL;
618 }
619
620 return ret;
621}
622
623int afe_sizeof_cfg_cmd(u16 port_id)
624{
625 int ret_size;
626
627 switch (port_id) {
628 case PRIMARY_I2S_RX:
629 case PRIMARY_I2S_TX:
630 case SECONDARY_I2S_RX:
631 case SECONDARY_I2S_TX:
632 case MI2S_RX:
633 case MI2S_TX:
634 case AFE_PORT_ID_PRIMARY_MI2S_RX:
635 case AFE_PORT_ID_PRIMARY_MI2S_TX:
636 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
637 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
638 case AFE_PORT_ID_QUINARY_MI2S_RX:
639 case AFE_PORT_ID_QUINARY_MI2S_TX:
640 ret_size = SIZEOF_CFG_CMD(afe_param_id_i2s_cfg);
641 break;
642 case HDMI_RX:
643 case DISPLAY_PORT_RX:
644 ret_size =
645 SIZEOF_CFG_CMD(afe_param_id_hdmi_multi_chan_audio_cfg);
646 break;
647 case SLIMBUS_0_RX:
648 case SLIMBUS_0_TX:
649 case SLIMBUS_1_RX:
650 case SLIMBUS_1_TX:
651 case SLIMBUS_2_RX:
652 case SLIMBUS_2_TX:
653 case SLIMBUS_3_RX:
654 case SLIMBUS_3_TX:
655 case SLIMBUS_4_RX:
656 case SLIMBUS_4_TX:
657 case SLIMBUS_5_RX:
658 case SLIMBUS_5_TX:
659 case SLIMBUS_6_RX:
660 case SLIMBUS_6_TX:
661 case SLIMBUS_7_RX:
662 case SLIMBUS_7_TX:
663 case SLIMBUS_8_RX:
664 case SLIMBUS_8_TX:
665 ret_size = SIZEOF_CFG_CMD(afe_param_id_slimbus_cfg);
666 break;
667 case VOICE_PLAYBACK_TX:
668 case VOICE2_PLAYBACK_TX:
669 case VOICE_RECORD_RX:
670 case VOICE_RECORD_TX:
671 ret_size = SIZEOF_CFG_CMD(afe_param_id_pseudo_port_cfg);
672 break;
673 case RT_PROXY_PORT_001_RX:
674 case RT_PROXY_PORT_001_TX:
675 ret_size = SIZEOF_CFG_CMD(afe_param_id_rt_proxy_port_cfg);
676 break;
677 case AFE_PORT_ID_USB_RX:
678 case AFE_PORT_ID_USB_TX:
679 ret_size = SIZEOF_CFG_CMD(afe_param_id_usb_audio_cfg);
680 break;
681 case AFE_PORT_ID_PRIMARY_PCM_RX:
682 case AFE_PORT_ID_PRIMARY_PCM_TX:
683 case AFE_PORT_ID_SECONDARY_PCM_RX:
684 case AFE_PORT_ID_SECONDARY_PCM_TX:
685 case AFE_PORT_ID_TERTIARY_PCM_RX:
686 case AFE_PORT_ID_TERTIARY_PCM_TX:
687 case AFE_PORT_ID_QUATERNARY_PCM_RX:
688 case AFE_PORT_ID_QUATERNARY_PCM_TX:
689 default:
690 pr_debug("%s: default case 0x%x\n", __func__, port_id);
691 ret_size = SIZEOF_CFG_CMD(afe_param_id_pcm_cfg);
692 break;
693 }
694 return ret_size;
695}
696
697int afe_q6_interface_prepare(void)
698{
699 int ret = 0;
700
701 pr_debug("%s:\n", __func__);
702
703 if (this_afe.apr == NULL) {
704 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
705 0xFFFFFFFF, &this_afe);
706 if (this_afe.apr == NULL) {
707 pr_err("%s: Unable to register AFE\n", __func__);
708 ret = -ENODEV;
709 }
710 rtac_set_afe_handle(this_afe.apr);
711 }
712 return ret;
713}
714
715/*
716 * afe_apr_send_pkt : returns 0 on success, negative otherwise.
717 */
718static int afe_apr_send_pkt(void *data, wait_queue_head_t *wait)
719{
720 int ret;
721
722 if (wait)
723 atomic_set(&this_afe.state, 1);
724 atomic_set(&this_afe.status, 0);
725 ret = apr_send_pkt(this_afe.apr, data);
726 if (ret > 0) {
727 if (wait) {
728 ret = wait_event_timeout(*wait,
729 (atomic_read(&this_afe.state) == 0),
730 msecs_to_jiffies(TIMEOUT_MS));
731 if (!ret) {
732 ret = -ETIMEDOUT;
733 } else if (atomic_read(&this_afe.status) > 0) {
734 pr_err("%s: DSP returned error[%s]\n", __func__,
735 adsp_err_get_err_str(atomic_read(
736 &this_afe.status)));
737 ret = adsp_err_get_lnx_err_code(
738 atomic_read(&this_afe.status));
739 } else {
740 ret = 0;
741 }
742 } else {
743 ret = 0;
744 }
745 } else if (ret == 0) {
746 pr_err("%s: packet not transmitted\n", __func__);
747 /* apr_send_pkt can return 0 when nothing is transmitted */
748 ret = -EINVAL;
749 }
750
751 pr_debug("%s: leave %d\n", __func__, ret);
752 return ret;
753}
754
755static int afe_send_cal_block(u16 port_id, struct cal_block_data *cal_block)
756{
757 int result = 0;
758 int index = 0;
759 struct afe_audioif_config_command_no_payload afe_cal;
760
761 if (!cal_block) {
762 pr_debug("%s: No AFE cal to send!\n", __func__);
763 result = -EINVAL;
764 goto done;
765 }
766 if (cal_block->cal_data.size <= 0) {
767 pr_debug("%s: AFE cal has invalid size!\n", __func__);
768 result = -EINVAL;
769 goto done;
770 }
771
772 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -0800773 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800774 pr_err("%s: AFE port index[%d] invalid!\n",
775 __func__, index);
776 result = -EINVAL;
777 goto done;
778 }
779
780 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
781 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
782 afe_cal.hdr.pkt_size = sizeof(afe_cal);
783 afe_cal.hdr.src_port = 0;
784 afe_cal.hdr.dest_port = 0;
785 afe_cal.hdr.token = index;
786 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
787 afe_cal.param.port_id = port_id;
788 afe_cal.param.payload_size = cal_block->cal_data.size;
789 afe_cal.param.payload_address_lsw =
790 lower_32_bits(cal_block->cal_data.paddr);
791 afe_cal.param.payload_address_msw =
792 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
793 afe_cal.param.mem_map_handle = cal_block->map_data.q6map_handle;
794
795 pr_debug("%s: AFE cal sent for device port = 0x%x, cal size = %zd, cal addr = 0x%pK\n",
796 __func__, port_id,
797 cal_block->cal_data.size, &cal_block->cal_data.paddr);
798
799 result = afe_apr_send_pkt(&afe_cal, &this_afe.wait[index]);
800 if (result)
801 pr_err("%s: AFE cal for port 0x%x failed %d\n",
802 __func__, port_id, result);
803
804done:
805 return result;
806}
807
808
809static int afe_send_custom_topology_block(struct cal_block_data *cal_block)
810{
811 int result = 0;
812 int index = 0;
813 struct cmd_set_topologies afe_cal;
814
815 if (!cal_block) {
816 pr_err("%s: No AFE SVC cal to send!\n", __func__);
817 return -EINVAL;
818 }
819 if (cal_block->cal_data.size <= 0) {
820 pr_err("%s: AFE SVC cal has invalid size: %zd!\n",
821 __func__, cal_block->cal_data.size);
822 return -EINVAL;
823 }
824
825 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
826 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
827 afe_cal.hdr.pkt_size = sizeof(afe_cal);
828 afe_cal.hdr.src_port = 0;
829 afe_cal.hdr.dest_port = 0;
830 afe_cal.hdr.token = index;
831 afe_cal.hdr.opcode = AFE_CMD_ADD_TOPOLOGIES;
832
833 afe_cal.payload_size = cal_block->cal_data.size;
834 afe_cal.payload_addr_lsw =
835 lower_32_bits(cal_block->cal_data.paddr);
836 afe_cal.payload_addr_msw =
837 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
838 afe_cal.mem_map_handle = cal_block->map_data.q6map_handle;
839
840 pr_debug("%s:cmd_id:0x%x calsize:%zd memmap_hdl:0x%x caladdr:0x%pK",
841 __func__, AFE_CMD_ADD_TOPOLOGIES, cal_block->cal_data.size,
842 afe_cal.mem_map_handle, &cal_block->cal_data.paddr);
843
844 result = afe_apr_send_pkt(&afe_cal, &this_afe.wait[index]);
845 if (result)
846 pr_err("%s: AFE send topology for command 0x%x failed %d\n",
847 __func__, AFE_CMD_ADD_TOPOLOGIES, result);
848
849 return result;
850}
851
852static void afe_send_custom_topology(void)
853{
854 struct cal_block_data *cal_block = NULL;
855 int cal_index = AFE_CUST_TOPOLOGY_CAL;
856 int ret;
857
858 if (this_afe.cal_data[cal_index] == NULL) {
859 pr_err("%s: cal_index %d not allocated!\n",
860 __func__, cal_index);
861 return;
862 }
863 mutex_lock(&this_afe.cal_data[cal_index]->lock);
864
865 if (!this_afe.set_custom_topology)
866 goto unlock;
867 this_afe.set_custom_topology = 0;
868 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
869 if (cal_block == NULL) {
870 pr_err("%s cal_block not found!!\n", __func__);
871 goto unlock;
872 }
873
874 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
875
876 ret = remap_cal_data(cal_block, cal_index);
877 if (ret) {
878 pr_err("%s: Remap_cal_data failed for cal %d!\n",
879 __func__, cal_index);
880 goto unlock;
881 }
882 ret = afe_send_custom_topology_block(cal_block);
883 if (ret < 0) {
884 pr_err("%s: No cal sent for cal_index %d! ret %d\n",
885 __func__, cal_index, ret);
886 goto unlock;
887 }
888 pr_debug("%s:sent custom topology for AFE\n", __func__);
889unlock:
890 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
891}
892
893static int afe_spk_ramp_dn_cfg(int port)
894{
895 int ret = -EINVAL;
896 int index = 0;
897 struct afe_spkr_prot_config_command config;
898
899 if (afe_get_port_type(port) != MSM_AFE_PORT_TYPE_RX) {
900 pr_debug("%s: port doesn't match 0x%x\n", __func__, port);
901 return 0;
902 }
903 if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_DISABLED ||
904 (this_afe.vi_rx_port != port)) {
905 pr_debug("%s: spkr protection disabled port 0x%x %d 0x%x\n",
906 __func__, port, ret, this_afe.vi_rx_port);
907 return 0;
908 }
909 memset(&config, 0, sizeof(config));
910 ret = q6audio_validate_port(port);
911 if (ret < 0) {
912 pr_err("%s: Invalid port 0x%x ret %d", __func__, port, ret);
913 ret = -EINVAL;
914 goto fail_cmd;
915 }
916 index = q6audio_get_port_index(port);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -0800917 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800918 pr_err("%s: AFE port index[%d] invalid!\n",
919 __func__, index);
920 ret = -EINVAL;
921 goto fail_cmd;
922 }
923 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
924 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
925 config.hdr.pkt_size = sizeof(config);
926 config.hdr.src_port = 0;
927 config.hdr.dest_port = 0;
928 config.hdr.token = index;
929
930 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
931 config.param.port_id = q6audio_get_port_id(port);
932 config.param.payload_size =
933 sizeof(config) - sizeof(config.hdr) - sizeof(config.param)
934 - sizeof(config.prot_config);
935 config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
936 config.pdata.param_id = AFE_PARAM_ID_FBSP_PTONE_RAMP_CFG;
937 config.pdata.param_size = 0;
938 atomic_set(&this_afe.state, 1);
939 atomic_set(&this_afe.status, 0);
940 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
941 if (ret < 0) {
942 pr_err("%s: port = 0x%x param = 0x%x failed %d\n",
943 __func__, port, config.pdata.param_id, ret);
944 goto fail_cmd;
945 }
946 ret = wait_event_timeout(this_afe.wait[index],
947 (atomic_read(&this_afe.state) == 0),
948 msecs_to_jiffies(TIMEOUT_MS));
949 if (!ret) {
950 pr_err("%s: wait_event timeout\n", __func__);
951 ret = -EINVAL;
952 goto fail_cmd;
953 }
954 if (atomic_read(&this_afe.status) > 0) {
955 pr_err("%s: config cmd failed [%s]\n",
956 __func__, adsp_err_get_err_str(
957 atomic_read(&this_afe.status)));
958 ret = adsp_err_get_lnx_err_code(
959 atomic_read(&this_afe.status));
960 goto fail_cmd;
961 }
962 /* dsp needs atleast 15ms to ramp down pilot tone*/
963 usleep_range(15000, 15010);
964 ret = 0;
965fail_cmd:
966 pr_debug("%s: config.pdata.param_id 0x%x status %d\n",
967 __func__, config.pdata.param_id, ret);
968return ret;
969}
970
971static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id,
972 union afe_spkr_prot_config *prot_config)
973{
974 int ret = -EINVAL;
975 int index = 0;
976 struct afe_spkr_prot_config_command config;
977
978 memset(&config, 0, sizeof(config));
979 if (!prot_config) {
980 pr_err("%s: Invalid params\n", __func__);
981 goto fail_cmd;
982 }
983 ret = q6audio_validate_port(src_port);
984 if (ret < 0) {
985 pr_err("%s: Invalid src port 0x%x ret %d",
986 __func__, src_port, ret);
987 ret = -EINVAL;
988 goto fail_cmd;
989 }
990 ret = q6audio_validate_port(dst_port);
991 if (ret < 0) {
992 pr_err("%s: Invalid dst port 0x%x ret %d", __func__,
993 dst_port, ret);
994 ret = -EINVAL;
995 goto fail_cmd;
996 }
997 index = q6audio_get_port_index(src_port);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -0800998 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800999 pr_err("%s: AFE port index[%d] invalid!\n",
1000 __func__, index);
1001 ret = -EINVAL;
1002 goto fail_cmd;
1003 }
1004 switch (param_id) {
1005 case AFE_PARAM_ID_FBSP_MODE_RX_CFG:
1006 config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
1007 break;
1008 case AFE_PARAM_ID_FEEDBACK_PATH_CFG:
1009 this_afe.vi_tx_port = src_port;
1010 this_afe.vi_rx_port = dst_port;
1011 config.pdata.module_id = AFE_MODULE_FEEDBACK;
1012 break;
1013 /*
1014 * AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2 is same as
1015 * AFE_PARAM_ID_SP_V2_TH_VI_MODE_CFG
1016 */
1017 case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2:
1018 case AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG:
1019 config.pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
1020 break;
1021 case AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG:
1022 case AFE_PARAM_ID_SP_V2_EX_VI_FTM_CFG:
1023 config.pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
1024 break;
1025 default:
1026 pr_err("%s: default case 0x%x\n", __func__, param_id);
1027 goto fail_cmd;
1028 }
1029
1030 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1031 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1032 config.hdr.pkt_size = sizeof(config);
1033 config.hdr.src_port = 0;
1034 config.hdr.dest_port = 0;
1035 config.hdr.token = index;
1036
1037 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1038 config.param.port_id = q6audio_get_port_id(src_port);
1039 config.param.payload_size = sizeof(config) - sizeof(config.hdr)
1040 - sizeof(config.param);
1041 config.pdata.param_id = param_id;
1042 config.pdata.param_size = sizeof(config.prot_config);
1043 config.prot_config = *prot_config;
1044 atomic_set(&this_afe.state, 1);
1045 atomic_set(&this_afe.status, 0);
1046 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
1047 if (ret < 0) {
1048 pr_err("%s: port = 0x%x param = 0x%x failed %d\n",
1049 __func__, src_port, param_id, ret);
1050 goto fail_cmd;
1051 }
1052 ret = wait_event_timeout(this_afe.wait[index],
1053 (atomic_read(&this_afe.state) == 0),
1054 msecs_to_jiffies(TIMEOUT_MS));
1055 if (!ret) {
1056 pr_err("%s: wait_event timeout\n", __func__);
1057 ret = -EINVAL;
1058 goto fail_cmd;
1059 }
1060 if (atomic_read(&this_afe.status) > 0) {
1061 pr_err("%s: config cmd failed [%s]\n",
1062 __func__, adsp_err_get_err_str(
1063 atomic_read(&this_afe.status)));
1064 ret = adsp_err_get_lnx_err_code(
1065 atomic_read(&this_afe.status));
1066 goto fail_cmd;
1067 }
1068 ret = 0;
1069fail_cmd:
1070 pr_debug("%s: config.pdata.param_id 0x%x status %d 0x%x\n",
1071 __func__, config.pdata.param_id, ret, src_port);
1072 return ret;
1073}
1074
1075static void afe_send_cal_spkr_prot_tx(int port_id)
1076{
1077 union afe_spkr_prot_config afe_spk_config;
1078
1079 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL ||
1080 this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
1081 this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL)
1082 return;
1083
1084 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1085 if ((this_afe.prot_cfg.mode != MSM_SPKR_PROT_DISABLED) &&
1086 (this_afe.vi_tx_port == port_id)) {
1087 if (this_afe.prot_cfg.mode ==
1088 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
1089 afe_spk_config.vi_proc_cfg.operation_mode =
1090 Q6AFE_MSM_SPKR_CALIBRATION;
1091 afe_spk_config.vi_proc_cfg.quick_calib_flag =
1092 this_afe.prot_cfg.quick_calib_flag;
1093 } else {
1094 afe_spk_config.vi_proc_cfg.operation_mode =
1095 Q6AFE_MSM_SPKR_PROCESSING;
1096 }
1097
1098 if (this_afe.th_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE)
1099 afe_spk_config.vi_proc_cfg.operation_mode =
1100 Q6AFE_MSM_SPKR_FTM_MODE;
1101 afe_spk_config.vi_proc_cfg.minor_version = 1;
1102 afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_1] =
1103 (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1];
1104 afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_2] =
1105 (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_2];
1106 afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_1] =
1107 (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_1];
1108 afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_2] =
1109 (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_2];
1110 if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_NOT_CALIBRATED) {
1111 struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg;
1112
1113 vi_proc_cfg = &afe_spk_config.vi_proc_cfg;
1114 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] =
1115 USE_CALIBRATED_R0TO;
1116 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] =
1117 USE_CALIBRATED_R0TO;
1118 } else {
1119 struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg;
1120
1121 vi_proc_cfg = &afe_spk_config.vi_proc_cfg;
1122 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] =
1123 USE_SAFE_R0TO;
1124 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] =
1125 USE_SAFE_R0TO;
1126 }
1127 if (afe_spk_prot_prepare(port_id, 0,
1128 AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2,
1129 &afe_spk_config))
1130 pr_err("%s: SPKR_CALIB_VI_PROC_CFG failed\n",
1131 __func__);
1132 }
1133 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1134
1135 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
1136 if ((this_afe.th_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE) &&
1137 (this_afe.vi_tx_port == port_id)) {
1138 afe_spk_config.th_vi_ftm_cfg.minor_version = 1;
1139 afe_spk_config.th_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_1] =
1140 this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_1];
1141 afe_spk_config.th_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_2] =
1142 this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_2];
1143 afe_spk_config.th_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_1] =
1144 this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_1];
1145 afe_spk_config.th_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_2] =
1146 this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_2];
1147
1148 if (afe_spk_prot_prepare(port_id, 0,
1149 AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG,
1150 &afe_spk_config))
1151 pr_err("%s: th vi ftm cfg failed\n", __func__);
1152 this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
1153 }
1154 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
1155
1156 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
1157 if ((this_afe.ex_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE) &&
1158 (this_afe.vi_tx_port == port_id)) {
1159 afe_spk_config.ex_vi_mode_cfg.minor_version = 1;
1160 afe_spk_config.ex_vi_mode_cfg.operation_mode =
1161 Q6AFE_MSM_SPKR_FTM_MODE;
1162 if (afe_spk_prot_prepare(port_id, 0,
1163 AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG,
1164 &afe_spk_config))
1165 pr_err("%s: ex vi mode cfg failed\n", __func__);
1166
1167 afe_spk_config.ex_vi_ftm_cfg.minor_version = 1;
1168 afe_spk_config.ex_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_1] =
1169 this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_1];
1170 afe_spk_config.ex_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_2] =
1171 this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_2];
1172 afe_spk_config.ex_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_1] =
1173 this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_1];
1174 afe_spk_config.ex_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_2] =
1175 this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_2];
1176
1177 if (afe_spk_prot_prepare(port_id, 0,
1178 AFE_PARAM_ID_SP_V2_EX_VI_FTM_CFG,
1179 &afe_spk_config))
1180 pr_err("%s: ex vi ftm cfg failed\n", __func__);
1181 this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
1182 }
1183 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
1184
1185}
1186
1187static void afe_send_cal_spkr_prot_rx(int port_id)
1188{
1189 union afe_spkr_prot_config afe_spk_config;
1190
1191 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
1192 goto done;
1193
1194 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1195
1196 if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_DISABLED &&
1197 (this_afe.vi_rx_port == port_id)) {
1198 if (this_afe.prot_cfg.mode ==
1199 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
1200 afe_spk_config.mode_rx_cfg.mode =
1201 Q6AFE_MSM_SPKR_CALIBRATION;
1202 else
1203 afe_spk_config.mode_rx_cfg.mode =
1204 Q6AFE_MSM_SPKR_PROCESSING;
1205 afe_spk_config.mode_rx_cfg.minor_version = 1;
1206 if (afe_spk_prot_prepare(port_id, 0,
1207 AFE_PARAM_ID_FBSP_MODE_RX_CFG,
1208 &afe_spk_config))
1209 pr_err("%s: RX MODE_VI_PROC_CFG failed\n",
1210 __func__);
1211 }
1212 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1213done:
1214 return;
1215}
1216
1217static int afe_send_hw_delay(u16 port_id, u32 rate)
1218{
1219 struct audio_cal_hw_delay_entry delay_entry;
1220 struct afe_audioif_config_command config;
1221 int index = 0;
1222 int ret = -EINVAL;
1223
1224 pr_debug("%s:\n", __func__);
1225
Xiaoyu Yed3650382017-02-02 12:58:01 -08001226 memset(&delay_entry, 0, sizeof(delay_entry));
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001227 delay_entry.sample_rate = rate;
1228 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
1229 ret = afe_get_cal_hw_delay(TX_DEVICE, &delay_entry);
1230 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
1231 ret = afe_get_cal_hw_delay(RX_DEVICE, &delay_entry);
1232
1233 /*
1234 * HW delay is only used for IMS calls to sync audio with video
1235 * It is only needed for devices & sample rates used for IMS video
1236 * calls. Values are received from ACDB calbration files
1237 */
1238 if (ret != 0) {
1239 pr_debug("%s: debug: HW delay info not available %d\n",
1240 __func__, ret);
1241 goto fail_cmd;
1242 }
1243
1244 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08001245 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001246 pr_err("%s: AFE port index[%d] invalid!\n",
1247 __func__, index);
1248 ret = -EINVAL;
1249 goto fail_cmd;
1250 }
1251
1252 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1253 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1254 config.hdr.pkt_size = sizeof(config);
1255 config.hdr.src_port = 0;
1256 config.hdr.dest_port = 0;
1257 config.hdr.token = index;
1258
1259 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1260 config.param.port_id = q6audio_get_port_id(port_id);
1261 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1262 sizeof(config.param);
1263 config.param.payload_address_lsw = 0x00;
1264 config.param.payload_address_msw = 0x00;
1265 config.param.mem_map_handle = 0x00;
1266 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
1267 config.pdata.param_id = AFE_PARAM_ID_DEVICE_HW_DELAY;
1268 config.pdata.param_size = sizeof(config.port);
1269
1270 config.port.hw_delay.delay_in_us = delay_entry.delay_usec;
1271 config.port.hw_delay.device_hw_delay_minor_version =
1272 AFE_API_VERSION_DEVICE_HW_DELAY;
1273
1274 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
1275 if (ret) {
1276 pr_err("%s: AFE hw delay for port 0x%x failed %d\n",
1277 __func__, port_id, ret);
1278 goto fail_cmd;
1279 }
1280
1281fail_cmd:
1282 pr_debug("%s: port_id 0x%x rate %u delay_usec %d status %d\n",
1283 __func__, port_id, rate, delay_entry.delay_usec, ret);
1284 return ret;
1285}
1286
1287static struct cal_block_data *afe_find_cal_topo_id_by_port(
1288 struct cal_type_data *cal_type, u16 port_id)
1289{
1290 struct list_head *ptr, *next;
1291 struct cal_block_data *cal_block = NULL;
1292 int32_t path;
1293 struct audio_cal_info_afe_top *afe_top;
Siena Richard23364c92017-01-11 16:20:55 -08001294 int afe_port_index = q6audio_get_port_index(port_id);
1295
1296 if (afe_port_index < 0)
1297 goto err_exit;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001298
1299 list_for_each_safe(ptr, next,
1300 &cal_type->cal_blocks) {
1301 cal_block = list_entry(ptr,
1302 struct cal_block_data, list);
1303
1304 path = ((afe_get_port_type(port_id) ==
1305 MSM_AFE_PORT_TYPE_TX)?(TX_DEVICE):(RX_DEVICE));
1306 afe_top =
1307 (struct audio_cal_info_afe_top *)cal_block->cal_info;
Vidyakumar Athota6ca5f292017-02-13 17:02:58 -08001308 if (afe_top->path == path) {
1309 if (this_afe.dev_acdb_id[afe_port_index] > 0) {
1310 if (afe_top->acdb_id ==
1311 this_afe.dev_acdb_id[afe_port_index]) {
1312 pr_debug("%s: top_id:%x acdb_id:%d afe_port_id:%d\n",
1313 __func__, afe_top->topology,
1314 afe_top->acdb_id,
1315 q6audio_get_port_id(port_id));
1316 return cal_block;
1317 }
1318 } else {
1319 pr_debug("%s: top_id:%x acdb_id:%d afe_port:%d\n",
Siena Richard23364c92017-01-11 16:20:55 -08001320 __func__, afe_top->topology, afe_top->acdb_id,
1321 q6audio_get_port_id(port_id));
Vidyakumar Athota6ca5f292017-02-13 17:02:58 -08001322 return cal_block;
1323 }
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001324 }
1325 }
Siena Richard23364c92017-01-11 16:20:55 -08001326
1327err_exit:
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001328 return NULL;
1329}
1330
1331static int afe_get_cal_topology_id(u16 port_id, u32 *topology_id)
1332{
1333 int ret = 0;
1334
1335 struct cal_block_data *cal_block = NULL;
1336 struct audio_cal_info_afe_top *afe_top_info = NULL;
1337
1338 if (this_afe.cal_data[AFE_TOPOLOGY_CAL] == NULL) {
1339 pr_err("%s: [AFE_TOPOLOGY_CAL] not initialized\n", __func__);
1340 return -EINVAL;
1341 }
1342 if (topology_id == NULL) {
1343 pr_err("%s: topology_id is NULL\n", __func__);
1344 return -EINVAL;
1345 }
1346 *topology_id = 0;
1347
1348 mutex_lock(&this_afe.cal_data[AFE_TOPOLOGY_CAL]->lock);
1349 cal_block = afe_find_cal_topo_id_by_port(
1350 this_afe.cal_data[AFE_TOPOLOGY_CAL], port_id);
1351 if (cal_block == NULL) {
1352 pr_err("%s: [AFE_TOPOLOGY_CAL] not initialized for this port %d\n",
1353 __func__, port_id);
1354 ret = -EINVAL;
1355 goto unlock;
1356 }
1357
1358 afe_top_info = ((struct audio_cal_info_afe_top *)
1359 cal_block->cal_info);
1360 if (!afe_top_info->topology) {
1361 pr_err("%s: invalid topology id : [%d, %d]\n",
1362 __func__, afe_top_info->acdb_id, afe_top_info->topology);
1363 ret = -EINVAL;
1364 goto unlock;
1365 }
1366 *topology_id = (u32)afe_top_info->topology;
1367
1368 pr_debug("%s: port_id = %u acdb_id = %d topology_id = %u ret=%d\n",
1369 __func__, port_id, afe_top_info->acdb_id,
1370 afe_top_info->topology, ret);
1371unlock:
1372 mutex_unlock(&this_afe.cal_data[AFE_TOPOLOGY_CAL]->lock);
1373 return ret;
1374}
1375
1376static int afe_send_port_topology_id(u16 port_id)
1377{
1378 struct afe_audioif_config_command config;
1379 int index = 0;
1380 int ret = 0;
1381 u32 topology_id = 0;
1382
1383 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08001384 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001385 pr_err("%s: AFE port index[%d] invalid!\n",
1386 __func__, index);
1387 return -EINVAL;
1388 }
1389
1390 ret = afe_get_cal_topology_id(port_id, &topology_id);
1391 if (ret || !topology_id) {
1392 pr_debug("%s: AFE port[%d] get_cal_topology[%d] invalid!\n",
1393 __func__, port_id, topology_id);
1394 goto done;
1395 }
1396
1397 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1398 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1399 config.hdr.pkt_size = sizeof(config);
1400 config.hdr.src_port = 0;
1401 config.hdr.dest_port = 0;
1402 config.hdr.token = index;
1403
1404 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1405 config.param.port_id = q6audio_get_port_id(port_id);
1406 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1407 sizeof(config.param);
1408 config.param.payload_address_lsw = 0x00;
1409 config.param.payload_address_msw = 0x00;
1410 config.param.mem_map_handle = 0x00;
1411 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
1412 config.pdata.param_id = AFE_PARAM_ID_SET_TOPOLOGY;
1413 config.pdata.param_size = sizeof(config.port);
1414 config.port.topology.minor_version = AFE_API_VERSION_TOPOLOGY_V1;
1415 config.port.topology.topology_id = topology_id;
1416
1417 pr_debug("%s: param PL size=%d iparam_size[%d][%zd %zd %zd %zd] param_id[0x%x]\n",
1418 __func__, config.param.payload_size, config.pdata.param_size,
1419 sizeof(config), sizeof(config.param), sizeof(config.port),
1420 sizeof(struct apr_hdr), config.pdata.param_id);
1421
1422 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
1423 if (ret) {
1424 pr_err("%s: AFE set topology id enable for port 0x%x failed %d\n",
1425 __func__, port_id, ret);
1426 goto done;
1427 }
1428
1429 this_afe.topology[index] = topology_id;
Vidyakumar Athota69ece6b2017-02-02 17:29:19 -08001430 rtac_update_afe_topology(port_id);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001431done:
1432 pr_debug("%s: AFE set topology id 0x%x enable for port 0x%x ret %d\n",
1433 __func__, topology_id, port_id, ret);
1434 return ret;
1435
1436}
1437
1438static int remap_cal_data(struct cal_block_data *cal_block, int cal_index)
1439{
1440 int ret = 0;
1441
1442 if (cal_block->map_data.ion_client == NULL) {
1443 pr_err("%s: No ION allocation for cal index %d!\n",
1444 __func__, cal_index);
1445 ret = -EINVAL;
1446 goto done;
1447 }
1448
1449 if ((cal_block->map_data.map_size > 0) &&
1450 (cal_block->map_data.q6map_handle == 0)) {
1451 atomic_set(&this_afe.mem_map_cal_index, cal_index);
1452 ret = afe_cmd_memory_map(cal_block->cal_data.paddr,
1453 cal_block->map_data.map_size);
1454 atomic_set(&this_afe.mem_map_cal_index, -1);
1455 if (ret < 0) {
1456 pr_err("%s: mmap did not work! size = %zd ret %d\n",
1457 __func__,
1458 cal_block->map_data.map_size, ret);
1459 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
1460 __func__,
1461 &cal_block->cal_data.paddr,
1462 cal_block->map_data.map_size);
1463 goto done;
1464 }
1465 cal_block->map_data.q6map_handle = atomic_read(&this_afe.
1466 mem_map_cal_handles[cal_index]);
1467 }
1468done:
1469 return ret;
1470}
1471
Siena Richard23364c92017-01-11 16:20:55 -08001472static struct cal_block_data *afe_find_cal(int cal_index, int port_id)
1473{
1474 struct list_head *ptr, *next;
1475 struct cal_block_data *cal_block = NULL;
1476 struct audio_cal_info_afe *afe_cal_info = NULL;
1477 int afe_port_index = q6audio_get_port_index(port_id);
1478
1479 pr_debug("%s: cal_index %d port_id %d port_index %d\n", __func__,
1480 cal_index, port_id, afe_port_index);
1481 if (afe_port_index < 0) {
1482 pr_err("%s: Error getting AFE port index %d\n",
1483 __func__, afe_port_index);
1484 goto exit;
1485 }
1486
1487 list_for_each_safe(ptr, next,
1488 &this_afe.cal_data[cal_index]->cal_blocks) {
1489 cal_block = list_entry(ptr, struct cal_block_data, list);
1490 afe_cal_info = cal_block->cal_info;
1491 if ((afe_cal_info->acdb_id ==
1492 this_afe.dev_acdb_id[afe_port_index]) &&
1493 (afe_cal_info->sample_rate ==
1494 this_afe.afe_sample_rates[afe_port_index])) {
1495 pr_debug("%s: cal block is a match, size is %zd\n",
1496 __func__, cal_block->cal_data.size);
1497 goto exit;
1498 }
1499 }
1500 pr_err("%s: no matching cal_block found\n", __func__);
1501 cal_block = NULL;
1502
1503exit:
1504 return cal_block;
1505}
1506
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001507static void send_afe_cal_type(int cal_index, int port_id)
1508{
1509 struct cal_block_data *cal_block = NULL;
1510 int ret;
Vidyakumar Athota6ca5f292017-02-13 17:02:58 -08001511 int afe_port_index = q6audio_get_port_index(port_id);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001512
1513 pr_debug("%s:\n", __func__);
1514
1515 if (this_afe.cal_data[cal_index] == NULL) {
1516 pr_warn("%s: cal_index %d not allocated!\n",
1517 __func__, cal_index);
1518 goto done;
1519 }
1520
Vidyakumar Athota6ca5f292017-02-13 17:02:58 -08001521 if (afe_port_index < 0) {
1522 pr_err("%s: Error getting AFE port index %d\n",
1523 __func__, afe_port_index);
1524 goto done;
1525 }
1526
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001527 mutex_lock(&this_afe.cal_data[cal_index]->lock);
Siena Richard23364c92017-01-11 16:20:55 -08001528
Vidyakumar Athota6ca5f292017-02-13 17:02:58 -08001529 if (((cal_index == AFE_COMMON_RX_CAL) ||
1530 (cal_index == AFE_COMMON_TX_CAL)) &&
1531 (this_afe.dev_acdb_id[afe_port_index] > 0))
Siena Richard23364c92017-01-11 16:20:55 -08001532 cal_block = afe_find_cal(cal_index, port_id);
1533 else
1534 cal_block = cal_utils_get_only_cal_block(
1535 this_afe.cal_data[cal_index]);
1536
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001537 if (cal_block == NULL) {
1538 pr_err("%s cal_block not found!!\n", __func__);
1539 goto unlock;
1540 }
1541
1542 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
1543
1544 ret = remap_cal_data(cal_block, cal_index);
1545 if (ret) {
1546 pr_err("%s: Remap_cal_data failed for cal %d!\n",
1547 __func__, cal_index);
1548 goto unlock;
1549 }
1550 ret = afe_send_cal_block(port_id, cal_block);
1551 if (ret < 0)
1552 pr_debug("%s: No cal sent for cal_index %d, port_id = 0x%x! ret %d\n",
1553 __func__, cal_index, port_id, ret);
1554unlock:
1555 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
1556done:
1557 return;
1558}
1559
1560void afe_send_cal(u16 port_id)
1561{
1562 pr_debug("%s: port_id=0x%x\n", __func__, port_id);
1563
1564 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) {
1565 afe_send_cal_spkr_prot_tx(port_id);
1566 send_afe_cal_type(AFE_COMMON_TX_CAL, port_id);
1567 } else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) {
1568 afe_send_cal_spkr_prot_rx(port_id);
1569 send_afe_cal_type(AFE_COMMON_RX_CAL, port_id);
1570 }
1571}
1572
1573int afe_turn_onoff_hw_mad(u16 mad_type, u16 enable)
1574{
1575 int ret;
1576 struct afe_cmd_hw_mad_ctrl config;
1577
1578 pr_debug("%s: enter\n", __func__);
1579 memset(&config, 0, sizeof(config));
1580 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1581 APR_HDR_LEN(APR_HDR_SIZE),
1582 APR_PKT_VER);
1583 config.hdr.pkt_size = sizeof(config);
1584 config.hdr.src_port = 0;
1585 config.hdr.dest_port = 0;
1586 config.hdr.token = IDX_GLOBAL_CFG;
1587 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1588 config.param.port_id = SLIMBUS_5_TX;
1589 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1590 sizeof(config.param);
1591 config.param.payload_address_lsw = 0x00;
1592 config.param.payload_address_msw = 0x00;
1593 config.param.mem_map_handle = 0x00;
1594 config.pdata.module_id = AFE_MODULE_HW_MAD;
1595 config.pdata.param_id = AFE_PARAM_ID_HW_MAD_CTRL;
1596 config.pdata.param_size = sizeof(config.payload);
1597 config.payload.minor_version = 1;
1598 config.payload.mad_type = mad_type;
1599 config.payload.mad_enable = enable;
1600
1601 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
1602 if (ret)
1603 pr_err("%s: AFE_PARAM_ID_HW_MAD_CTRL failed %d\n", __func__,
1604 ret);
1605 return ret;
1606}
1607
1608static int afe_send_slimbus_slave_cfg(
1609 struct afe_param_cdc_slimbus_slave_cfg *sb_slave_cfg)
1610{
1611 int ret;
1612 struct afe_svc_cmd_sb_slave_cfg config;
1613
1614 pr_debug("%s: enter\n", __func__);
1615
1616 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1617 APR_HDR_LEN(APR_HDR_SIZE),
1618 APR_PKT_VER);
1619 config.hdr.pkt_size = sizeof(config);
1620 config.hdr.src_port = 0;
1621 config.hdr.dest_port = 0;
1622 config.hdr.token = IDX_GLOBAL_CFG;
1623 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1624 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1625 sizeof(config.param);
1626 config.param.payload_address_lsw = 0x00;
1627 config.param.payload_address_msw = 0x00;
1628 config.param.mem_map_handle = 0x00;
1629 config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
1630 config.pdata.param_id = AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG;
1631 config.pdata.param_size =
1632 sizeof(struct afe_param_cdc_slimbus_slave_cfg);
1633 config.sb_slave_cfg = *sb_slave_cfg;
1634
1635 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
1636 if (ret)
1637 pr_err("%s: AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG failed %d\n",
1638 __func__, ret);
1639
1640 pr_debug("%s: leave %d\n", __func__, ret);
1641 return ret;
1642}
1643
1644static int afe_send_codec_reg_page_config(
1645 struct afe_param_cdc_reg_page_cfg *cdc_reg_page_cfg)
1646{
1647 struct afe_svc_cmd_cdc_reg_page_cfg config;
1648 int ret;
1649
1650 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1651 APR_HDR_LEN(APR_HDR_SIZE),
1652 APR_PKT_VER);
1653 config.hdr.pkt_size = sizeof(config);
1654 config.hdr.src_port = 0;
1655 config.hdr.dest_port = 0;
1656 config.hdr.token = IDX_GLOBAL_CFG;
1657 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1658 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1659 sizeof(config.param);
1660 config.param.payload_address_lsw = 0x00;
1661 config.param.payload_address_msw = 0x00;
1662 config.param.mem_map_handle = 0x00;
1663 config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
1664 config.pdata.param_id = AFE_PARAM_ID_CDC_REG_PAGE_CFG;
1665 config.pdata.param_size =
1666 sizeof(struct afe_param_cdc_reg_page_cfg);
1667 config.cdc_reg_page_cfg = *cdc_reg_page_cfg;
1668
1669 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
1670 if (ret)
1671 pr_err("%s: AFE_PARAM_ID_CDC_REG_PAGE_CFG failed %d\n",
1672 __func__, ret);
1673
1674 return ret;
1675}
1676
1677static int afe_send_codec_reg_config(
1678 struct afe_param_cdc_reg_cfg_data *cdc_reg_cfg)
1679{
1680 int i, j, ret = -EINVAL;
1681 int pkt_size, payload_size, reg_per_pkt, num_pkts, num_regs;
1682 struct afe_svc_cmd_cdc_reg_cfg *config;
1683 struct afe_svc_cmd_set_param *param;
1684
1685 reg_per_pkt = (APR_MAX_BUF - sizeof(*config)) /
1686 sizeof(struct afe_param_cdc_reg_cfg_payload);
1687 if (reg_per_pkt > 0) {
1688 num_pkts = (cdc_reg_cfg->num_registers / reg_per_pkt) +
1689 (cdc_reg_cfg->num_registers % reg_per_pkt == 0 ? 0 : 1);
1690 } else {
1691 pr_err("%s: Failed to build codec reg config APR packet\n",
1692 __func__);
1693 return -EINVAL;
1694 }
1695
1696 for (j = 0; j < num_pkts; ++j) {
1697 /*
1698 * num_regs is set to reg_per_pkt on each pass through the loop
1699 * except the last, when it is set to the number of registers
1700 * remaining from the total
1701 */
1702 num_regs = (j < (num_pkts - 1) ? reg_per_pkt :
1703 cdc_reg_cfg->num_registers - (reg_per_pkt * j));
1704 payload_size = sizeof(struct afe_param_cdc_reg_cfg_payload) *
1705 num_regs;
1706 pkt_size = sizeof(*config) + payload_size;
1707 pr_debug("%s: pkt_size %d, payload_size %d\n", __func__,
1708 pkt_size, payload_size);
1709 config = kzalloc(pkt_size, GFP_KERNEL);
1710 if (!config)
1711 return -ENOMEM;
1712
1713 config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1714 APR_HDR_LEN(APR_HDR_SIZE),
1715 APR_PKT_VER);
1716 config->hdr.pkt_size = pkt_size;
1717 config->hdr.src_port = 0;
1718 config->hdr.dest_port = 0;
1719 config->hdr.token = IDX_GLOBAL_CFG;
1720 config->hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1721
1722 param = &config->param;
1723 param->payload_size = payload_size;
1724 param->payload_address_lsw = 0x00;
1725 param->payload_address_msw = 0x00;
1726 param->mem_map_handle = 0x00;
1727
1728 for (i = 0; i < num_regs; i++) {
1729 config->reg_data[i].common.module_id =
1730 AFE_MODULE_CDC_DEV_CFG;
1731 config->reg_data[i].common.param_id =
1732 AFE_PARAM_ID_CDC_REG_CFG;
1733 config->reg_data[i].common.param_size =
1734 sizeof(config->reg_data[i].reg_cfg);
1735 config->reg_data[i].reg_cfg =
1736 cdc_reg_cfg->reg_data[i + (j * reg_per_pkt)];
1737 }
1738
1739 ret = afe_apr_send_pkt(config, &this_afe.wait[IDX_GLOBAL_CFG]);
1740 if (ret) {
1741 pr_err("%s: AFE_PARAM_ID_CDC_REG_CFG failed %d\n",
1742 __func__, ret);
1743 kfree(config);
1744 break;
1745 }
1746 kfree(config);
1747 }
1748
1749 return ret;
1750}
1751
1752static int afe_init_cdc_reg_config(void)
1753{
1754 int ret;
1755 struct afe_svc_cmd_init_cdc_reg_cfg config;
1756
1757 pr_debug("%s: enter\n", __func__);
1758 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1759 APR_HDR_LEN(APR_HDR_SIZE),
1760 APR_PKT_VER);
1761 config.hdr.pkt_size = sizeof(config);
1762 config.hdr.src_port = 0;
1763 config.hdr.dest_port = 0;
1764 config.hdr.token = IDX_GLOBAL_CFG;
1765 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1766
1767 config.param.payload_size = sizeof(struct afe_port_param_data_v2);
1768 config.param.payload_address_lsw = 0x00;
1769 config.param.payload_address_msw = 0x00;
1770 config.param.mem_map_handle = 0x00;
1771
1772 config.init.module_id = AFE_MODULE_CDC_DEV_CFG;
1773 config.init.param_id = AFE_PARAM_ID_CDC_REG_CFG_INIT;
1774 config.init.param_size = 0;
1775
1776 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
1777 if (ret) {
1778 pr_err("%s: AFE_PARAM_ID_CDC_INIT_REG_CFG failed %d\n",
1779 __func__, ret);
1780 }
1781
1782 return ret;
1783}
1784
1785static int afe_send_slimbus_slave_port_cfg(
1786 struct afe_param_slimbus_slave_port_cfg *port_config, u16 port_id)
1787{
1788 int ret, index;
1789 struct afe_cmd_hw_mad_slimbus_slave_port_cfg config;
1790
1791 pr_debug("%s: enter, port_id = 0x%x\n", __func__, port_id);
1792 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08001793 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001794 pr_err("%s: AFE port index[%d] invalid!\n",
1795 __func__, index);
1796 return -EINVAL;
1797 }
1798 ret = q6audio_validate_port(port_id);
1799 if (ret < 0) {
1800 pr_err("%s: port id = 0x%x ret %d\n", __func__, port_id, ret);
1801 return -EINVAL;
1802 }
1803
1804 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1805 APR_HDR_LEN(APR_HDR_SIZE),
1806 APR_PKT_VER);
1807 config.hdr.pkt_size = sizeof(config);
1808 config.hdr.src_port = 0;
1809 config.hdr.dest_port = 0;
1810 config.hdr.token = index;
1811 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1812 config.param.port_id = port_id;
1813 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1814 sizeof(config.param);
1815 config.param.payload_address_lsw = 0x00;
1816 config.param.payload_address_msw = 0x00;
1817 config.param.mem_map_handle = 0x00;
1818 config.pdata.module_id = AFE_MODULE_HW_MAD;
1819 config.pdata.param_id = AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG;
1820 config.pdata.param_size = sizeof(*port_config);
1821 config.sb_port_cfg = *port_config;
1822
1823 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
1824 if (ret) {
1825 pr_err("%s: AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG failed %d\n",
1826 __func__, ret);
1827 }
1828 pr_debug("%s: leave %d\n", __func__, ret);
1829 return ret;
1830}
1831static int afe_aanc_port_cfg(void *apr, uint16_t tx_port, uint16_t rx_port)
1832{
1833 struct afe_port_cmd_set_aanc_param cfg;
1834 int ret = 0;
1835 int index = 0;
1836
1837 pr_debug("%s: tx_port 0x%x, rx_port 0x%x\n",
1838 __func__, tx_port, rx_port);
1839
1840 ret = afe_q6_interface_prepare();
1841 if (ret != 0) {
1842 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
1843 return -EINVAL;
1844 }
1845
1846 index = q6audio_get_port_index(tx_port);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08001847 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001848 pr_err("%s: AFE port index[%d] invalid!\n",
1849 __func__, index);
1850 return -EINVAL;
1851 }
1852 ret = q6audio_validate_port(tx_port);
1853 if (ret < 0) {
1854 pr_err("%s: port id: 0x%x ret %d\n", __func__, tx_port, ret);
1855 return -EINVAL;
1856 }
1857 pr_debug("%s: AANC sample rate tx rate: %d rx rate %d\n",
1858 __func__, this_afe.aanc_info.aanc_tx_port_sample_rate,
1859 this_afe.aanc_info.aanc_rx_port_sample_rate);
1860 /*
1861 * If aanc tx sample rate or rx sample rate is zero, skip aanc
1862 * configuration as AFE resampler will fail for invalid sample
1863 * rates.
1864 */
1865 if (!this_afe.aanc_info.aanc_tx_port_sample_rate ||
1866 !this_afe.aanc_info.aanc_rx_port_sample_rate) {
1867 return -EINVAL;
1868 }
1869
1870 cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1871 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1872 cfg.hdr.pkt_size = sizeof(cfg);
1873 cfg.hdr.src_port = 0;
1874 cfg.hdr.dest_port = 0;
1875 cfg.hdr.token = index;
1876 cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1877
1878 cfg.param.port_id = tx_port;
1879 cfg.param.payload_size = sizeof(struct afe_port_param_data_v2) +
1880 sizeof(struct afe_param_aanc_port_cfg);
1881 cfg.param.payload_address_lsw = 0;
1882 cfg.param.payload_address_msw = 0;
1883 cfg.param.mem_map_handle = 0;
1884
1885 cfg.pdata.module_id = AFE_MODULE_AANC;
1886 cfg.pdata.param_id = AFE_PARAM_ID_AANC_PORT_CONFIG;
1887 cfg.pdata.param_size = sizeof(struct afe_param_aanc_port_cfg);
1888 cfg.pdata.reserved = 0;
1889
1890 cfg.data.aanc_port_cfg.aanc_port_cfg_minor_version =
1891 AFE_API_VERSION_AANC_PORT_CONFIG;
1892 cfg.data.aanc_port_cfg.tx_port_sample_rate =
1893 this_afe.aanc_info.aanc_tx_port_sample_rate;
1894 cfg.data.aanc_port_cfg.tx_port_channel_map[0] = AANC_TX_VOICE_MIC;
1895 cfg.data.aanc_port_cfg.tx_port_channel_map[1] = AANC_TX_NOISE_MIC;
1896 cfg.data.aanc_port_cfg.tx_port_channel_map[2] = AANC_TX_ERROR_MIC;
1897 cfg.data.aanc_port_cfg.tx_port_channel_map[3] = AANC_TX_MIC_UNUSED;
1898 cfg.data.aanc_port_cfg.tx_port_channel_map[4] = AANC_TX_MIC_UNUSED;
1899 cfg.data.aanc_port_cfg.tx_port_channel_map[5] = AANC_TX_MIC_UNUSED;
1900 cfg.data.aanc_port_cfg.tx_port_channel_map[6] = AANC_TX_MIC_UNUSED;
1901 cfg.data.aanc_port_cfg.tx_port_channel_map[7] = AANC_TX_MIC_UNUSED;
1902 cfg.data.aanc_port_cfg.tx_port_num_channels = 3;
1903 cfg.data.aanc_port_cfg.rx_path_ref_port_id = rx_port;
1904 cfg.data.aanc_port_cfg.ref_port_sample_rate =
1905 this_afe.aanc_info.aanc_rx_port_sample_rate;
1906
1907 ret = afe_apr_send_pkt((uint32_t *) &cfg, &this_afe.wait[index]);
1908 if (ret) {
1909 pr_err("%s: AFE AANC port config failed for tx_port 0x%x, rx_port 0x%x ret %d\n",
1910 __func__, tx_port, rx_port, ret);
1911 }
1912
1913 return ret;
1914}
1915
1916static int afe_aanc_mod_enable(void *apr, uint16_t tx_port, uint16_t enable)
1917{
1918 struct afe_port_cmd_set_aanc_param cfg;
1919 int ret = 0;
1920 int index = 0;
1921
1922 pr_debug("%s: tx_port 0x%x\n",
1923 __func__, tx_port);
1924
1925 ret = afe_q6_interface_prepare();
1926 if (ret != 0) {
1927 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
1928 return -EINVAL;
1929 }
1930
1931 index = q6audio_get_port_index(tx_port);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08001932 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001933 pr_err("%s: AFE port index[%d] invalid!\n",
1934 __func__, index);
1935 return -EINVAL;
1936 }
1937 ret = q6audio_validate_port(tx_port);
1938 if (ret < 0) {
1939 pr_err("%s: port id: 0x%x ret %d\n", __func__, tx_port, ret);
1940 return -EINVAL;
1941 }
1942
1943 cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1944 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1945 cfg.hdr.pkt_size = sizeof(cfg);
1946 cfg.hdr.src_port = 0;
1947 cfg.hdr.dest_port = 0;
1948 cfg.hdr.token = index;
1949 cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1950
1951 cfg.param.port_id = tx_port;
1952 cfg.param.payload_size = sizeof(struct afe_port_param_data_v2) +
1953 sizeof(struct afe_mod_enable_param);
1954 cfg.param.payload_address_lsw = 0;
1955 cfg.param.payload_address_lsw = 0;
1956 cfg.param.mem_map_handle = 0;
1957
1958 cfg.pdata.module_id = AFE_MODULE_AANC;
1959 cfg.pdata.param_id = AFE_PARAM_ID_ENABLE;
1960 cfg.pdata.param_size = sizeof(struct afe_mod_enable_param);
1961 cfg.pdata.reserved = 0;
1962
1963 cfg.data.mod_enable.enable = enable;
1964 cfg.data.mod_enable.reserved = 0;
1965
1966 ret = afe_apr_send_pkt((uint32_t *) &cfg, &this_afe.wait[index]);
1967 if (ret) {
1968 pr_err("%s: AFE AANC enable failed for tx_port 0x%x ret %d\n",
1969 __func__, tx_port, ret);
1970 }
1971 return ret;
1972}
1973
1974static int afe_send_bank_selection_clip(
1975 struct afe_param_id_clip_bank_sel *param)
1976{
1977 int ret;
1978 struct afe_svc_cmd_set_clip_bank_selection config;
1979
1980 if (!param) {
1981 pr_err("%s: Invalid params", __func__);
1982 return -EINVAL;
1983 }
1984 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1985 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1986 config.hdr.pkt_size = sizeof(config);
1987 config.hdr.src_port = 0;
1988 config.hdr.dest_port = 0;
1989 config.hdr.token = IDX_GLOBAL_CFG;
1990 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1991
1992 config.param.payload_size = sizeof(struct afe_port_param_data_v2) +
1993 sizeof(struct afe_param_id_clip_bank_sel);
1994 config.param.payload_address_lsw = 0x00;
1995 config.param.payload_address_msw = 0x00;
1996 config.param.mem_map_handle = 0x00;
1997
1998 config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
1999 config.pdata.param_id = AFE_PARAM_ID_CLIP_BANK_SEL_CFG;
2000 config.pdata.param_size =
2001 sizeof(struct afe_param_id_clip_bank_sel);
2002 config.bank_sel = *param;
2003 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
2004 if (ret) {
2005 pr_err("%s: AFE_PARAM_ID_CLIP_BANK_SEL_CFG failed %d\n",
2006 __func__, ret);
2007 }
2008 return ret;
2009}
2010int afe_send_aanc_version(
2011 struct afe_param_id_cdc_aanc_version *version_cfg)
2012{
2013 int ret;
2014 struct afe_svc_cmd_cdc_aanc_version config;
2015
2016 pr_debug("%s: enter\n", __func__);
2017 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2018 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2019 config.hdr.pkt_size = sizeof(config);
2020 config.hdr.src_port = 0;
2021 config.hdr.dest_port = 0;
2022 config.hdr.token = IDX_GLOBAL_CFG;
2023 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
2024
2025 config.param.payload_size = sizeof(struct afe_port_param_data_v2) +
2026 sizeof(struct afe_param_id_cdc_aanc_version);
2027 config.param.payload_address_lsw = 0x00;
2028 config.param.payload_address_msw = 0x00;
2029 config.param.mem_map_handle = 0x00;
2030
2031 config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
2032 config.pdata.param_id = AFE_PARAM_ID_CDC_AANC_VERSION;
2033 config.pdata.param_size =
2034 sizeof(struct afe_param_id_cdc_aanc_version);
2035 config.version = *version_cfg;
2036 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
2037 if (ret) {
2038 pr_err("%s: AFE_PARAM_ID_CDC_AANC_VERSION failed %d\n",
2039 __func__, ret);
2040 }
2041 return ret;
2042}
2043
2044int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type)
2045{
2046 int i;
2047
Ashish Jainb31517a2017-02-03 18:26:11 +05302048 if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
2049 port_id == AFE_PORT_ID_INT3_MI2S_TX) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002050 mad_type = MAD_SW_AUDIO;
2051 return 0;
2052 }
2053
2054 i = port_id - SLIMBUS_0_RX;
2055 if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
2056 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2057 return -EINVAL;
2058 }
2059 atomic_set(&afe_ports_mad_type[i], mad_type);
2060 return 0;
2061}
2062
2063enum afe_mad_type afe_port_get_mad_type(u16 port_id)
2064{
2065 int i;
2066
Ashish Jainb31517a2017-02-03 18:26:11 +05302067 if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
2068 port_id == AFE_PORT_ID_INT3_MI2S_TX)
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002069 return MAD_SW_AUDIO;
2070
2071 i = port_id - SLIMBUS_0_RX;
2072 if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
2073 pr_debug("%s: Non Slimbus port_id 0x%x\n", __func__, port_id);
2074 return MAD_HW_NONE;
2075 }
2076 return (enum afe_mad_type) atomic_read(&afe_ports_mad_type[i]);
2077}
2078
2079int afe_set_config(enum afe_config_type config_type, void *config_data, int arg)
2080{
2081 int ret;
2082
2083 pr_debug("%s: enter config_type %d\n", __func__, config_type);
2084 ret = afe_q6_interface_prepare();
2085 if (ret) {
2086 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2087 return ret;
2088 }
2089
2090 switch (config_type) {
2091 case AFE_SLIMBUS_SLAVE_CONFIG:
2092 ret = afe_send_slimbus_slave_cfg(config_data);
2093 if (!ret)
2094 ret = afe_init_cdc_reg_config();
2095 else
2096 pr_err("%s: Sending slimbus slave config failed %d\n",
2097 __func__, ret);
2098 break;
2099 case AFE_CDC_REGISTERS_CONFIG:
2100 ret = afe_send_codec_reg_config(config_data);
2101 break;
2102 case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
2103 ret = afe_send_slimbus_slave_port_cfg(config_data, arg);
2104 break;
2105 case AFE_AANC_VERSION:
2106 ret = afe_send_aanc_version(config_data);
2107 break;
2108 case AFE_CLIP_BANK_SEL:
2109 ret = afe_send_bank_selection_clip(config_data);
2110 break;
2111 case AFE_CDC_CLIP_REGISTERS_CONFIG:
2112 ret = afe_send_codec_reg_config(config_data);
2113 break;
2114 case AFE_CDC_REGISTER_PAGE_CONFIG:
2115 ret = afe_send_codec_reg_page_config(config_data);
2116 break;
2117 default:
2118 pr_err("%s: unknown configuration type %d",
2119 __func__, config_type);
2120 ret = -EINVAL;
2121 }
2122
2123 if (!ret)
2124 set_bit(config_type, &afe_configured_cmd);
2125
2126 return ret;
2127}
Karthikeyan Mani9d63f3b2017-06-27 14:23:26 -07002128EXPORT_SYMBOL(afe_set_config);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002129
2130/*
2131 * afe_clear_config - If SSR happens ADSP loses AFE configs, let AFE driver know
2132 * about the state so client driver can wait until AFE is
2133 * reconfigured.
2134 */
2135void afe_clear_config(enum afe_config_type config)
2136{
2137 clear_bit(config, &afe_configured_cmd);
2138}
Karthikeyan Mani9d63f3b2017-06-27 14:23:26 -07002139EXPORT_SYMBOL(afe_clear_config);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002140
2141bool afe_has_config(enum afe_config_type config)
2142{
2143 return !!test_bit(config, &afe_configured_cmd);
2144}
2145
2146int afe_send_spdif_clk_cfg(struct afe_param_id_spdif_clk_cfg *cfg,
2147 u16 port_id)
2148{
2149 struct afe_spdif_clk_config_command clk_cfg;
2150 int ret = 0;
2151 int index = 0;
2152
2153 if (!cfg) {
2154 pr_err("%s: Error, no configuration data\n", __func__);
2155 ret = -EINVAL;
2156 return ret;
2157 }
2158 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08002159 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002160 pr_err("%s: AFE port index[%d] invalid!\n",
2161 __func__, index);
2162 return -EINVAL;
2163 }
2164 ret = q6audio_validate_port(port_id);
2165 if (ret < 0) {
2166 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2167 return -EINVAL;
2168 }
2169
2170 ret = afe_q6_interface_prepare();
2171 if (ret) {
2172 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2173 return ret;
2174 }
2175 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2176 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2177 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
2178 clk_cfg.hdr.src_port = 0;
2179 clk_cfg.hdr.dest_port = 0;
2180 clk_cfg.hdr.token = index;
2181
2182 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2183 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
2184 clk_cfg.param.payload_address_lsw = 0x00;
2185 clk_cfg.param.payload_address_msw = 0x00;
2186 clk_cfg.param.mem_map_handle = 0x00;
2187 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2188 clk_cfg.pdata.param_id = AFE_PARAM_ID_SPDIF_CLK_CONFIG;
2189 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
2190 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
2191 - sizeof(clk_cfg.param);
2192 clk_cfg.clk_cfg = *cfg;
2193
2194 pr_debug("%s: Minor version = 0x%x clk val = %d\n"
2195 "clk root = 0x%x\n port id = 0x%x\n",
2196 __func__, cfg->clk_cfg_minor_version,
2197 cfg->clk_value, cfg->clk_root,
2198 q6audio_get_port_id(port_id));
2199
2200 atomic_set(&this_afe.state, 1);
2201 atomic_set(&this_afe.status, 0);
2202 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
2203 if (ret < 0) {
2204 pr_err("%s: AFE send clock config for port 0x%x failed ret = %d\n",
2205 __func__, port_id, ret);
2206 ret = -EINVAL;
2207 goto fail_cmd;
2208 }
2209
2210 ret = wait_event_timeout(this_afe.wait[index],
2211 (atomic_read(&this_afe.state) == 0),
2212 msecs_to_jiffies(TIMEOUT_MS));
2213 if (!ret) {
2214 pr_err("%s: wait_event timeout\n",
2215 __func__);
2216 ret = -EINVAL;
2217 goto fail_cmd;
2218 }
2219 if (atomic_read(&this_afe.status) > 0) {
2220 pr_err("%s: config cmd failed [%s]\n",
2221 __func__, adsp_err_get_err_str(
2222 atomic_read(&this_afe.status)));
2223 ret = adsp_err_get_lnx_err_code(
2224 atomic_read(&this_afe.status));
2225 goto fail_cmd;
2226 }
2227
2228fail_cmd:
2229 return ret;
2230}
2231
2232int afe_send_spdif_ch_status_cfg(struct afe_param_id_spdif_ch_status_cfg
2233 *ch_status_cfg, u16 port_id)
2234{
2235 struct afe_spdif_chstatus_config_command ch_status;
2236 int ret = 0;
2237 int index = 0;
2238
2239 if (!ch_status_cfg) {
2240 pr_err("%s: Error, no configuration data\n", __func__);
2241 ret = -EINVAL;
2242 return ret;
2243 }
2244 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08002245 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002246 pr_err("%s: AFE port index[%d] invalid!\n",
2247 __func__, index);
2248 return -EINVAL;
2249 }
2250 ret = q6audio_validate_port(port_id);
2251 if (ret < 0) {
2252 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2253 return -EINVAL;
2254 }
2255
2256 ret = afe_q6_interface_prepare();
2257 if (ret != 0) {
2258 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2259 return ret;
2260 }
2261 ch_status.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2262 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2263 ch_status.hdr.pkt_size = sizeof(ch_status_cfg);
2264 ch_status.hdr.src_port = 0;
2265 ch_status.hdr.dest_port = 0;
2266 ch_status.hdr.token = index;
2267
2268 ch_status.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2269 ch_status.param.port_id = q6audio_get_port_id(port_id);
2270 ch_status.param.payload_address_lsw = 0x00;
2271 ch_status.param.payload_address_msw = 0x00;
2272 ch_status.param.mem_map_handle = 0x00;
2273 ch_status.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2274 ch_status.pdata.param_id = AFE_PARAM_ID_SPDIF_CLK_CONFIG;
2275 ch_status.pdata.param_size = sizeof(ch_status.ch_status);
2276 ch_status.param.payload_size = sizeof(ch_status)
2277 - sizeof(struct apr_hdr) - sizeof(ch_status.param);
2278 ch_status.ch_status = *ch_status_cfg;
2279
2280 atomic_set(&this_afe.state, 1);
2281 atomic_set(&this_afe.status, 0);
2282 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &ch_status);
2283 if (ret < 0) {
2284 pr_err("%s: AFE send channel status for port 0x%x failed ret = %d\n",
2285 __func__, port_id, ret);
2286 ret = -EINVAL;
2287 goto fail_cmd;
2288 }
2289
2290 ret = wait_event_timeout(this_afe.wait[index],
2291 (atomic_read(&this_afe.state) == 0),
2292 msecs_to_jiffies(TIMEOUT_MS));
2293 if (!ret) {
2294 pr_err("%s: wait_event timeout\n",
2295 __func__);
2296 ret = -EINVAL;
2297 goto fail_cmd;
2298 }
2299 if (atomic_read(&this_afe.status) > 0) {
2300 pr_err("%s: config cmd failed [%s]\n",
2301 __func__, adsp_err_get_err_str(
2302 atomic_read(&this_afe.status)));
2303 ret = adsp_err_get_lnx_err_code(
2304 atomic_read(&this_afe.status));
2305 goto fail_cmd;
2306 }
2307
2308fail_cmd:
2309 return ret;
2310}
2311
2312static int afe_send_cmd_port_start(u16 port_id)
2313{
2314 struct afe_port_cmd_device_start start;
2315 int ret, index;
2316
2317 pr_debug("%s: enter\n", __func__);
2318 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08002319 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002320 pr_err("%s: AFE port index[%d] invalid!\n",
2321 __func__, index);
2322 return -EINVAL;
2323 }
2324 ret = q6audio_validate_port(port_id);
2325 if (ret < 0) {
2326 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2327 return -EINVAL;
2328 }
2329
2330 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2331 APR_HDR_LEN(APR_HDR_SIZE),
2332 APR_PKT_VER);
2333 start.hdr.pkt_size = sizeof(start);
2334 start.hdr.src_port = 0;
2335 start.hdr.dest_port = 0;
2336 start.hdr.token = index;
2337 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
2338 start.port_id = q6audio_get_port_id(port_id);
2339 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
2340 __func__, start.hdr.opcode, start.port_id);
2341
2342 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
2343 if (ret) {
2344 pr_err("%s: AFE enable for port 0x%x failed %d\n", __func__,
2345 port_id, ret);
2346 } else if (this_afe.task != current) {
2347 this_afe.task = current;
2348 pr_debug("task_name = %s pid = %d\n",
2349 this_afe.task->comm, this_afe.task->pid);
2350 }
2351
2352 return ret;
2353}
2354
2355static int afe_aanc_start(uint16_t tx_port_id, uint16_t rx_port_id)
2356{
2357 int ret;
2358
2359 pr_debug("%s: Tx port is 0x%x, Rx port is 0x%x\n",
2360 __func__, tx_port_id, rx_port_id);
2361 ret = afe_aanc_port_cfg(this_afe.apr, tx_port_id, rx_port_id);
2362 if (ret) {
2363 pr_err("%s: Send AANC Port Config failed %d\n",
2364 __func__, ret);
2365 goto fail_cmd;
2366 }
2367 send_afe_cal_type(AFE_AANC_CAL, tx_port_id);
2368
2369fail_cmd:
2370 return ret;
2371}
2372
2373int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port,
2374 u32 rate)
2375{
2376 struct afe_audioif_config_command config;
2377 int ret = 0;
2378 int index = 0;
2379 uint16_t port_index;
2380
2381 if (!spdif_port) {
2382 pr_err("%s: Error, no configuration data\n", __func__);
2383 ret = -EINVAL;
2384 return ret;
2385 }
2386
2387 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2388
2389 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08002390 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002391 pr_err("%s: AFE port index[%d] invalid!\n",
2392 __func__, index);
2393 return -EINVAL;
2394 }
2395 ret = q6audio_validate_port(port_id);
2396 if (ret < 0) {
2397 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2398 return -EINVAL;
2399 }
2400
2401 afe_send_cal(port_id);
2402 afe_send_hw_delay(port_id, rate);
2403
2404 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2405 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2406 config.hdr.pkt_size = sizeof(config);
2407 config.hdr.src_port = 0;
2408 config.hdr.dest_port = 0;
2409 config.hdr.token = index;
2410 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2411 config.param.port_id = q6audio_get_port_id(port_id);
2412 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
2413 sizeof(config.param);
2414 config.param.payload_address_lsw = 0x00;
2415 config.param.payload_address_msw = 0x00;
2416 config.param.mem_map_handle = 0x00;
2417 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2418 config.pdata.param_id = AFE_PARAM_ID_SPDIF_CONFIG;
2419 config.pdata.param_size = sizeof(config.port);
2420 config.port.spdif = spdif_port->cfg;
2421 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2422 if (ret) {
2423 pr_err("%s: AFE enable for port 0x%x failed ret = %d\n",
2424 __func__, port_id, ret);
2425 goto fail_cmd;
2426 }
2427
2428 port_index = afe_get_port_index(port_id);
2429 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
2430 this_afe.afe_sample_rates[port_index] = rate;
2431 } else {
2432 pr_err("%s: Invalid port index %d\n", __func__, port_index);
2433 ret = -EINVAL;
2434 goto fail_cmd;
2435 }
2436
2437 ret = afe_send_spdif_ch_status_cfg(&spdif_port->ch_status, port_id);
2438 if (ret < 0) {
2439 pr_err("%s: afe send failed %d\n", __func__, ret);
2440 goto fail_cmd;
2441 }
2442
2443 return afe_send_cmd_port_start(port_id);
2444
2445fail_cmd:
2446 return ret;
2447}
2448
2449int afe_send_slot_mapping_cfg(
2450 struct afe_param_id_slot_mapping_cfg *slot_mapping_cfg,
2451 u16 port_id)
2452{
2453 struct afe_slot_mapping_config_command config;
2454 int ret = 0;
2455 int index = 0;
2456
2457 if (!slot_mapping_cfg) {
2458 pr_err("%s: Error, no configuration data\n", __func__);
2459 return -EINVAL;
2460 }
2461
2462 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2463
2464 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08002465 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002466 pr_err("%s: AFE port index[%d] invalid!\n",
2467 __func__, index);
2468 return -EINVAL;
2469 }
2470 ret = q6audio_validate_port(port_id);
2471 if (ret < 0) {
2472 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2473 return -EINVAL;
2474 }
2475
2476 memset(&config, 0, sizeof(config));
2477 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2478 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2479 config.hdr.pkt_size = sizeof(config);
2480 config.hdr.src_port = 0;
2481 config.hdr.dest_port = 0;
2482 config.hdr.token = index;
2483
2484 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2485 config.param.port_id = q6audio_get_port_id(port_id);
2486 config.param.payload_size = sizeof(config)
2487 - sizeof(struct apr_hdr) - sizeof(config.param);
2488 config.param.payload_address_lsw = 0x00;
2489 config.param.payload_address_msw = 0x00;
2490 config.param.mem_map_handle = 0x00;
2491 config.pdata.module_id = AFE_MODULE_TDM;
2492 config.pdata.param_id = AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG;
2493 config.pdata.param_size = sizeof(config.slot_mapping);
2494 config.slot_mapping = *slot_mapping_cfg;
2495
2496 atomic_set(&this_afe.state, 1);
2497 atomic_set(&this_afe.status, 0);
2498 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
2499 if (ret < 0) {
2500 pr_err("%s: AFE send slot mapping for port 0x%x failed ret = %d\n",
2501 __func__, port_id, ret);
2502 ret = -EINVAL;
2503 goto fail_cmd;
2504 }
2505
2506 ret = wait_event_timeout(this_afe.wait[index],
2507 (atomic_read(&this_afe.state) == 0),
2508 msecs_to_jiffies(TIMEOUT_MS));
2509 if (!ret) {
2510 pr_err("%s: wait_event timeout\n",
2511 __func__);
2512 ret = -EINVAL;
2513 goto fail_cmd;
2514 }
2515 if (atomic_read(&this_afe.status) > 0) {
2516 pr_err("%s: config cmd failed [%s]\n",
2517 __func__, adsp_err_get_err_str(
2518 atomic_read(&this_afe.status)));
2519 ret = adsp_err_get_lnx_err_code(
2520 atomic_read(&this_afe.status));
2521 goto fail_cmd;
2522 }
2523
2524fail_cmd:
2525 return ret;
2526}
2527
2528int afe_send_custom_tdm_header_cfg(
2529 struct afe_param_id_custom_tdm_header_cfg *custom_tdm_header_cfg,
2530 u16 port_id)
2531{
2532 struct afe_custom_tdm_header_config_command config;
2533 int ret = 0;
2534 int index = 0;
2535
2536 if (!custom_tdm_header_cfg) {
2537 pr_err("%s: Error, no configuration data\n", __func__);
2538 return -EINVAL;
2539 }
2540
2541 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2542
2543 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08002544 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002545 pr_err("%s: AFE port index[%d] invalid!\n",
2546 __func__, index);
2547 return -EINVAL;
2548 }
2549 ret = q6audio_validate_port(port_id);
2550 if (ret < 0) {
2551 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2552 return -EINVAL;
2553 }
2554
2555 memset(&config, 0, sizeof(config));
2556 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2557 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2558 config.hdr.pkt_size = sizeof(config);
2559 config.hdr.src_port = 0;
2560 config.hdr.dest_port = 0;
2561 config.hdr.token = index;
2562
2563 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2564 config.param.port_id = q6audio_get_port_id(port_id);
2565 config.param.payload_size = sizeof(config)
2566 - sizeof(struct apr_hdr) - sizeof(config.param);
2567 config.param.payload_address_lsw = 0x00;
2568 config.param.payload_address_msw = 0x00;
2569 config.param.mem_map_handle = 0x00;
2570 config.pdata.module_id = AFE_MODULE_TDM;
2571 config.pdata.param_id = AFE_PARAM_ID_CUSTOM_TDM_HEADER_CONFIG;
2572 config.pdata.param_size = sizeof(config.custom_tdm_header);
2573 config.custom_tdm_header = *custom_tdm_header_cfg;
2574
2575 atomic_set(&this_afe.state, 1);
2576 atomic_set(&this_afe.status, 0);
2577 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
2578 if (ret < 0) {
2579 pr_err("%s: AFE send custom tdm header for port 0x%x failed ret = %d\n",
2580 __func__, port_id, ret);
2581 ret = -EINVAL;
2582 goto fail_cmd;
2583 }
2584
2585 ret = wait_event_timeout(this_afe.wait[index],
2586 (atomic_read(&this_afe.state) == 0),
2587 msecs_to_jiffies(TIMEOUT_MS));
2588 if (!ret) {
2589 pr_err("%s: wait_event timeout\n",
2590 __func__);
2591 ret = -EINVAL;
2592 goto fail_cmd;
2593 }
2594 if (atomic_read(&this_afe.status) > 0) {
2595 pr_err("%s: config cmd failed [%s]\n",
2596 __func__, adsp_err_get_err_str(
2597 atomic_read(&this_afe.status)));
2598 ret = adsp_err_get_lnx_err_code(
2599 atomic_read(&this_afe.status));
2600 goto fail_cmd;
2601 }
2602
2603fail_cmd:
2604 return ret;
2605}
2606
2607int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
Josh Kirschdb567c12017-01-04 17:59:30 -08002608 u32 rate, u16 num_groups)
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002609{
2610 struct afe_audioif_config_command config;
2611 int ret = 0;
2612 int index = 0;
2613 uint16_t port_index = 0;
2614 enum afe_mad_type mad_type = MAD_HW_NONE;
2615
2616 if (!tdm_port) {
2617 pr_err("%s: Error, no configuration data\n", __func__);
2618 return -EINVAL;
2619 }
2620
2621 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2622
2623 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08002624 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002625 pr_err("%s: AFE port index[%d] invalid!\n",
2626 __func__, index);
2627 return -EINVAL;
2628 }
2629 ret = q6audio_validate_port(port_id);
2630 if (ret < 0) {
2631 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2632 return -EINVAL;
2633 }
2634
2635 ret = afe_q6_interface_prepare();
2636 if (ret != 0) {
2637 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2638 return ret;
2639 }
2640
Siena Richard23364c92017-01-11 16:20:55 -08002641 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
2642 this_afe.afe_sample_rates[index] = rate;
2643
2644 if (this_afe.rt_cb)
2645 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
2646 }
2647
Josh Kirschdb567c12017-01-04 17:59:30 -08002648 /* Also send the topology id here if multiple ports: */
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002649 port_index = afe_get_port_index(port_id);
Josh Kirschdb567c12017-01-04 17:59:30 -08002650 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE) &&
2651 num_groups > 1) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002652 /* One time call: only for first time */
2653 afe_send_custom_topology();
2654 afe_send_port_topology_id(port_id);
2655 afe_send_cal(port_id);
2656 afe_send_hw_delay(port_id, rate);
2657 }
2658
2659 /* Start SW MAD module */
2660 mad_type = afe_port_get_mad_type(port_id);
2661 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
2662 mad_type);
2663 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
2664 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
2665 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
2666 pr_err("%s: AFE isn't configured yet for\n"
2667 "HW MAD try Again\n", __func__);
2668 ret = -EAGAIN;
2669 goto fail_cmd;
2670 }
2671 ret = afe_turn_onoff_hw_mad(mad_type, true);
2672 if (ret) {
2673 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
2674 __func__, ret);
2675 goto fail_cmd;
2676 }
2677 }
2678
2679 memset(&config, 0, sizeof(config));
2680 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2681 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2682 config.hdr.pkt_size = sizeof(config);
2683 config.hdr.src_port = 0;
2684 config.hdr.dest_port = 0;
2685 config.hdr.token = index;
2686 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2687 config.param.port_id = q6audio_get_port_id(port_id);
2688 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
2689 sizeof(config.param);
2690 config.param.payload_address_lsw = 0x00;
2691 config.param.payload_address_msw = 0x00;
2692 config.param.mem_map_handle = 0x00;
2693 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2694 config.pdata.param_id = AFE_PARAM_ID_TDM_CONFIG;
2695 config.pdata.param_size = sizeof(config.port);
2696 config.port.tdm = tdm_port->tdm;
2697
2698 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2699 if (ret) {
2700 pr_err("%s: AFE enable for port 0x%x failed ret = %d\n",
2701 __func__, port_id, ret);
2702 goto fail_cmd;
2703 }
2704
2705 port_index = afe_get_port_index(port_id);
2706 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
2707 this_afe.afe_sample_rates[port_index] = rate;
2708 } else {
2709 pr_err("%s: Invalid port index %d\n", __func__, port_index);
2710 ret = -EINVAL;
2711 goto fail_cmd;
2712 }
Josh Kirschdb567c12017-01-04 17:59:30 -08002713 /* slot mapping is not need if there is only one group */
2714 if (num_groups > 1) {
2715 ret = afe_send_slot_mapping_cfg(&tdm_port->slot_mapping,
2716 port_id);
2717 if (ret < 0) {
2718 pr_err("%s: afe send failed %d\n", __func__, ret);
2719 goto fail_cmd;
2720 }
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002721 }
2722
2723 if (tdm_port->custom_tdm_header.header_type) {
2724 ret = afe_send_custom_tdm_header_cfg(
2725 &tdm_port->custom_tdm_header, port_id);
2726 if (ret < 0) {
2727 pr_err("%s: afe send failed %d\n", __func__, ret);
2728 goto fail_cmd;
2729 }
2730 }
2731
2732 ret = afe_send_cmd_port_start(port_id);
2733
2734fail_cmd:
2735 return ret;
2736}
2737
2738void afe_set_cal_mode(u16 port_id, enum afe_cal_mode afe_cal_mode)
2739{
2740 uint16_t port_index;
2741
2742 port_index = afe_get_port_index(port_id);
2743 this_afe.afe_cal_mode[port_index] = afe_cal_mode;
2744}
2745
Siena Richard23364c92017-01-11 16:20:55 -08002746void afe_set_routing_callback(routing_cb cb)
2747{
2748 this_afe.rt_cb = cb;
2749}
2750
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002751int afe_port_send_usb_dev_param(u16 port_id, union afe_port_config *afe_config)
2752{
2753 struct afe_usb_audio_dev_param_command config;
2754 int ret = 0, index = 0;
2755
2756 if (!afe_config) {
2757 pr_err("%s: Error, no configuration data\n", __func__);
2758 ret = -EINVAL;
2759 goto exit;
2760 }
2761 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08002762 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002763 pr_err("%s: AFE port index[%d] invalid! for port ID 0x%x\n",
2764 __func__, index, port_id);
2765 ret = -EINVAL;
2766 goto exit;
2767 }
2768 memset(&config, 0, sizeof(config));
2769 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2770 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2771 config.hdr.pkt_size = sizeof(config);
2772 config.hdr.src_port = 0;
2773 config.hdr.dest_port = 0;
2774 config.hdr.token = index;
2775 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2776 config.param.port_id = q6audio_get_port_id(port_id);
2777 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
2778 sizeof(config.param);
2779 config.param.payload_address_lsw = 0x00;
2780 config.param.payload_address_msw = 0x00;
2781 config.param.mem_map_handle = 0x00;
2782 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2783 config.pdata.param_id = AFE_PARAM_ID_USB_AUDIO_DEV_PARAMS;
2784 config.pdata.param_size = sizeof(config.usb_dev);
2785 config.usb_dev.cfg_minor_version =
2786 AFE_API_MINIOR_VERSION_USB_AUDIO_CONFIG;
2787 config.usb_dev.dev_token = afe_config->usb_audio.dev_token;
2788
2789 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2790 if (ret) {
2791 pr_err("%s: AFE device param cmd failed %d\n",
2792 __func__, ret);
2793 ret = -EINVAL;
2794 goto exit;
2795 }
Haynes Mathew George434a2e12016-10-27 16:56:21 -07002796
2797 config.pdata.param_id = AFE_PARAM_ID_USB_AUDIO_DEV_LPCM_FMT;
2798 config.pdata.param_size = sizeof(config.lpcm_fmt);
2799 config.lpcm_fmt.cfg_minor_version =
2800 AFE_API_MINIOR_VERSION_USB_AUDIO_CONFIG;
2801 config.lpcm_fmt.endian = afe_config->usb_audio.endian;
2802
2803 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2804 if (ret) {
2805 pr_err("%s: AFE device param cmd LPCM_FMT failed %d\n",
2806 __func__, ret);
2807 ret = -EINVAL;
2808 goto exit;
2809 }
2810
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002811exit:
2812 return ret;
2813}
2814
2815static int q6afe_send_enc_config(u16 port_id,
2816 union afe_enc_config_data *cfg, u32 format,
2817 union afe_port_config afe_config,
2818 u16 afe_in_channels, u16 afe_in_bit_width)
2819{
2820 struct afe_audioif_config_command config;
2821 int index;
2822 int ret;
2823 int payload_size = sizeof(config) - sizeof(struct apr_hdr) -
2824 sizeof(config.param) - sizeof(config.port);
2825
2826 pr_debug("%s:update DSP for enc format = %d\n", __func__, format);
2827 if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 &&
2828 format != ASM_MEDIA_FMT_APTX && format != ASM_MEDIA_FMT_APTX_HD) {
2829 pr_err("%s:Unsuppported format Ignore AFE config\n", __func__);
2830 return 0;
2831 }
2832 memset(&config, 0, sizeof(config));
2833 index = q6audio_get_port_index(port_id);
Xiaoyu Yed3650382017-02-02 12:58:01 -08002834 if (index < 0) {
2835 pr_err("%s: Invalid index number: %d\n", __func__, index);
2836 return -EINVAL;
2837 }
2838
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002839 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2840 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2841 config.hdr.pkt_size = sizeof(config);
2842 config.hdr.src_port = 0;
2843 config.hdr.dest_port = 0;
2844 config.hdr.token = index;
2845
2846 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2847 config.param.port_id = q6audio_get_port_id(port_id);
2848 config.param.payload_size = payload_size + sizeof(config.port.enc_fmt);
2849 config.param.payload_address_lsw = 0x00;
2850 config.param.payload_address_msw = 0x00;
2851 config.param.mem_map_handle = 0x00;
2852 config.pdata.module_id = AFE_MODULE_ID_ENCODER;
2853 config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_FMT_ID;
2854 config.pdata.param_size = sizeof(config.port.enc_fmt);
2855 config.port.enc_fmt.fmt_id = format;
2856 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENC_FMT_ID payload: %d\n",
2857 __func__, config.param.payload_size);
2858 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2859 if (ret) {
2860 pr_err("%s:unable to send AFE_ENCODER_PARAM_ID_ENC_FMT_ID",
2861 __func__);
2862 goto exit;
2863 }
2864
2865 config.param.payload_size = payload_size
2866 + sizeof(config.port.enc_blk_param);
2867 pr_debug("%s:send AFE_ENCODER_PARAM_ID_ENC_CFG_BLK to DSP payload:%d\n",
2868 __func__, config.param.payload_size);
2869 config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_CFG_BLK;
2870 config.pdata.param_size = sizeof(config.port.enc_blk_param);
2871 config.port.enc_blk_param.enc_cfg_blk_size =
2872 sizeof(config.port.enc_blk_param.enc_blk_config);
2873 config.port.enc_blk_param.enc_blk_config = *cfg;
2874 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2875 if (ret) {
2876 pr_err("%s: AFE_ENCODER_PARAM_ID_ENC_CFG_BLK for port 0x%x failed %d\n",
2877 __func__, port_id, ret);
2878 goto exit;
2879 }
2880
2881 config.param.payload_size =
2882 payload_size + sizeof(config.port.enc_pkt_id_param);
2883 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_PACKETIZER to DSP payload = %d",
2884 __func__, config.param.payload_size);
2885 config.pdata.param_id = AFE_ENCODER_PARAM_ID_PACKETIZER_ID;
2886 config.pdata.param_size = sizeof(config.port.enc_pkt_id_param);
2887 config.port.enc_pkt_id_param.enc_packetizer_id =
2888 AFE_MODULE_ID_PACKETIZER_COP;
2889 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2890 if (ret) {
2891 pr_err("%s: AFE_ENCODER_PARAM_ID_PACKETIZER for port 0x%x failed %d\n",
2892 __func__, port_id, ret);
2893 goto exit;
2894 }
2895
2896 config.param.payload_size =
2897 payload_size + sizeof(config.port.media_type);
2898 config.pdata.param_size = sizeof(config.port.media_type);
2899
2900 pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP", __func__);
2901 config.pdata.module_id = AFE_MODULE_PORT;
2902 config.pdata.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
2903 config.port.media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
2904 config.port.media_type.sample_rate = afe_config.slim_sch.sample_rate;
2905 if (afe_in_bit_width)
2906 config.port.media_type.bit_width = afe_in_bit_width;
2907 else
2908 config.port.media_type.bit_width =
2909 afe_config.slim_sch.bit_width;
2910
2911 if (afe_in_channels)
2912 config.port.media_type.num_channels = afe_in_channels;
2913 else
2914 config.port.media_type.num_channels =
2915 afe_config.slim_sch.num_channels;
2916 config.port.media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
2917 config.port.media_type.reserved = 0;
2918
2919 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2920 if (ret) {
2921 pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
2922 __func__, port_id, ret);
2923 goto exit;
2924 }
2925
2926exit:
2927 return ret;
2928}
2929
2930static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
2931 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
2932 union afe_enc_config_data *cfg, u32 enc_format)
2933{
2934 struct afe_audioif_config_command config;
2935 int ret = 0;
2936 int cfg_type;
2937 int index = 0;
2938 enum afe_mad_type mad_type;
2939 uint16_t port_index;
2940
2941 if (!afe_config) {
2942 pr_err("%s: Error, no configuration data\n", __func__);
2943 ret = -EINVAL;
2944 return ret;
2945 }
2946
2947 if ((port_id == RT_PROXY_DAI_001_RX) ||
2948 (port_id == RT_PROXY_DAI_002_TX)) {
Xiaoyu Ye6e29a5f2017-01-30 12:36:23 -08002949 pr_debug("%s: before incrementing pcm_afe_instance %d port_id 0x%x\n",
2950 __func__,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002951 pcm_afe_instance[port_id & 0x1], port_id);
2952 port_id = VIRTUAL_ID_TO_PORTID(port_id);
2953 pcm_afe_instance[port_id & 0x1]++;
2954 return 0;
2955 }
2956 if ((port_id == RT_PROXY_DAI_002_RX) ||
2957 (port_id == RT_PROXY_DAI_001_TX)) {
Xiaoyu Ye6e29a5f2017-01-30 12:36:23 -08002958 pr_debug("%s: before incrementing proxy_afe_instance %d port_id 0x%x\n",
2959 __func__,
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002960 proxy_afe_instance[port_id & 0x1], port_id);
2961
2962 if (!afe_close_done[port_id & 0x1]) {
2963 /*close pcm dai corresponding to the proxy dai*/
2964 afe_close(port_id - 0x10);
2965 pcm_afe_instance[port_id & 0x1]++;
2966 pr_debug("%s: reconfigure afe port again\n", __func__);
2967 }
2968 proxy_afe_instance[port_id & 0x1]++;
2969 afe_close_done[port_id & 0x1] = false;
2970 port_id = VIRTUAL_ID_TO_PORTID(port_id);
2971 }
2972
2973 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2974
2975 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08002976 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002977 pr_err("%s: AFE port index[%d] invalid!\n",
2978 __func__, index);
2979 return -EINVAL;
2980 }
2981 ret = q6audio_validate_port(port_id);
2982 if (ret < 0) {
2983 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2984 return -EINVAL;
2985 }
2986
2987 ret = afe_q6_interface_prepare();
2988 if (ret != 0) {
2989 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2990 return ret;
2991 }
2992
Siena Richard23364c92017-01-11 16:20:55 -08002993 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
2994 this_afe.afe_sample_rates[index] = rate;
2995
2996 if (this_afe.rt_cb)
2997 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
2998 }
2999
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003000 mutex_lock(&this_afe.afe_cmd_lock);
3001 /* Also send the topology id here: */
3002 port_index = afe_get_port_index(port_id);
3003 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
3004 /* One time call: only for first time */
3005 afe_send_custom_topology();
3006 afe_send_port_topology_id(port_id);
3007 afe_send_cal(port_id);
3008 afe_send_hw_delay(port_id, rate);
3009 }
3010
3011 /* Start SW MAD module */
3012 mad_type = afe_port_get_mad_type(port_id);
3013 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
3014 mad_type);
3015 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
3016 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
3017 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
3018 pr_err("%s: AFE isn't configured yet for\n"
3019 "HW MAD try Again\n", __func__);
3020 ret = -EAGAIN;
3021 goto fail_cmd;
3022 }
3023 ret = afe_turn_onoff_hw_mad(mad_type, true);
3024 if (ret) {
3025 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
3026 __func__, ret);
3027 goto fail_cmd;
3028 }
3029 }
3030
3031 if ((this_afe.aanc_info.aanc_active) &&
3032 (this_afe.aanc_info.aanc_tx_port == port_id)) {
3033 this_afe.aanc_info.aanc_tx_port_sample_rate = rate;
3034 port_index =
3035 afe_get_port_index(this_afe.aanc_info.aanc_rx_port);
3036 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3037 this_afe.aanc_info.aanc_rx_port_sample_rate =
3038 this_afe.afe_sample_rates[port_index];
3039 } else {
3040 pr_err("%s: Invalid port index %d\n",
3041 __func__, port_index);
3042 ret = -EINVAL;
3043 goto fail_cmd;
3044 }
3045 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
3046 this_afe.aanc_info.aanc_rx_port);
3047 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
3048 }
3049
3050 if ((port_id == AFE_PORT_ID_USB_RX) ||
3051 (port_id == AFE_PORT_ID_USB_TX)) {
3052 ret = afe_port_send_usb_dev_param(port_id, afe_config);
3053 if (ret) {
3054 pr_err("%s: AFE device param for port 0x%x failed %d\n",
3055 __func__, port_id, ret);
3056 ret = -EINVAL;
3057 goto fail_cmd;
3058 }
3059 }
3060
3061 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3062 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3063 config.hdr.pkt_size = sizeof(config);
3064 config.hdr.src_port = 0;
3065 config.hdr.dest_port = 0;
3066 config.hdr.token = index;
3067
3068 switch (port_id) {
3069 case AFE_PORT_ID_PRIMARY_PCM_RX:
3070 case AFE_PORT_ID_PRIMARY_PCM_TX:
3071 case AFE_PORT_ID_SECONDARY_PCM_RX:
3072 case AFE_PORT_ID_SECONDARY_PCM_TX:
3073 case AFE_PORT_ID_TERTIARY_PCM_RX:
3074 case AFE_PORT_ID_TERTIARY_PCM_TX:
3075 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3076 case AFE_PORT_ID_QUATERNARY_PCM_TX:
3077 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
3078 break;
3079 case PRIMARY_I2S_RX:
3080 case PRIMARY_I2S_TX:
3081 case SECONDARY_I2S_RX:
3082 case SECONDARY_I2S_TX:
3083 case MI2S_RX:
3084 case MI2S_TX:
3085 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3086 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3087 case AFE_PORT_ID_SECONDARY_MI2S_RX:
3088 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
3089 case AFE_PORT_ID_SECONDARY_MI2S_TX:
3090 case AFE_PORT_ID_TERTIARY_MI2S_RX:
3091 case AFE_PORT_ID_TERTIARY_MI2S_TX:
3092 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3093 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3094 case AFE_PORT_ID_QUINARY_MI2S_RX:
3095 case AFE_PORT_ID_QUINARY_MI2S_TX:
3096 case AFE_PORT_ID_SENARY_MI2S_TX:
Laxminath Kasam4e444572017-01-15 20:00:11 +05303097 case AFE_PORT_ID_INT0_MI2S_RX:
3098 case AFE_PORT_ID_INT0_MI2S_TX:
3099 case AFE_PORT_ID_INT1_MI2S_RX:
3100 case AFE_PORT_ID_INT1_MI2S_TX:
3101 case AFE_PORT_ID_INT2_MI2S_RX:
3102 case AFE_PORT_ID_INT2_MI2S_TX:
3103 case AFE_PORT_ID_INT3_MI2S_RX:
3104 case AFE_PORT_ID_INT3_MI2S_TX:
3105 case AFE_PORT_ID_INT4_MI2S_RX:
3106 case AFE_PORT_ID_INT4_MI2S_TX:
3107 case AFE_PORT_ID_INT5_MI2S_RX:
3108 case AFE_PORT_ID_INT5_MI2S_TX:
3109 case AFE_PORT_ID_INT6_MI2S_RX:
3110 case AFE_PORT_ID_INT6_MI2S_TX:
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003111 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
3112 break;
3113 case HDMI_RX:
3114 case DISPLAY_PORT_RX:
3115 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
3116 break;
3117 case VOICE_PLAYBACK_TX:
3118 case VOICE2_PLAYBACK_TX:
3119 case VOICE_RECORD_RX:
3120 case VOICE_RECORD_TX:
3121 cfg_type = AFE_PARAM_ID_PSEUDO_PORT_CONFIG;
3122 break;
3123 case SLIMBUS_0_RX:
3124 case SLIMBUS_0_TX:
3125 case SLIMBUS_1_RX:
3126 case SLIMBUS_1_TX:
3127 case SLIMBUS_2_RX:
3128 case SLIMBUS_2_TX:
3129 case SLIMBUS_3_RX:
3130 case SLIMBUS_3_TX:
3131 case SLIMBUS_4_RX:
3132 case SLIMBUS_4_TX:
3133 case SLIMBUS_5_RX:
3134 case SLIMBUS_5_TX:
3135 case SLIMBUS_6_RX:
3136 case SLIMBUS_6_TX:
3137 case SLIMBUS_7_RX:
3138 case SLIMBUS_7_TX:
3139 case SLIMBUS_8_RX:
3140 case SLIMBUS_8_TX:
3141 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
3142 break;
3143 case AFE_PORT_ID_USB_RX:
3144 case AFE_PORT_ID_USB_TX:
3145 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
3146 break;
3147 case RT_PROXY_PORT_001_RX:
3148 case RT_PROXY_PORT_001_TX:
3149 cfg_type = AFE_PARAM_ID_RT_PROXY_CONFIG;
3150 break;
3151 case INT_BT_SCO_RX:
3152 case INT_BT_A2DP_RX:
3153 case INT_BT_SCO_TX:
3154 case INT_FM_RX:
3155 case INT_FM_TX:
3156 cfg_type = AFE_PARAM_ID_INTERNAL_BT_FM_CONFIG;
3157 break;
3158 default:
3159 pr_err("%s: Invalid port id 0x%x\n", __func__, port_id);
3160 ret = -EINVAL;
3161 goto fail_cmd;
3162 }
3163 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3164 config.param.port_id = q6audio_get_port_id(port_id);
3165 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
3166 sizeof(config.param);
3167 config.param.payload_address_lsw = 0x00;
3168 config.param.payload_address_msw = 0x00;
3169 config.param.mem_map_handle = 0x00;
3170 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3171 config.pdata.param_id = cfg_type;
3172 config.pdata.param_size = sizeof(config.port);
3173
3174 config.port = *afe_config;
3175 if ((enc_format != ASM_MEDIA_FMT_NONE) &&
3176 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
3177 config.port.slim_sch.data_format =
3178 AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED;
3179 }
3180 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3181 if (ret) {
3182 pr_err("%s: AFE enable for port 0x%x failed %d\n",
3183 __func__, port_id, ret);
3184 goto fail_cmd;
3185 }
3186
3187 if ((enc_format != ASM_MEDIA_FMT_NONE) &&
3188 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
3189 pr_debug("%s: Found AFE encoder support for SLIMBUS enc_format = %d\n",
3190 __func__, enc_format);
3191 ret = q6afe_send_enc_config(port_id, cfg, enc_format,
3192 *afe_config, afe_in_channels,
3193 afe_in_bit_width);
3194 if (ret) {
3195 pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
3196 __func__, port_id, ret);
3197 goto fail_cmd;
3198 }
3199 }
3200
3201 port_index = afe_get_port_index(port_id);
3202 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003203 /*
3204 * If afe_port_start() for tx port called before
3205 * rx port, then aanc rx sample rate is zero. So,
3206 * AANC state machine in AFE will not get triggered.
3207 * Make sure to check whether aanc is active during
3208 * afe_port_start() for rx port and if aanc rx
3209 * sample rate is zero, call afe_aanc_start to configure
3210 * aanc with valid sample rates.
3211 */
3212 if (this_afe.aanc_info.aanc_active &&
3213 !this_afe.aanc_info.aanc_rx_port_sample_rate) {
3214 this_afe.aanc_info.aanc_rx_port_sample_rate =
3215 this_afe.afe_sample_rates[port_index];
3216 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
3217 this_afe.aanc_info.aanc_rx_port);
3218 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
3219 }
3220 } else {
3221 pr_err("%s: Invalid port index %d\n", __func__, port_index);
3222 ret = -EINVAL;
3223 goto fail_cmd;
3224 }
3225 ret = afe_send_cmd_port_start(port_id);
3226
3227fail_cmd:
3228 mutex_unlock(&this_afe.afe_cmd_lock);
3229 return ret;
3230}
3231
3232/**
3233 * afe_port_start - to configure AFE session with
3234 * specified port configuration
3235 *
3236 * @port_id: AFE port id number
3237 * @afe_config: port configutation
3238 * @rate: sampling rate of port
3239 *
3240 * Returns 0 on success or error value on port start failure.
3241 */
3242int afe_port_start(u16 port_id, union afe_port_config *afe_config,
3243 u32 rate)
3244{
3245 return __afe_port_start(port_id, afe_config, rate,
3246 0, 0, NULL, ASM_MEDIA_FMT_NONE);
3247}
3248EXPORT_SYMBOL(afe_port_start);
3249
3250/**
3251 * afe_port_start_v2 - to configure AFE session with
3252 * specified port configuration and encoder params
3253 *
3254 * @port_id: AFE port id number
3255 * @afe_config: port configutation
3256 * @rate: sampling rate of port
3257 * @cfg: AFE encoder configuration information to setup encoder
3258 * @afe_in_channels: AFE input channel configuration, this needs
3259 * update only if input channel is differ from AFE output
3260 *
3261 * Returns 0 on success or error value on port start failure.
3262 */
3263int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
3264 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
3265 struct afe_enc_config *enc_cfg)
3266{
3267 return __afe_port_start(port_id, afe_config, rate,
3268 afe_in_channels, afe_in_bit_width,
3269 &enc_cfg->data, enc_cfg->format);
3270}
3271EXPORT_SYMBOL(afe_port_start_v2);
3272
3273int afe_get_port_index(u16 port_id)
3274{
3275 switch (port_id) {
3276 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
3277 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
3278 case AFE_PORT_ID_PRIMARY_PCM_RX:
3279 return IDX_AFE_PORT_ID_PRIMARY_PCM_RX;
3280 case AFE_PORT_ID_PRIMARY_PCM_TX:
3281 return IDX_AFE_PORT_ID_PRIMARY_PCM_TX;
3282 case AFE_PORT_ID_SECONDARY_PCM_RX:
3283 return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
3284 case AFE_PORT_ID_SECONDARY_PCM_TX:
3285 return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
3286 case AFE_PORT_ID_TERTIARY_PCM_RX:
3287 return IDX_AFE_PORT_ID_TERTIARY_PCM_RX;
3288 case AFE_PORT_ID_TERTIARY_PCM_TX:
3289 return IDX_AFE_PORT_ID_TERTIARY_PCM_TX;
3290 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3291 return IDX_AFE_PORT_ID_QUATERNARY_PCM_RX;
3292 case AFE_PORT_ID_QUATERNARY_PCM_TX:
3293 return IDX_AFE_PORT_ID_QUATERNARY_PCM_TX;
3294 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
3295 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
3296 case MI2S_RX: return IDX_MI2S_RX;
3297 case MI2S_TX: return IDX_MI2S_TX;
3298 case HDMI_RX: return IDX_HDMI_RX;
3299 case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX;
3300 case AFE_PORT_ID_SPDIF_RX: return IDX_SPDIF_RX;
3301 case RSVD_2: return IDX_RSVD_2;
3302 case RSVD_3: return IDX_RSVD_3;
3303 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
3304 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
3305 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
3306 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
3307 case VOICE2_PLAYBACK_TX: return IDX_VOICE2_PLAYBACK_TX;
3308 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
3309 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
3310 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
3311 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
3312 case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
3313 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
3314 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
3315 case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
3316 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
3317 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
3318 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
3319 case INT_FM_RX: return IDX_INT_FM_RX;
3320 case INT_FM_TX: return IDX_INT_FM_TX;
3321 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
3322 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
3323 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
3324 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
3325 case SLIMBUS_5_RX: return IDX_SLIMBUS_5_RX;
3326 case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX;
3327 case SLIMBUS_6_RX: return IDX_SLIMBUS_6_RX;
3328 case SLIMBUS_6_TX: return IDX_SLIMBUS_6_TX;
3329 case SLIMBUS_7_RX: return IDX_SLIMBUS_7_RX;
3330 case SLIMBUS_7_TX: return IDX_SLIMBUS_7_TX;
3331 case SLIMBUS_8_RX: return IDX_SLIMBUS_8_RX;
3332 case SLIMBUS_8_TX: return IDX_SLIMBUS_8_TX;
3333 case AFE_PORT_ID_USB_RX: return IDX_AFE_PORT_ID_USB_RX;
3334 case AFE_PORT_ID_USB_TX: return IDX_AFE_PORT_ID_USB_TX;
3335 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3336 return IDX_AFE_PORT_ID_PRIMARY_MI2S_RX;
3337 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3338 return IDX_AFE_PORT_ID_PRIMARY_MI2S_TX;
3339 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3340 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
3341 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3342 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX;
3343 case AFE_PORT_ID_SECONDARY_MI2S_RX:
3344 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX;
3345 case AFE_PORT_ID_SECONDARY_MI2S_TX:
3346 return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX;
3347 case AFE_PORT_ID_TERTIARY_MI2S_RX:
3348 return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX;
3349 case AFE_PORT_ID_TERTIARY_MI2S_TX:
3350 return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX;
3351 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
3352 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_SD1;
3353 case AFE_PORT_ID_QUINARY_MI2S_RX:
3354 return IDX_AFE_PORT_ID_QUINARY_MI2S_RX;
3355 case AFE_PORT_ID_QUINARY_MI2S_TX:
3356 return IDX_AFE_PORT_ID_QUINARY_MI2S_TX;
3357 case AFE_PORT_ID_SENARY_MI2S_TX:
3358 return IDX_AFE_PORT_ID_SENARY_MI2S_TX;
3359 case AFE_PORT_ID_PRIMARY_TDM_RX:
3360 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_0;
3361 case AFE_PORT_ID_PRIMARY_TDM_TX:
3362 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_0;
3363 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
3364 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_1;
3365 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
3366 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_1;
3367 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
3368 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_2;
3369 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
3370 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_2;
3371 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
3372 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_3;
3373 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
3374 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_3;
3375 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
3376 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_4;
3377 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
3378 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_4;
3379 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
3380 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_5;
3381 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
3382 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_5;
3383 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
3384 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_6;
3385 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
3386 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_6;
3387 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
3388 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_7;
3389 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
3390 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_7;
3391 case AFE_PORT_ID_SECONDARY_TDM_RX:
3392 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_0;
3393 case AFE_PORT_ID_SECONDARY_TDM_TX:
3394 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_0;
3395 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
3396 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_1;
3397 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
3398 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_1;
3399 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
3400 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_2;
3401 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
3402 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_2;
3403 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
3404 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_3;
3405 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
3406 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_3;
3407 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
3408 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_4;
3409 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
3410 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_4;
3411 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
3412 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_5;
3413 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
3414 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_5;
3415 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
3416 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_6;
3417 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
3418 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_6;
3419 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
3420 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_7;
3421 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
3422 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_7;
3423 case AFE_PORT_ID_TERTIARY_TDM_RX:
3424 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_0;
3425 case AFE_PORT_ID_TERTIARY_TDM_TX:
3426 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_0;
3427 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
3428 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_1;
3429 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
3430 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_1;
3431 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
3432 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_2;
3433 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
3434 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_2;
3435 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
3436 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_3;
3437 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
3438 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_3;
3439 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
3440 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_4;
3441 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
3442 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_4;
3443 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
3444 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_5;
3445 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
3446 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_5;
3447 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
3448 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_6;
3449 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
3450 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_6;
3451 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
3452 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_7;
3453 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
3454 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_7;
3455 case AFE_PORT_ID_QUATERNARY_TDM_RX:
3456 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_0;
3457 case AFE_PORT_ID_QUATERNARY_TDM_TX:
3458 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_0;
3459 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
3460 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_1;
3461 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
3462 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_1;
3463 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
3464 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_2;
3465 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
3466 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_2;
3467 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
3468 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_3;
3469 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
3470 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_3;
3471 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
3472 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_4;
3473 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
3474 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_4;
3475 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
3476 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_5;
3477 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
3478 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_5;
3479 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
3480 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_6;
3481 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
3482 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_6;
3483 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
3484 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_7;
3485 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
3486 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_7;
Laxminath Kasam4e444572017-01-15 20:00:11 +05303487 case AFE_PORT_ID_INT0_MI2S_RX:
3488 return IDX_AFE_PORT_ID_INT0_MI2S_RX;
3489 case AFE_PORT_ID_INT0_MI2S_TX:
3490 return IDX_AFE_PORT_ID_INT0_MI2S_TX;
3491 case AFE_PORT_ID_INT1_MI2S_RX:
3492 return IDX_AFE_PORT_ID_INT1_MI2S_RX;
3493 case AFE_PORT_ID_INT1_MI2S_TX:
3494 return IDX_AFE_PORT_ID_INT1_MI2S_TX;
3495 case AFE_PORT_ID_INT2_MI2S_RX:
3496 return IDX_AFE_PORT_ID_INT2_MI2S_RX;
3497 case AFE_PORT_ID_INT2_MI2S_TX:
3498 return IDX_AFE_PORT_ID_INT2_MI2S_TX;
3499 case AFE_PORT_ID_INT3_MI2S_RX:
3500 return IDX_AFE_PORT_ID_INT3_MI2S_RX;
3501 case AFE_PORT_ID_INT3_MI2S_TX:
3502 return IDX_AFE_PORT_ID_INT3_MI2S_TX;
3503 case AFE_PORT_ID_INT4_MI2S_RX:
3504 return IDX_AFE_PORT_ID_INT4_MI2S_RX;
3505 case AFE_PORT_ID_INT4_MI2S_TX:
3506 return IDX_AFE_PORT_ID_INT4_MI2S_TX;
3507 case AFE_PORT_ID_INT5_MI2S_RX:
3508 return IDX_AFE_PORT_ID_INT5_MI2S_RX;
3509 case AFE_PORT_ID_INT5_MI2S_TX:
3510 return IDX_AFE_PORT_ID_INT5_MI2S_TX;
3511 case AFE_PORT_ID_INT6_MI2S_RX:
3512 return IDX_AFE_PORT_ID_INT6_MI2S_RX;
3513 case AFE_PORT_ID_INT6_MI2S_TX:
3514 return IDX_AFE_PORT_ID_INT6_MI2S_TX;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003515 default:
3516 pr_err("%s: port 0x%x\n", __func__, port_id);
3517 return -EINVAL;
3518 }
3519}
3520
3521int afe_open(u16 port_id,
3522 union afe_port_config *afe_config, int rate)
3523{
3524 struct afe_port_cmd_device_start start;
3525 struct afe_audioif_config_command config;
3526 int ret = 0;
3527 int cfg_type;
3528 int index = 0;
3529
3530 if (!afe_config) {
3531 pr_err("%s: Error, no configuration data\n", __func__);
3532 ret = -EINVAL;
3533 return ret;
3534 }
3535
3536 pr_err("%s: port_id 0x%x rate %d\n", __func__, port_id, rate);
3537
3538 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08003539 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003540 pr_err("%s: AFE port index[%d] invalid!\n",
3541 __func__, index);
3542 return -EINVAL;
3543 }
3544 ret = q6audio_validate_port(port_id);
3545 if (ret < 0) {
3546 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
3547 return -EINVAL;
3548 }
3549
3550 if ((port_id == RT_PROXY_DAI_001_RX) ||
3551 (port_id == RT_PROXY_DAI_002_TX)) {
3552 pr_err("%s: wrong port 0x%x\n", __func__, port_id);
3553 return -EINVAL;
3554 }
3555 if ((port_id == RT_PROXY_DAI_002_RX) ||
3556 (port_id == RT_PROXY_DAI_001_TX))
3557 port_id = VIRTUAL_ID_TO_PORTID(port_id);
3558
3559 ret = afe_q6_interface_prepare();
3560 if (ret != 0) {
3561 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3562 return -EINVAL;
3563 }
Siena Richard23364c92017-01-11 16:20:55 -08003564
3565 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
3566 this_afe.afe_sample_rates[index] = rate;
3567
3568 if (this_afe.rt_cb)
3569 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
3570 }
3571
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003572 /* Also send the topology id here: */
3573 afe_send_custom_topology(); /* One time call: only for first time */
3574 afe_send_port_topology_id(port_id);
3575
3576 ret = q6audio_validate_port(port_id);
3577 if (ret < 0) {
3578 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
3579 __func__, port_id, ret);
3580 return -EINVAL;
3581 }
3582 mutex_lock(&this_afe.afe_cmd_lock);
3583
3584 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3585 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3586 config.hdr.pkt_size = sizeof(config);
3587 config.hdr.src_port = 0;
3588 config.hdr.dest_port = 0;
3589 config.hdr.token = index;
3590 switch (port_id) {
3591 case PRIMARY_I2S_RX:
3592 case PRIMARY_I2S_TX:
3593 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
3594 break;
3595 case AFE_PORT_ID_PRIMARY_PCM_RX:
3596 case AFE_PORT_ID_PRIMARY_PCM_TX:
3597 case AFE_PORT_ID_SECONDARY_PCM_RX:
3598 case AFE_PORT_ID_SECONDARY_PCM_TX:
3599 case AFE_PORT_ID_TERTIARY_PCM_RX:
3600 case AFE_PORT_ID_TERTIARY_PCM_TX:
3601 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3602 case AFE_PORT_ID_QUATERNARY_PCM_TX:
3603 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
3604 break;
3605 case SECONDARY_I2S_RX:
3606 case SECONDARY_I2S_TX:
3607 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3608 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3609 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3610 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3611 case MI2S_RX:
3612 case MI2S_TX:
3613 case AFE_PORT_ID_QUINARY_MI2S_RX:
3614 case AFE_PORT_ID_QUINARY_MI2S_TX:
3615 case AFE_PORT_ID_SENARY_MI2S_TX:
3616 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
3617 break;
3618 case HDMI_RX:
3619 case DISPLAY_PORT_RX:
3620 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
3621 break;
3622 case SLIMBUS_0_RX:
3623 case SLIMBUS_0_TX:
3624 case SLIMBUS_1_RX:
3625 case SLIMBUS_1_TX:
3626 case SLIMBUS_2_RX:
3627 case SLIMBUS_2_TX:
3628 case SLIMBUS_3_RX:
3629 case SLIMBUS_3_TX:
3630 case SLIMBUS_4_RX:
3631 case SLIMBUS_4_TX:
3632 case SLIMBUS_5_RX:
3633 case SLIMBUS_6_RX:
3634 case SLIMBUS_6_TX:
3635 case SLIMBUS_7_RX:
3636 case SLIMBUS_7_TX:
3637 case SLIMBUS_8_RX:
3638 case SLIMBUS_8_TX:
3639 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
3640 break;
3641 case AFE_PORT_ID_USB_RX:
3642 case AFE_PORT_ID_USB_TX:
3643 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
3644 break;
3645 default:
3646 pr_err("%s: Invalid port id 0x%x\n",
3647 __func__, port_id);
3648 ret = -EINVAL;
3649 goto fail_cmd;
3650 }
3651 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3652 config.param.port_id = q6audio_get_port_id(port_id);
3653 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr)
3654 - sizeof(config.param);
3655 config.param.payload_address_lsw = 0x00;
3656 config.param.payload_address_msw = 0x00;
3657 config.param.mem_map_handle = 0x00;
3658 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3659 config.pdata.param_id = cfg_type;
3660 config.pdata.param_size = sizeof(config.port);
3661
3662 config.port = *afe_config;
3663 pr_debug("%s: param PL size=%d iparam_size[%d][%zd %zd %zd %zd] param_id[0x%x]\n",
3664 __func__, config.param.payload_size, config.pdata.param_size,
3665 sizeof(config), sizeof(config.param), sizeof(config.port),
3666 sizeof(struct apr_hdr), config.pdata.param_id);
3667
3668 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3669 if (ret) {
3670 pr_err("%s: AFE enable for port 0x%x opcode[0x%x]failed %d\n",
3671 __func__, port_id, cfg_type, ret);
3672 goto fail_cmd;
3673 }
3674 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3675 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3676 start.hdr.pkt_size = sizeof(start);
3677 start.hdr.src_port = 0;
3678 start.hdr.dest_port = 0;
3679 start.hdr.token = index;
3680 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
3681 start.port_id = q6audio_get_port_id(port_id);
3682 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
3683 __func__, start.hdr.opcode, start.port_id);
3684
3685 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
3686 if (ret) {
3687 pr_err("%s: AFE enable for port 0x%x failed %d\n", __func__,
3688 port_id, ret);
3689 goto fail_cmd;
3690 }
3691
3692fail_cmd:
3693 mutex_unlock(&this_afe.afe_cmd_lock);
3694 return ret;
3695}
3696
3697int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
3698{
3699 struct afe_loopback_cfg_v1 lb_cmd;
3700 int ret = 0;
3701 int index = 0;
3702
3703 if (rx_port == MI2S_RX)
3704 rx_port = AFE_PORT_ID_PRIMARY_MI2S_RX;
3705 if (tx_port == MI2S_TX)
3706 tx_port = AFE_PORT_ID_PRIMARY_MI2S_TX;
3707
3708 ret = afe_q6_interface_prepare();
3709 if (ret != 0) {
3710 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3711 return ret;
3712 }
3713
3714 index = q6audio_get_port_index(rx_port);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08003715 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003716 pr_err("%s: AFE port index[%d] invalid!\n",
3717 __func__, index);
3718 return -EINVAL;
3719 }
3720 ret = q6audio_validate_port(rx_port);
3721 if (ret < 0) {
3722 pr_err("%s: Invalid port 0x%x ret %d", __func__, rx_port, ret);
3723 return -EINVAL;
3724 }
3725
3726 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3727 APR_HDR_LEN(20), APR_PKT_VER);
3728 lb_cmd.hdr.pkt_size = sizeof(lb_cmd);
3729 lb_cmd.hdr.src_port = 0;
3730 lb_cmd.hdr.dest_port = 0;
3731 lb_cmd.hdr.token = index;
3732 lb_cmd.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3733 lb_cmd.param.port_id = tx_port;
3734 lb_cmd.param.payload_size = (sizeof(lb_cmd) - sizeof(struct apr_hdr) -
3735 sizeof(struct afe_port_cmd_set_param_v2));
3736 lb_cmd.param.payload_address_lsw = 0x00;
3737 lb_cmd.param.payload_address_msw = 0x00;
3738 lb_cmd.param.mem_map_handle = 0x00;
3739 lb_cmd.pdata.module_id = AFE_MODULE_LOOPBACK;
3740 lb_cmd.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
3741 lb_cmd.pdata.param_size = lb_cmd.param.payload_size -
3742 sizeof(struct afe_port_param_data_v2);
3743
3744 lb_cmd.dst_port_id = rx_port;
3745 lb_cmd.routing_mode = LB_MODE_DEFAULT;
3746 lb_cmd.enable = (enable ? 1 : 0);
3747 lb_cmd.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
3748
3749 ret = afe_apr_send_pkt(&lb_cmd, &this_afe.wait[index]);
3750 if (ret)
3751 pr_err("%s: AFE loopback failed %d\n", __func__, ret);
3752 return ret;
3753}
3754
3755int afe_loopback_gain(u16 port_id, u16 volume)
3756{
3757 struct afe_loopback_gain_per_path_param set_param;
3758 int ret = 0;
3759 int index = 0;
3760
3761 if (this_afe.apr == NULL) {
3762 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
3763 0xFFFFFFFF, &this_afe);
3764 pr_debug("%s: Register AFE\n", __func__);
3765 if (this_afe.apr == NULL) {
3766 pr_err("%s: Unable to register AFE\n", __func__);
3767 ret = -ENODEV;
3768 return ret;
3769 }
3770 rtac_set_afe_handle(this_afe.apr);
3771 }
3772
3773 ret = q6audio_validate_port(port_id);
3774 if (ret < 0) {
3775 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
3776 __func__, port_id, ret);
3777 ret = -EINVAL;
3778 goto fail_cmd;
3779 }
3780 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08003781 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003782 pr_err("%s: AFE port index[%d] invalid!\n",
3783 __func__, index);
3784 return -EINVAL;
3785 }
3786 ret = q6audio_validate_port(port_id);
3787 if (ret < 0) {
3788 pr_err("%s: Invalid port 0x%x ret %d",
3789 __func__, port_id, ret);
3790 return -EINVAL;
3791 }
3792
3793 /* RX ports numbers are even .TX ports numbers are odd. */
3794 if (port_id % 2 == 0) {
3795 pr_err("%s: Failed : afe loopback gain only for TX ports. port_id %d\n",
3796 __func__, port_id);
3797 ret = -EINVAL;
3798 goto fail_cmd;
3799 }
3800
3801 pr_debug("%s: port 0x%x volume %d\n", __func__, port_id, volume);
3802
3803 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3804 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3805 set_param.hdr.pkt_size = sizeof(set_param);
3806 set_param.hdr.src_port = 0;
3807 set_param.hdr.dest_port = 0;
3808 set_param.hdr.token = index;
3809 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3810
3811 set_param.param.port_id = port_id;
3812 set_param.param.payload_size =
3813 (sizeof(struct afe_loopback_gain_per_path_param) -
3814 sizeof(struct apr_hdr) - sizeof(struct afe_port_cmd_set_param_v2));
3815 set_param.param.payload_address_lsw = 0;
3816 set_param.param.payload_address_msw = 0;
3817 set_param.param.mem_map_handle = 0;
3818
3819 set_param.pdata.module_id = AFE_MODULE_LOOPBACK;
3820 set_param.pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
3821 set_param.pdata.param_size =
3822 (set_param.param.payload_size -
3823 sizeof(struct afe_port_param_data_v2));
3824 set_param.rx_port_id = port_id;
3825 set_param.gain = volume;
3826
3827 ret = afe_apr_send_pkt(&set_param, &this_afe.wait[index]);
3828 if (ret) {
3829 pr_err("%s: AFE param set failed for port 0x%x ret %d\n",
3830 __func__, port_id, ret);
3831 goto fail_cmd;
3832 }
3833
3834fail_cmd:
3835 return ret;
3836}
3837
3838int afe_pseudo_port_start_nowait(u16 port_id)
3839{
3840 struct afe_pseudoport_start_command start;
3841 int ret = 0;
3842
3843 pr_debug("%s: port_id=0x%x\n", __func__, port_id);
3844 if (this_afe.apr == NULL) {
3845 pr_err("%s: AFE APR is not registered\n", __func__);
3846 return -ENODEV;
3847 }
3848
3849
3850 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3851 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3852 start.hdr.pkt_size = sizeof(start);
3853 start.hdr.src_port = 0;
3854 start.hdr.dest_port = 0;
3855 start.hdr.token = 0;
3856 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
3857 start.port_id = port_id;
3858 start.timing = 1;
3859
3860 ret = afe_apr_send_pkt(&start, NULL);
3861 if (ret) {
3862 pr_err("%s: AFE enable for port 0x%x failed %d\n",
3863 __func__, port_id, ret);
3864 return ret;
3865 }
3866 return 0;
3867}
3868
3869int afe_start_pseudo_port(u16 port_id)
3870{
3871 int ret = 0;
3872 struct afe_pseudoport_start_command start;
3873 int index = 0;
3874
3875 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
3876
3877 ret = afe_q6_interface_prepare();
3878 if (ret != 0) {
3879 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3880 return ret;
3881 }
3882
3883 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08003884 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003885 pr_err("%s: AFE port index[%d] invalid!\n",
3886 __func__, index);
3887 return -EINVAL;
3888 }
3889 ret = q6audio_validate_port(port_id);
3890 if (ret < 0) {
3891 pr_err("%s: Invalid port 0x%x ret %d",
3892 __func__, port_id, ret);
3893 return -EINVAL;
3894 }
3895
3896 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3897 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3898 start.hdr.pkt_size = sizeof(start);
3899 start.hdr.src_port = 0;
3900 start.hdr.dest_port = 0;
3901 start.hdr.token = 0;
3902 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
3903 start.port_id = port_id;
3904 start.timing = 1;
3905 start.hdr.token = index;
3906
3907 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
3908 if (ret)
3909 pr_err("%s: AFE enable for port 0x%x failed %d\n",
3910 __func__, port_id, ret);
3911 return ret;
3912}
3913
3914int afe_pseudo_port_stop_nowait(u16 port_id)
3915{
3916 int ret = 0;
3917 struct afe_pseudoport_stop_command stop;
3918 int index = 0;
3919
3920 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
3921
3922 if (this_afe.apr == NULL) {
3923 pr_err("%s: AFE is already closed\n", __func__);
3924 return -EINVAL;
3925 }
3926 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08003927 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003928 pr_err("%s: AFE port index[%d] invalid!\n",
3929 __func__, index);
3930 return -EINVAL;
3931 }
3932 ret = q6audio_validate_port(port_id);
3933 if (ret < 0) {
3934 pr_err("%s: Invalid port 0x%x ret %d",
3935 __func__, port_id, ret);
3936 return -EINVAL;
3937 }
3938
3939 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3940 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3941 stop.hdr.pkt_size = sizeof(stop);
3942 stop.hdr.src_port = 0;
3943 stop.hdr.dest_port = 0;
3944 stop.hdr.token = 0;
3945 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
3946 stop.port_id = port_id;
3947 stop.reserved = 0;
3948 stop.hdr.token = index;
3949
3950 ret = afe_apr_send_pkt(&stop, NULL);
3951 if (ret)
3952 pr_err("%s: AFE close failed %d\n", __func__, ret);
3953
3954 return ret;
3955}
3956
3957int afe_port_group_set_param(u16 group_id,
3958 union afe_port_group_config *afe_group_config)
3959{
3960 int ret;
3961 struct afe_port_group_create config;
3962 int cfg_type;
3963
3964 if (!afe_group_config) {
3965 pr_err("%s: Error, no configuration data\n", __func__);
3966 return -EINVAL;
3967 }
3968
3969 pr_debug("%s: group id: 0x%x\n", __func__, group_id);
3970
3971 ret = afe_q6_interface_prepare();
3972 if (ret != 0) {
3973 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3974 return ret;
3975 }
3976
3977 switch (group_id) {
3978 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX:
3979 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX:
3980 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_RX:
3981 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_TX:
3982 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_RX:
3983 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_TX:
3984 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_RX:
3985 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_TX:
3986 cfg_type = AFE_PARAM_ID_GROUP_DEVICE_TDM_CONFIG;
3987 break;
3988 default:
3989 pr_err("%s: Invalid group id 0x%x\n", __func__, group_id);
3990 return -EINVAL;
3991 }
3992
3993 memset(&config, 0, sizeof(config));
3994 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3995 APR_HDR_LEN(APR_HDR_SIZE),
3996 APR_PKT_VER);
3997 config.hdr.pkt_size = sizeof(config);
3998 config.hdr.src_port = 0;
3999 config.hdr.dest_port = 0;
4000 config.hdr.token = IDX_GLOBAL_CFG;
4001 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
4002
4003 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
4004 sizeof(config.param);
4005 config.param.payload_address_lsw = 0x00;
4006 config.param.payload_address_msw = 0x00;
4007 config.param.mem_map_handle = 0x00;
4008 config.pdata.module_id = AFE_MODULE_GROUP_DEVICE;
4009 config.pdata.param_id = cfg_type;
4010 config.pdata.param_size = sizeof(config.data);
4011 config.data = *afe_group_config;
4012
4013 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
4014 if (ret)
4015 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_CFG failed %d\n",
4016 __func__, ret);
4017
4018 return ret;
4019}
4020
4021int afe_port_group_enable(u16 group_id,
4022 union afe_port_group_config *afe_group_config,
4023 u16 enable)
4024{
4025 int ret;
4026 struct afe_port_group_create config;
4027
4028 pr_debug("%s: group id: 0x%x enable: %d\n", __func__,
4029 group_id, enable);
4030
4031 ret = afe_q6_interface_prepare();
4032 if (ret != 0) {
4033 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4034 return ret;
4035 }
4036
4037 if (enable) {
4038 ret = afe_port_group_set_param(group_id, afe_group_config);
4039 if (ret < 0) {
4040 pr_err("%s: afe send failed %d\n", __func__, ret);
4041 return ret;
4042 }
4043 }
4044
4045 memset(&config, 0, sizeof(config));
4046 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4047 APR_HDR_LEN(APR_HDR_SIZE),
4048 APR_PKT_VER);
4049 config.hdr.pkt_size = sizeof(config);
4050 config.hdr.src_port = 0;
4051 config.hdr.dest_port = 0;
4052 config.hdr.token = IDX_GLOBAL_CFG;
4053 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
4054
4055 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
4056 sizeof(config.param);
4057 config.param.payload_address_lsw = 0x00;
4058 config.param.payload_address_msw = 0x00;
4059 config.param.mem_map_handle = 0x00;
4060 config.pdata.module_id = AFE_MODULE_GROUP_DEVICE;
4061 config.pdata.param_id = AFE_PARAM_ID_GROUP_DEVICE_ENABLE;
4062 config.pdata.param_size = sizeof(config.data);
4063 config.data.group_enable.group_id = group_id;
4064 config.data.group_enable.enable = enable;
4065
4066 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
4067 if (ret)
4068 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_ENABLE failed %d\n",
4069 __func__, ret);
4070
4071 return ret;
4072}
4073
4074int afe_stop_pseudo_port(u16 port_id)
4075{
4076 int ret = 0;
4077 struct afe_pseudoport_stop_command stop;
4078 int index = 0;
4079
4080 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4081
4082 if (this_afe.apr == NULL) {
4083 pr_err("%s: AFE is already closed\n", __func__);
4084 return -EINVAL;
4085 }
4086
4087 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08004088 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08004089 pr_err("%s: AFE port index[%d] invalid!\n",
4090 __func__, index);
4091 return -EINVAL;
4092 }
4093 ret = q6audio_validate_port(port_id);
4094 if (ret < 0) {
4095 pr_err("%s: Invalid port 0x%x ret %d\n",
4096 __func__, port_id, ret);
4097 return -EINVAL;
4098 }
4099
4100 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4101 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4102 stop.hdr.pkt_size = sizeof(stop);
4103 stop.hdr.src_port = 0;
4104 stop.hdr.dest_port = 0;
4105 stop.hdr.token = 0;
4106 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
4107 stop.port_id = port_id;
4108 stop.reserved = 0;
4109 stop.hdr.token = index;
4110
4111 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
4112 if (ret)
4113 pr_err("%s: AFE close failed %d\n", __func__, ret);
4114
4115 return ret;
4116}
4117
4118uint32_t afe_req_mmap_handle(struct afe_audio_client *ac)
4119{
4120 return ac->mem_map_handle;
4121}
4122
4123struct afe_audio_client *q6afe_audio_client_alloc(void *priv)
4124{
4125 struct afe_audio_client *ac;
4126 int lcnt = 0;
4127
4128 ac = kzalloc(sizeof(struct afe_audio_client), GFP_KERNEL);
4129 if (!ac)
4130 return NULL;
4131
4132 ac->priv = priv;
4133
4134 init_waitqueue_head(&ac->cmd_wait);
4135 INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
4136 INIT_LIST_HEAD(&ac->port[1].mem_map_handle);
4137 pr_debug("%s: mem_map_handle list init'ed\n", __func__);
4138 mutex_init(&ac->cmd_lock);
4139 for (lcnt = 0; lcnt <= OUT; lcnt++) {
4140 mutex_init(&ac->port[lcnt].lock);
4141 spin_lock_init(&ac->port[lcnt].dsp_lock);
4142 }
4143 atomic_set(&ac->cmd_state, 0);
4144
4145 return ac;
4146}
4147
4148int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir,
4149 struct afe_audio_client *ac,
4150 unsigned int bufsz,
4151 unsigned int bufcnt)
4152{
4153 int cnt = 0;
4154 int rc = 0;
4155 struct afe_audio_buffer *buf;
4156 size_t len;
4157
4158 if (!(ac) || ((dir != IN) && (dir != OUT))) {
4159 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
4160 return -EINVAL;
4161 }
4162
4163 pr_debug("%s: bufsz[%d]bufcnt[%d]\n",
4164 __func__,
4165 bufsz, bufcnt);
4166
4167 if (ac->port[dir].buf) {
4168 pr_debug("%s: buffer already allocated\n", __func__);
4169 return 0;
4170 }
4171 mutex_lock(&ac->cmd_lock);
4172 buf = kzalloc(((sizeof(struct afe_audio_buffer))*bufcnt),
4173 GFP_KERNEL);
4174
4175 if (!buf) {
4176 pr_err("%s: null buf\n", __func__);
4177 mutex_unlock(&ac->cmd_lock);
4178 goto fail;
4179 }
4180
4181 ac->port[dir].buf = buf;
4182
4183 rc = msm_audio_ion_alloc("afe_client", &buf[0].client,
4184 &buf[0].handle, bufsz*bufcnt,
4185 &buf[0].phys, &len,
4186 &buf[0].data);
4187 if (rc) {
4188 pr_err("%s: audio ION alloc failed, rc = %d\n",
4189 __func__, rc);
4190 mutex_unlock(&ac->cmd_lock);
4191 goto fail;
4192 }
4193
4194 buf[0].used = dir ^ 1;
4195 buf[0].size = bufsz;
4196 buf[0].actual_size = bufsz;
4197 cnt = 1;
4198 while (cnt < bufcnt) {
4199 if (bufsz > 0) {
4200 buf[cnt].data = buf[0].data + (cnt * bufsz);
4201 buf[cnt].phys = buf[0].phys + (cnt * bufsz);
4202 if (!buf[cnt].data) {
4203 pr_err("%s: Buf alloc failed\n",
4204 __func__);
4205 mutex_unlock(&ac->cmd_lock);
4206 goto fail;
4207 }
4208 buf[cnt].used = dir ^ 1;
4209 buf[cnt].size = bufsz;
4210 buf[cnt].actual_size = bufsz;
4211 pr_debug("%s: data[%pK]phys[%pK][%pK]\n", __func__,
4212 buf[cnt].data,
4213 &buf[cnt].phys,
4214 &buf[cnt].phys);
4215 }
4216 cnt++;
4217 }
4218 ac->port[dir].max_buf_cnt = cnt;
4219 mutex_unlock(&ac->cmd_lock);
4220 return 0;
4221fail:
4222 pr_err("%s: jump fail\n", __func__);
4223 q6afe_audio_client_buf_free_contiguous(dir, ac);
4224 return -EINVAL;
4225}
4226
4227int afe_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz,
4228 struct afe_audio_client *ac)
4229{
4230 int ret = 0;
4231
4232 mutex_lock(&this_afe.afe_cmd_lock);
4233 ac->mem_map_handle = 0;
4234 ret = afe_cmd_memory_map(dma_addr_p, dma_buf_sz);
4235 if (ret < 0) {
4236 pr_err("%s: afe_cmd_memory_map failed %d\n",
4237 __func__, ret);
4238
4239 mutex_unlock(&this_afe.afe_cmd_lock);
4240 return ret;
4241 }
4242 ac->mem_map_handle = this_afe.mmap_handle;
4243 mutex_unlock(&this_afe.afe_cmd_lock);
4244
4245 return ret;
4246}
4247
4248int afe_cmd_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz)
4249{
4250 int ret = 0;
4251 int cmd_size = 0;
4252 void *payload = NULL;
4253 void *mmap_region_cmd = NULL;
4254 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
4255 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
4256 int index = 0;
4257
4258 pr_debug("%s:\n", __func__);
4259
4260 if (this_afe.apr == NULL) {
4261 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4262 0xFFFFFFFF, &this_afe);
4263 pr_debug("%s: Register AFE\n", __func__);
4264 if (this_afe.apr == NULL) {
4265 pr_err("%s: Unable to register AFE\n", __func__);
4266 ret = -ENODEV;
4267 return ret;
4268 }
4269 rtac_set_afe_handle(this_afe.apr);
4270 }
4271 if (dma_buf_sz % SZ_4K != 0) {
4272 /*
4273 * The memory allocated by msm_audio_ion_alloc is always 4kB
4274 * aligned, ADSP expects the size to be 4kB aligned as well
4275 * so re-adjusts the buffer size before passing to ADSP.
4276 */
4277 dma_buf_sz = PAGE_ALIGN(dma_buf_sz);
4278 }
4279
4280 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
4281 + sizeof(struct afe_service_shared_map_region_payload);
4282
4283 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
4284 if (!mmap_region_cmd)
4285 return -ENOMEM;
4286
4287 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
4288 mmap_region_cmd;
4289 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4290 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4291 mregion->hdr.pkt_size = cmd_size;
4292 mregion->hdr.src_port = 0;
4293 mregion->hdr.dest_port = 0;
4294 mregion->hdr.token = 0;
4295 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
4296 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
4297 mregion->num_regions = 1;
4298 mregion->property_flag = 0x00;
4299 /* Todo */
4300 index = mregion->hdr.token = IDX_RSVD_2;
4301
4302 payload = ((u8 *) mmap_region_cmd +
4303 sizeof(struct afe_service_cmd_shared_mem_map_regions));
4304
4305 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
4306
4307 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
4308 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
4309 mregion_pl->mem_size_bytes = dma_buf_sz;
4310
4311 pr_debug("%s: dma_addr_p 0x%pK , size %d\n", __func__,
4312 &dma_addr_p, dma_buf_sz);
4313 atomic_set(&this_afe.state, 1);
4314 atomic_set(&this_afe.status, 0);
4315 this_afe.mmap_handle = 0;
4316 ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
4317 if (ret < 0) {
4318 pr_err("%s: AFE memory map cmd failed %d\n",
4319 __func__, ret);
4320 ret = -EINVAL;
4321 goto fail_cmd;
4322 }
4323
4324 ret = wait_event_timeout(this_afe.wait[index],
4325 (atomic_read(&this_afe.state) == 0),
4326 msecs_to_jiffies(TIMEOUT_MS));
4327 if (!ret) {
4328 pr_err("%s: wait_event timeout\n", __func__);
4329 ret = -EINVAL;
4330 goto fail_cmd;
4331 }
4332 if (atomic_read(&this_afe.status) > 0) {
4333 pr_err("%s: config cmd failed [%s]\n",
4334 __func__, adsp_err_get_err_str(
4335 atomic_read(&this_afe.status)));
4336 ret = adsp_err_get_lnx_err_code(
4337 atomic_read(&this_afe.status));
4338 goto fail_cmd;
4339 }
4340
4341 kfree(mmap_region_cmd);
4342 return 0;
4343fail_cmd:
4344 kfree(mmap_region_cmd);
4345 pr_err("%s: fail_cmd\n", __func__);
4346 return ret;
4347}
4348
4349int afe_cmd_memory_map_nowait(int port_id, phys_addr_t dma_addr_p,
4350 u32 dma_buf_sz)
4351{
4352 int ret = 0;
4353 int cmd_size = 0;
4354 void *payload = NULL;
4355 void *mmap_region_cmd = NULL;
4356 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
4357 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
4358 int index = 0;
4359
4360 pr_debug("%s:\n", __func__);
4361
4362 if (this_afe.apr == NULL) {
4363 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4364 0xFFFFFFFF, &this_afe);
4365 pr_debug("%s: Register AFE\n", __func__);
4366 if (this_afe.apr == NULL) {
4367 pr_err("%s: Unable to register AFE\n", __func__);
4368 ret = -ENODEV;
4369 return ret;
4370 }
4371 rtac_set_afe_handle(this_afe.apr);
4372 }
4373 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08004374 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08004375 pr_err("%s: AFE port index[%d] invalid!\n",
4376 __func__, index);
4377 return -EINVAL;
4378 }
4379 ret = q6audio_validate_port(port_id);
4380 if (ret < 0) {
4381 pr_err("%s: Invalid port 0x%x ret %d",
4382 __func__, port_id, ret);
4383 return -EINVAL;
4384 }
4385
4386 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
4387 + sizeof(struct afe_service_shared_map_region_payload);
4388
4389 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
4390 if (!mmap_region_cmd)
4391 return -ENOMEM;
4392
4393 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
4394 mmap_region_cmd;
4395 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4396 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4397 mregion->hdr.pkt_size = sizeof(mregion);
4398 mregion->hdr.src_port = 0;
4399 mregion->hdr.dest_port = 0;
4400 mregion->hdr.token = 0;
4401 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
4402 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
4403 mregion->num_regions = 1;
4404 mregion->property_flag = 0x00;
4405
4406 payload = ((u8 *) mmap_region_cmd +
4407 sizeof(struct afe_service_cmd_shared_mem_map_regions));
4408 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
4409
4410 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
4411 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
4412 mregion_pl->mem_size_bytes = dma_buf_sz;
4413
4414 ret = afe_apr_send_pkt(mmap_region_cmd, NULL);
4415 if (ret)
4416 pr_err("%s: AFE memory map cmd failed %d\n",
4417 __func__, ret);
4418 kfree(mmap_region_cmd);
4419 return ret;
4420}
4421int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
4422 struct afe_audio_client *ac)
4423{
4424 struct afe_audio_port_data *port;
4425 int cnt = 0;
4426
4427 mutex_lock(&ac->cmd_lock);
4428 port = &ac->port[dir];
4429 if (!port->buf) {
4430 pr_err("%s: buf is null\n", __func__);
4431 mutex_unlock(&ac->cmd_lock);
4432 return 0;
4433 }
4434 cnt = port->max_buf_cnt - 1;
4435
4436 if (port->buf[0].data) {
4437 pr_debug("%s: data[%pK]phys[%pK][%pK] , client[%pK] handle[%pK]\n",
4438 __func__,
4439 port->buf[0].data,
4440 &port->buf[0].phys,
4441 &port->buf[0].phys,
4442 port->buf[0].client,
4443 port->buf[0].handle);
4444 msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
4445 port->buf[0].client = NULL;
4446 port->buf[0].handle = NULL;
4447 }
4448
4449 while (cnt >= 0) {
4450 port->buf[cnt].data = NULL;
4451 port->buf[cnt].phys = 0;
4452 cnt--;
4453 }
4454 port->max_buf_cnt = 0;
4455 kfree(port->buf);
4456 port->buf = NULL;
4457 mutex_unlock(&ac->cmd_lock);
4458 return 0;
4459}
4460
4461void q6afe_audio_client_free(struct afe_audio_client *ac)
4462{
4463 int loopcnt;
4464 struct afe_audio_port_data *port;
4465
4466 if (!ac) {
4467 pr_err("%s: audio client is NULL\n", __func__);
4468 return;
4469 }
4470 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
4471 port = &ac->port[loopcnt];
4472 if (!port->buf)
4473 continue;
4474 pr_debug("%s: loopcnt = %d\n", __func__, loopcnt);
4475 q6afe_audio_client_buf_free_contiguous(loopcnt, ac);
4476 }
4477 kfree(ac);
4478}
4479
4480int afe_cmd_memory_unmap(u32 mem_map_handle)
4481{
4482 int ret = 0;
4483 struct afe_service_cmd_shared_mem_unmap_regions mregion;
4484 int index = 0;
4485
4486 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
4487
4488 if (this_afe.apr == NULL) {
4489 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4490 0xFFFFFFFF, &this_afe);
4491 pr_debug("%s: Register AFE\n", __func__);
4492 if (this_afe.apr == NULL) {
4493 pr_err("%s: Unable to register AFE\n", __func__);
4494 ret = -ENODEV;
4495 return ret;
4496 }
4497 rtac_set_afe_handle(this_afe.apr);
4498 }
4499
4500 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4501 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4502 mregion.hdr.pkt_size = sizeof(mregion);
4503 mregion.hdr.src_port = 0;
4504 mregion.hdr.dest_port = 0;
4505 mregion.hdr.token = 0;
4506 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
4507 mregion.mem_map_handle = mem_map_handle;
4508
4509 /* Todo */
4510 index = mregion.hdr.token = IDX_RSVD_2;
4511
4512 atomic_set(&this_afe.status, 0);
4513 ret = afe_apr_send_pkt(&mregion, &this_afe.wait[index]);
4514 if (ret)
4515 pr_err("%s: AFE memory unmap cmd failed %d\n",
4516 __func__, ret);
4517
4518 return ret;
4519}
4520
4521int afe_cmd_memory_unmap_nowait(u32 mem_map_handle)
4522{
4523 int ret = 0;
4524 struct afe_service_cmd_shared_mem_unmap_regions mregion;
4525
4526 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
4527
4528 if (this_afe.apr == NULL) {
4529 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4530 0xFFFFFFFF, &this_afe);
4531 pr_debug("%s: Register AFE\n", __func__);
4532 if (this_afe.apr == NULL) {
4533 pr_err("%s: Unable to register AFE\n", __func__);
4534 ret = -ENODEV;
4535 return ret;
4536 }
4537 rtac_set_afe_handle(this_afe.apr);
4538 }
4539
4540 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4541 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4542 mregion.hdr.pkt_size = sizeof(mregion);
4543 mregion.hdr.src_port = 0;
4544 mregion.hdr.dest_port = 0;
4545 mregion.hdr.token = 0;
4546 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
4547 mregion.mem_map_handle = mem_map_handle;
4548
4549 ret = afe_apr_send_pkt(&mregion, NULL);
4550 if (ret)
4551 pr_err("%s: AFE memory unmap cmd failed %d\n",
4552 __func__, ret);
4553 return ret;
4554}
4555
4556int afe_register_get_events(u16 port_id,
4557 void (*cb)(uint32_t opcode,
4558 uint32_t token, uint32_t *payload, void *priv),
4559 void *private_data)
4560{
4561 int ret = 0;
4562 struct afe_service_cmd_register_rt_port_driver rtproxy;
4563
4564 pr_debug("%s: port_id: 0x%x\n", __func__, port_id);
4565
4566 if (this_afe.apr == NULL) {
4567 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4568 0xFFFFFFFF, &this_afe);
4569 pr_debug("%s: Register AFE\n", __func__);
4570 if (this_afe.apr == NULL) {
4571 pr_err("%s: Unable to register AFE\n", __func__);
4572 ret = -ENODEV;
4573 return ret;
4574 }
4575 rtac_set_afe_handle(this_afe.apr);
4576 }
4577 if ((port_id == RT_PROXY_DAI_002_RX) ||
4578 (port_id == RT_PROXY_DAI_001_TX)) {
4579 port_id = VIRTUAL_ID_TO_PORTID(port_id);
4580 } else {
4581 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
4582 return -EINVAL;
4583 }
4584
4585 if (port_id == RT_PROXY_PORT_001_TX) {
4586 this_afe.tx_cb = cb;
4587 this_afe.tx_private_data = private_data;
4588 } else if (port_id == RT_PROXY_PORT_001_RX) {
4589 this_afe.rx_cb = cb;
4590 this_afe.rx_private_data = private_data;
4591 }
4592
4593 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4594 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4595 rtproxy.hdr.pkt_size = sizeof(rtproxy);
4596 rtproxy.hdr.src_port = 1;
4597 rtproxy.hdr.dest_port = 1;
4598 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER;
4599 rtproxy.port_id = port_id;
4600 rtproxy.reserved = 0;
4601
4602 ret = afe_apr_send_pkt(&rtproxy, NULL);
4603 if (ret)
4604 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
4605 __func__, ret);
4606 return ret;
4607}
4608
4609int afe_unregister_get_events(u16 port_id)
4610{
4611 int ret = 0;
4612 struct afe_service_cmd_unregister_rt_port_driver rtproxy;
4613 int index = 0;
4614
4615 pr_debug("%s:\n", __func__);
4616
4617 if (this_afe.apr == NULL) {
4618 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4619 0xFFFFFFFF, &this_afe);
4620 pr_debug("%s: Register AFE\n", __func__);
4621 if (this_afe.apr == NULL) {
4622 pr_err("%s: Unable to register AFE\n", __func__);
4623 ret = -ENODEV;
4624 return ret;
4625 }
4626 rtac_set_afe_handle(this_afe.apr);
4627 }
4628
4629 if ((port_id == RT_PROXY_DAI_002_RX) ||
4630 (port_id == RT_PROXY_DAI_001_TX)) {
4631 port_id = VIRTUAL_ID_TO_PORTID(port_id);
4632 } else {
4633 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
4634 return -EINVAL;
4635 }
4636
4637 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08004638 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08004639 pr_err("%s: AFE port index[%d] invalid!\n",
4640 __func__, index);
4641 return -EINVAL;
4642 }
4643 ret = q6audio_validate_port(port_id);
4644 if (ret < 0) {
4645 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
4646 return -EINVAL;
4647 }
4648
4649 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4650 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4651 rtproxy.hdr.pkt_size = sizeof(rtproxy);
4652 rtproxy.hdr.src_port = 0;
4653 rtproxy.hdr.dest_port = 0;
4654 rtproxy.hdr.token = 0;
4655 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER;
4656 rtproxy.port_id = port_id;
4657 rtproxy.reserved = 0;
4658
4659 rtproxy.hdr.token = index;
4660
4661 if (port_id == RT_PROXY_PORT_001_TX) {
4662 this_afe.tx_cb = NULL;
4663 this_afe.tx_private_data = NULL;
4664 } else if (port_id == RT_PROXY_PORT_001_RX) {
4665 this_afe.rx_cb = NULL;
4666 this_afe.rx_private_data = NULL;
4667 }
4668
4669 ret = afe_apr_send_pkt(&rtproxy, &this_afe.wait[index]);
4670 if (ret)
4671 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
4672 __func__, ret);
4673 return ret;
4674}
4675
4676int afe_rt_proxy_port_write(phys_addr_t buf_addr_p,
4677 u32 mem_map_handle, int bytes)
4678{
4679 int ret = 0;
4680 struct afe_port_data_cmd_rt_proxy_port_write_v2 afecmd_wr;
4681
4682 if (this_afe.apr == NULL) {
4683 pr_err("%s: register to AFE is not done\n", __func__);
4684 ret = -ENODEV;
4685 return ret;
4686 }
4687 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
4688 &buf_addr_p, bytes);
4689
4690 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4691 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4692 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
4693 afecmd_wr.hdr.src_port = 0;
4694 afecmd_wr.hdr.dest_port = 0;
4695 afecmd_wr.hdr.token = 0;
4696 afecmd_wr.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2;
4697 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
4698 afecmd_wr.buffer_address_lsw = lower_32_bits(buf_addr_p);
4699 afecmd_wr.buffer_address_msw =
4700 msm_audio_populate_upper_32_bits(buf_addr_p);
4701 afecmd_wr.mem_map_handle = mem_map_handle;
4702 afecmd_wr.available_bytes = bytes;
4703 afecmd_wr.reserved = 0;
4704
4705 ret = afe_apr_send_pkt(&afecmd_wr, NULL);
4706 if (ret)
4707 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
4708 __func__, afecmd_wr.port_id, ret);
4709 return ret;
4710
4711}
4712
4713int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
4714 u32 mem_map_handle, int bytes)
4715{
4716 int ret = 0;
4717 struct afe_port_data_cmd_rt_proxy_port_read_v2 afecmd_rd;
4718
4719 if (this_afe.apr == NULL) {
4720 pr_err("%s: register to AFE is not done\n", __func__);
4721 ret = -ENODEV;
4722 return ret;
4723 }
4724 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
4725 &buf_addr_p, bytes);
4726
4727 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4728 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4729 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
4730 afecmd_rd.hdr.src_port = 0;
4731 afecmd_rd.hdr.dest_port = 0;
4732 afecmd_rd.hdr.token = 0;
4733 afecmd_rd.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2;
4734 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
4735 afecmd_rd.buffer_address_lsw = lower_32_bits(buf_addr_p);
4736 afecmd_rd.buffer_address_msw =
4737 msm_audio_populate_upper_32_bits(buf_addr_p);
4738 afecmd_rd.available_bytes = bytes;
4739 afecmd_rd.mem_map_handle = mem_map_handle;
4740
4741 ret = afe_apr_send_pkt(&afecmd_rd, NULL);
4742 if (ret)
4743 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
4744 __func__, afecmd_rd.port_id, ret);
4745 return ret;
4746}
4747
4748#ifdef CONFIG_DEBUG_FS
4749static struct dentry *debugfs_afelb;
4750static struct dentry *debugfs_afelb_gain;
4751
4752static int afe_debug_open(struct inode *inode, struct file *file)
4753{
4754 file->private_data = inode->i_private;
4755 pr_info("%s: debug intf %s\n", __func__, (char *) file->private_data);
4756 return 0;
4757}
4758
4759static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
4760{
4761 char *token;
4762 int base, cnt;
4763
4764 token = strsep(&buf, " ");
4765
4766 for (cnt = 0; cnt < num_of_par; cnt++) {
4767 if (token != NULL) {
4768 if ((token[1] == 'x') || (token[1] == 'X'))
4769 base = 16;
4770 else
4771 base = 10;
4772
4773 if (kstrtoul(token, base, &param1[cnt]) != 0) {
4774 pr_err("%s: kstrtoul failed\n",
4775 __func__);
4776 return -EINVAL;
4777 }
4778
4779 token = strsep(&buf, " ");
4780 } else {
4781 pr_err("%s: token NULL\n", __func__);
4782 return -EINVAL;
4783 }
4784 }
4785 return 0;
4786}
4787#define AFE_LOOPBACK_ON (1)
4788#define AFE_LOOPBACK_OFF (0)
4789static ssize_t afe_debug_write(struct file *filp,
4790 const char __user *ubuf, size_t cnt, loff_t *ppos)
4791{
4792 char *lb_str = filp->private_data;
4793 char lbuf[32];
4794 int rc;
4795 unsigned long param[5];
4796
4797 if (cnt > sizeof(lbuf) - 1) {
4798 pr_err("%s: cnt %zd size %zd\n", __func__, cnt, sizeof(lbuf)-1);
4799 return -EINVAL;
4800 }
4801
4802 rc = copy_from_user(lbuf, ubuf, cnt);
4803 if (rc) {
4804 pr_err("%s: copy from user failed %d\n", __func__, rc);
4805 return -EFAULT;
4806 }
4807
4808 lbuf[cnt] = '\0';
4809
4810 if (!strcmp(lb_str, "afe_loopback")) {
4811 rc = afe_get_parameters(lbuf, param, 3);
4812 if (!rc) {
4813 pr_info("%s: %lu %lu %lu\n", lb_str, param[0], param[1],
4814 param[2]);
4815
4816 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
4817 AFE_LOOPBACK_OFF)) {
4818 pr_err("%s: Error, parameter 0 incorrect\n",
4819 __func__);
4820 rc = -EINVAL;
4821 goto afe_error;
4822 }
4823 if ((q6audio_validate_port(param[1]) < 0) ||
4824 (q6audio_validate_port(param[2])) < 0) {
4825 pr_err("%s: Error, invalid afe port\n",
4826 __func__);
4827 }
4828 if (this_afe.apr == NULL) {
4829 pr_err("%s: Error, AFE not opened\n", __func__);
4830 rc = -EINVAL;
4831 } else {
4832 rc = afe_loopback(param[0], param[1], param[2]);
4833 }
4834 } else {
4835 pr_err("%s: Error, invalid parameters\n", __func__);
4836 rc = -EINVAL;
4837 }
4838
4839 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
4840 rc = afe_get_parameters(lbuf, param, 2);
4841 if (!rc) {
4842 pr_info("%s: %s %lu %lu\n",
4843 __func__, lb_str, param[0], param[1]);
4844
4845 rc = q6audio_validate_port(param[0]);
4846 if (rc < 0) {
4847 pr_err("%s: Error, invalid afe port %d %lu\n",
4848 __func__, rc, param[0]);
4849 rc = -EINVAL;
4850 goto afe_error;
4851 }
4852
4853 if (param[1] > 100) {
4854 pr_err("%s: Error, volume should be 0 to 100 percentage param = %lu\n",
4855 __func__, param[1]);
4856 rc = -EINVAL;
4857 goto afe_error;
4858 }
4859
4860 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
4861
4862 if (this_afe.apr == NULL) {
4863 pr_err("%s: Error, AFE not opened\n", __func__);
4864 rc = -EINVAL;
4865 } else {
4866 rc = afe_loopback_gain(param[0], param[1]);
4867 }
4868 } else {
4869 pr_err("%s: Error, invalid parameters\n", __func__);
4870 rc = -EINVAL;
4871 }
4872 }
4873
4874afe_error:
4875 if (rc == 0)
4876 rc = cnt;
4877 else
4878 pr_err("%s: rc = %d\n", __func__, rc);
4879
4880 return rc;
4881}
4882
4883static const struct file_operations afe_debug_fops = {
4884 .open = afe_debug_open,
4885 .write = afe_debug_write
4886};
4887
4888static void config_debug_fs_init(void)
4889{
4890 debugfs_afelb = debugfs_create_file("afe_loopback",
4891 0664, NULL, (void *) "afe_loopback",
4892 &afe_debug_fops);
4893
4894 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
4895 0664, NULL, (void *) "afe_loopback_gain",
4896 &afe_debug_fops);
4897}
4898static void config_debug_fs_exit(void)
4899{
4900 debugfs_remove(debugfs_afelb);
4901 debugfs_remove(debugfs_afelb_gain);
4902}
4903#else
4904static void config_debug_fs_init(void)
4905{
4906}
4907static void config_debug_fs_exit(void)
4908{
4909}
4910#endif
4911
4912void afe_set_dtmf_gen_rx_portid(u16 port_id, int set)
4913{
4914 if (set)
4915 this_afe.dtmf_gen_rx_portid = port_id;
4916 else if (this_afe.dtmf_gen_rx_portid == port_id)
4917 this_afe.dtmf_gen_rx_portid = -1;
4918}
4919
4920int afe_dtmf_generate_rx(int64_t duration_in_ms,
4921 uint16_t high_freq,
4922 uint16_t low_freq, uint16_t gain)
4923{
4924 int ret = 0;
4925 int index = 0;
4926 struct afe_dtmf_generation_command cmd_dtmf;
4927
4928 pr_debug("%s: DTMF AFE Gen\n", __func__);
4929
4930 if (afe_validate_port(this_afe.dtmf_gen_rx_portid) < 0) {
4931 pr_err("%s: Failed : Invalid Port id = 0x%x\n",
4932 __func__, this_afe.dtmf_gen_rx_portid);
4933 ret = -EINVAL;
4934 goto fail_cmd;
4935 }
4936
4937 if (this_afe.apr == NULL) {
4938 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4939 0xFFFFFFFF, &this_afe);
4940 pr_debug("%s: Register AFE\n", __func__);
4941 if (this_afe.apr == NULL) {
4942 pr_err("%s: Unable to register AFE\n", __func__);
4943 ret = -ENODEV;
4944 return ret;
4945 }
4946 rtac_set_afe_handle(this_afe.apr);
4947 }
4948
4949 pr_debug("%s: dur=%lld: hfreq=%d lfreq=%d gain=%d portid=0x%x\n",
4950 __func__,
4951 duration_in_ms, high_freq, low_freq, gain,
4952 this_afe.dtmf_gen_rx_portid);
4953
4954 cmd_dtmf.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4955 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4956 cmd_dtmf.hdr.pkt_size = sizeof(cmd_dtmf);
4957 cmd_dtmf.hdr.src_port = 0;
4958 cmd_dtmf.hdr.dest_port = 0;
4959 cmd_dtmf.hdr.token = 0;
4960 cmd_dtmf.hdr.opcode = AFE_PORTS_CMD_DTMF_CTL;
4961 cmd_dtmf.duration_in_ms = duration_in_ms;
4962 cmd_dtmf.high_freq = high_freq;
4963 cmd_dtmf.low_freq = low_freq;
4964 cmd_dtmf.gain = gain;
4965 cmd_dtmf.num_ports = 1;
4966 cmd_dtmf.port_ids = q6audio_get_port_id(this_afe.dtmf_gen_rx_portid);
4967
4968 atomic_set(&this_afe.state, 1);
4969 atomic_set(&this_afe.status, 0);
4970 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_dtmf);
4971 if (ret < 0) {
4972 pr_err("%s: AFE DTMF failed for num_ports:%d ids:0x%x\n",
4973 __func__, cmd_dtmf.num_ports, cmd_dtmf.port_ids);
4974 ret = -EINVAL;
4975 goto fail_cmd;
4976 }
4977 index = q6audio_get_port_index(this_afe.dtmf_gen_rx_portid);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08004978 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08004979 pr_err("%s: AFE port index[%d] invalid!\n",
4980 __func__, index);
4981 ret = -EINVAL;
4982 goto fail_cmd;
4983 }
4984 ret = wait_event_timeout(this_afe.wait[index],
4985 (atomic_read(&this_afe.state) == 0),
4986 msecs_to_jiffies(TIMEOUT_MS));
4987 if (!ret) {
4988 pr_err("%s: wait_event timeout\n", __func__);
4989 ret = -EINVAL;
4990 goto fail_cmd;
4991 }
4992 if (atomic_read(&this_afe.status) > 0) {
4993 pr_err("%s: config cmd failed [%s]\n",
4994 __func__, adsp_err_get_err_str(
4995 atomic_read(&this_afe.status)));
4996 ret = adsp_err_get_lnx_err_code(
4997 atomic_read(&this_afe.status));
4998 goto fail_cmd;
4999 }
5000 return 0;
5001
5002fail_cmd:
5003 pr_err("%s: failed %d\n", __func__, ret);
5004 return ret;
5005}
5006
Siena Richardd83d83f2016-12-15 13:49:41 -08005007static int afe_sidetone_iir(u16 tx_port_id)
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005008{
Siena Richardd83d83f2016-12-15 13:49:41 -08005009 struct afe_loopback_iir_cfg_v2 iir_sidetone;
5010 int ret;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005011 int index = 0;
Siena Richardd83d83f2016-12-15 13:49:41 -08005012 uint16_t size = 0;
5013 int cal_index = AFE_SIDETONE_IIR_CAL;
5014 int iir_pregain = 0;
5015 int iir_num_biquad_stages = 0;
5016 int iir_enable;
5017 struct cal_block_data *cal_block;
5018 int mid;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005019
Siena Richardd83d83f2016-12-15 13:49:41 -08005020 memset(&iir_sidetone, 0, sizeof(iir_sidetone));
5021 index = q6audio_get_port_index(tx_port_id);
5022 iir_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5023 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5024 iir_sidetone.hdr.pkt_size = sizeof(iir_sidetone);
5025 iir_sidetone.hdr.src_port = 0;
5026 iir_sidetone.hdr.dest_port = 0;
5027 iir_sidetone.hdr.token = index;
5028 iir_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
5029 iir_sidetone.param.port_id = tx_port_id;
5030 iir_sidetone.param.payload_address_lsw = 0x00;
5031 iir_sidetone.param.payload_address_msw = 0x00;
5032 iir_sidetone.param.mem_map_handle = 0x00;
5033
5034 if (this_afe.cal_data[cal_index] == NULL) {
5035 pr_err("%s: cal data is NULL\n", __func__);
5036 ret = -EINVAL;
5037 goto done;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005038 }
Siena Richardd83d83f2016-12-15 13:49:41 -08005039 mutex_lock(&this_afe.cal_data[cal_index]->lock);
5040 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
5041 if (cal_block == NULL) {
5042 pr_err("%s: cal_block not found\n ", __func__);
5043 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5044 ret = -EINVAL;
5045 goto done;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005046 }
5047
Siena Richardd83d83f2016-12-15 13:49:41 -08005048 iir_pregain = ((struct audio_cal_info_sidetone_iir *)
5049 cal_block->cal_info)->pregain;
5050 iir_enable = ((struct audio_cal_info_sidetone_iir *)
5051 cal_block->cal_info)->iir_enable;
5052 iir_num_biquad_stages = ((struct audio_cal_info_sidetone_iir *)
5053 cal_block->cal_info)->num_biquad_stages;
5054 mid = ((struct audio_cal_info_sidetone_iir *)
5055 cal_block->cal_info)->mid;
5056
5057 /*
5058 * calculate the actual size of payload based on no of stages
5059 * enabled in calibration
5060 */
5061 size = (MAX_SIDETONE_IIR_DATA_SIZE / MAX_NO_IIR_FILTER_STAGE) *
5062 iir_num_biquad_stages;
5063 /*
5064 * For an odd number of stages, 2 bytes of padding are
5065 * required at the end of the payload.
5066 */
5067 if (iir_num_biquad_stages % 2) {
5068 pr_debug("%s: adding 2 to size:%d\n", __func__, size);
5069 size = size + 2;
5070 }
5071 memcpy(&iir_sidetone.st_iir_filter_config_data.iir_config,
5072 &((struct audio_cal_info_sidetone_iir *)
5073 cal_block->cal_info)->iir_config,
5074 sizeof(iir_sidetone.st_iir_filter_config_data.iir_config));
5075 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5076
5077 /*
5078 * Calculate the payload size for setparams command
5079 */
5080 iir_sidetone.param.payload_size = (sizeof(iir_sidetone) -
5081 sizeof(struct apr_hdr) -
5082 sizeof(struct afe_port_cmd_set_param_v2) -
5083 (MAX_SIDETONE_IIR_DATA_SIZE - size));
5084
5085 pr_debug("%s: payload size :%d\n", __func__,
5086 iir_sidetone.param.payload_size);
5087
5088 /*
5089 * Set IIR enable params
5090 */
5091 iir_sidetone.st_iir_enable_pdata.module_id = mid;
5092 iir_sidetone.st_iir_enable_pdata.param_id =
5093 AFE_PARAM_ID_ENABLE;
5094 iir_sidetone.st_iir_enable_pdata.param_size =
5095 sizeof(iir_sidetone.st_iir_mode_enable_data);
5096 iir_sidetone.st_iir_mode_enable_data.enable = iir_enable;
5097
5098 /*
5099 * Set IIR filter config params
5100 */
5101 iir_sidetone.st_iir_filter_config_pdata.module_id = mid;
5102 iir_sidetone.st_iir_filter_config_pdata.param_id =
5103 AFE_PARAM_ID_SIDETONE_IIR_FILTER_CONFIG;
5104 iir_sidetone.st_iir_filter_config_pdata.param_size =
5105 sizeof(iir_sidetone.st_iir_filter_config_data.num_biquad_stages)
5106 +
5107 sizeof(iir_sidetone.st_iir_filter_config_data.pregain) + size;
5108 iir_sidetone.st_iir_filter_config_pdata.reserved = 0;
5109 iir_sidetone.st_iir_filter_config_data.num_biquad_stages =
5110 iir_num_biquad_stages;
5111 iir_sidetone.st_iir_filter_config_data.pregain = iir_pregain;
5112 pr_debug("%s: tx(0x%x)mid(0x%x)iir_en(%d)stg(%d)gain(0x%x)size(%d)\n",
5113 __func__, tx_port_id, mid,
5114 iir_sidetone.st_iir_mode_enable_data.enable,
5115 iir_sidetone.st_iir_filter_config_data.num_biquad_stages,
5116 iir_sidetone.st_iir_filter_config_data.pregain,
5117 iir_sidetone.st_iir_filter_config_pdata.param_size);
5118 ret = afe_apr_send_pkt(&iir_sidetone, &this_afe.wait[index]);
5119 if (ret)
5120 pr_err("%s: AFE sidetone failed for tx_port(0x%x)\n",
5121 __func__, tx_port_id);
5122
5123done:
5124 return ret;
5125
5126}
5127
5128static int afe_sidetone(u16 tx_port_id, u16 rx_port_id, bool enable)
5129{
5130 struct afe_st_loopback_cfg_v1 cmd_sidetone;
5131 int ret;
5132 int index;
5133 int cal_index = AFE_SIDETONE_CAL;
5134 int sidetone_gain;
5135 int sidetone_enable;
5136 struct cal_block_data *cal_block;
5137 int mid = 0;
5138
5139 memset(&cmd_sidetone, 0, sizeof(cmd_sidetone));
5140 if (this_afe.cal_data[cal_index] == NULL) {
5141 pr_err("%s: cal data is NULL\n", __func__);
5142 ret = -EINVAL;
5143 goto done;
5144 }
5145 mutex_lock(&this_afe.cal_data[cal_index]->lock);
5146 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
5147 if (cal_block == NULL) {
5148 pr_err("%s: cal_block not found\n", __func__);
5149 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5150 ret = -EINVAL;
5151 goto done;
5152 }
5153 sidetone_gain = ((struct audio_cal_info_sidetone *)
5154 cal_block->cal_info)->gain;
5155 sidetone_enable = ((struct audio_cal_info_sidetone *)
5156 cal_block->cal_info)->enable;
5157 mid = ((struct audio_cal_info_sidetone *)
5158 cal_block->cal_info)->mid;
5159 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5160
5161 index = q6audio_get_port_index(tx_port_id);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005162 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5163 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5164 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
5165 cmd_sidetone.hdr.src_port = 0;
5166 cmd_sidetone.hdr.dest_port = 0;
Siena Richardd83d83f2016-12-15 13:49:41 -08005167 cmd_sidetone.hdr.token = index;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005168 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005169 cmd_sidetone.param.port_id = tx_port_id;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005170 cmd_sidetone.param.payload_size = (sizeof(cmd_sidetone) -
5171 sizeof(struct apr_hdr) -
5172 sizeof(struct afe_port_cmd_set_param_v2));
5173 cmd_sidetone.param.payload_address_lsw = 0x00;
5174 cmd_sidetone.param.payload_address_msw = 0x00;
5175 cmd_sidetone.param.mem_map_handle = 0x00;
Siena Richardd83d83f2016-12-15 13:49:41 -08005176 cmd_sidetone.gain_pdata.module_id = AFE_MODULE_LOOPBACK;
5177 cmd_sidetone.gain_pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
5178 /*
5179 * size of actual payload only
5180 */
5181 cmd_sidetone.gain_pdata.param_size = sizeof(
5182 struct afe_loopback_sidetone_gain);
5183 cmd_sidetone.gain_data.rx_port_id = rx_port_id;
5184 cmd_sidetone.gain_data.gain = sidetone_gain;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005185
Siena Richardd83d83f2016-12-15 13:49:41 -08005186 cmd_sidetone.cfg_pdata.module_id = AFE_MODULE_LOOPBACK;
5187 cmd_sidetone.cfg_pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
5188 /*
5189 * size of actual payload only
5190 */
5191 cmd_sidetone.cfg_pdata.param_size = sizeof(struct loopback_cfg_data);
5192 cmd_sidetone.cfg_data.loopback_cfg_minor_version =
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005193 AFE_API_VERSION_LOOPBACK_CONFIG;
Siena Richardd83d83f2016-12-15 13:49:41 -08005194 cmd_sidetone.cfg_data.dst_port_id = rx_port_id;
5195 cmd_sidetone.cfg_data.routing_mode = LB_MODE_SIDETONE;
Vikram Panduranga74934752017-03-07 18:03:07 -08005196 cmd_sidetone.cfg_data.enable = enable;
Siena Richardd83d83f2016-12-15 13:49:41 -08005197
5198 pr_debug("%s rx(0x%x) tx(0x%x) enable(%d) mid(0x%x) gain(%d) sidetone_enable(%d)\n",
5199 __func__, rx_port_id, tx_port_id,
5200 enable, mid, sidetone_gain, sidetone_enable);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005201
5202 ret = afe_apr_send_pkt(&cmd_sidetone, &this_afe.wait[index]);
5203 if (ret)
Siena Richardd83d83f2016-12-15 13:49:41 -08005204 pr_err("%s: AFE sidetone send failed for tx_port:%d rx_port:%d ret:%d\n",
5205 __func__, tx_port_id, rx_port_id, ret);
5206done:
5207 return ret;
5208}
5209
5210int afe_sidetone_enable(u16 tx_port_id, u16 rx_port_id, bool enable)
5211{
5212 int ret;
5213 int index;
5214
5215 index = q6audio_get_port_index(rx_port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08005216 if (index < 0 || index >= AFE_MAX_PORTS) {
Siena Richardd83d83f2016-12-15 13:49:41 -08005217 pr_err("%s: AFE port index[%d] invalid!\n",
5218 __func__, index);
5219 ret = -EINVAL;
5220 goto done;
5221 }
5222 if (q6audio_validate_port(rx_port_id) < 0) {
5223 pr_err("%s: Invalid port 0x%x\n",
5224 __func__, rx_port_id);
5225 ret = -EINVAL;
5226 goto done;
5227 }
5228 index = q6audio_get_port_index(tx_port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08005229 if (index < 0 || index >= AFE_MAX_PORTS) {
Siena Richardd83d83f2016-12-15 13:49:41 -08005230 pr_err("%s: AFE port index[%d] invalid!\n",
5231 __func__, index);
5232 ret = -EINVAL;
5233 goto done;
5234 }
5235 if (q6audio_validate_port(tx_port_id) < 0) {
5236 pr_err("%s: Invalid port 0x%x\n",
5237 __func__, tx_port_id);
5238 ret = -EINVAL;
5239 goto done;
5240 }
5241 if (enable) {
5242 ret = afe_sidetone_iir(tx_port_id);
5243 if (ret)
5244 goto done;
5245 }
5246
5247 ret = afe_sidetone(tx_port_id, rx_port_id, enable);
5248
5249done:
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005250 return ret;
5251}
5252
5253int afe_validate_port(u16 port_id)
5254{
5255 int ret;
5256
5257 switch (port_id) {
5258 case PRIMARY_I2S_RX:
5259 case PRIMARY_I2S_TX:
5260 case AFE_PORT_ID_PRIMARY_PCM_RX:
5261 case AFE_PORT_ID_PRIMARY_PCM_TX:
5262 case AFE_PORT_ID_SECONDARY_PCM_RX:
5263 case AFE_PORT_ID_SECONDARY_PCM_TX:
5264 case AFE_PORT_ID_TERTIARY_PCM_RX:
5265 case AFE_PORT_ID_TERTIARY_PCM_TX:
5266 case AFE_PORT_ID_QUATERNARY_PCM_RX:
5267 case AFE_PORT_ID_QUATERNARY_PCM_TX:
5268 case SECONDARY_I2S_RX:
5269 case SECONDARY_I2S_TX:
5270 case MI2S_RX:
5271 case MI2S_TX:
5272 case HDMI_RX:
5273 case DISPLAY_PORT_RX:
5274 case AFE_PORT_ID_SPDIF_RX:
5275 case RSVD_2:
5276 case RSVD_3:
5277 case DIGI_MIC_TX:
5278 case VOICE_RECORD_RX:
5279 case VOICE_RECORD_TX:
5280 case VOICE_PLAYBACK_TX:
5281 case VOICE2_PLAYBACK_TX:
5282 case SLIMBUS_0_RX:
5283 case SLIMBUS_0_TX:
5284 case SLIMBUS_1_RX:
5285 case SLIMBUS_1_TX:
5286 case SLIMBUS_2_RX:
5287 case SLIMBUS_2_TX:
5288 case SLIMBUS_3_RX:
5289 case INT_BT_SCO_RX:
5290 case INT_BT_SCO_TX:
5291 case INT_BT_A2DP_RX:
5292 case INT_FM_RX:
5293 case INT_FM_TX:
5294 case RT_PROXY_PORT_001_RX:
5295 case RT_PROXY_PORT_001_TX:
5296 case SLIMBUS_4_RX:
5297 case SLIMBUS_4_TX:
5298 case SLIMBUS_5_RX:
5299 case SLIMBUS_6_RX:
5300 case SLIMBUS_6_TX:
5301 case SLIMBUS_7_RX:
5302 case SLIMBUS_7_TX:
5303 case SLIMBUS_8_RX:
5304 case SLIMBUS_8_TX:
5305 case AFE_PORT_ID_USB_RX:
5306 case AFE_PORT_ID_USB_TX:
5307 case AFE_PORT_ID_PRIMARY_MI2S_RX:
5308 case AFE_PORT_ID_PRIMARY_MI2S_TX:
5309 case AFE_PORT_ID_SECONDARY_MI2S_RX:
5310 case AFE_PORT_ID_SECONDARY_MI2S_TX:
5311 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
5312 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
5313 case AFE_PORT_ID_TERTIARY_MI2S_RX:
5314 case AFE_PORT_ID_TERTIARY_MI2S_TX:
5315 case AFE_PORT_ID_QUINARY_MI2S_RX:
5316 case AFE_PORT_ID_QUINARY_MI2S_TX:
5317 case AFE_PORT_ID_SENARY_MI2S_TX:
5318 case AFE_PORT_ID_PRIMARY_TDM_RX:
5319 case AFE_PORT_ID_PRIMARY_TDM_TX:
5320 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
5321 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
5322 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
5323 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
5324 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
5325 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
5326 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
5327 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
5328 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
5329 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
5330 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
5331 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
5332 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
5333 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
5334 case AFE_PORT_ID_SECONDARY_TDM_RX:
5335 case AFE_PORT_ID_SECONDARY_TDM_TX:
5336 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
5337 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
5338 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
5339 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
5340 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
5341 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
5342 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
5343 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
5344 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
5345 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
5346 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
5347 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
5348 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
5349 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
5350 case AFE_PORT_ID_TERTIARY_TDM_RX:
5351 case AFE_PORT_ID_TERTIARY_TDM_TX:
5352 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
5353 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
5354 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
5355 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
5356 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
5357 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
5358 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
5359 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
5360 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
5361 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
5362 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
5363 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
5364 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
5365 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
5366 case AFE_PORT_ID_QUATERNARY_TDM_RX:
5367 case AFE_PORT_ID_QUATERNARY_TDM_TX:
5368 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
5369 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
5370 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
5371 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
5372 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
5373 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
5374 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
5375 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
5376 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
5377 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
5378 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
5379 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
5380 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
5381 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
Laxminath Kasam24f049a2017-01-24 18:05:32 +05305382 case AFE_PORT_ID_INT0_MI2S_RX:
5383 case AFE_PORT_ID_INT1_MI2S_RX:
5384 case AFE_PORT_ID_INT2_MI2S_RX:
5385 case AFE_PORT_ID_INT3_MI2S_RX:
5386 case AFE_PORT_ID_INT4_MI2S_RX:
5387 case AFE_PORT_ID_INT5_MI2S_RX:
5388 case AFE_PORT_ID_INT6_MI2S_RX:
5389 case AFE_PORT_ID_INT0_MI2S_TX:
5390 case AFE_PORT_ID_INT1_MI2S_TX:
5391 case AFE_PORT_ID_INT2_MI2S_TX:
5392 case AFE_PORT_ID_INT3_MI2S_TX:
5393 case AFE_PORT_ID_INT4_MI2S_TX:
5394 case AFE_PORT_ID_INT5_MI2S_TX:
5395 case AFE_PORT_ID_INT6_MI2S_TX:
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005396 {
5397 ret = 0;
5398 break;
5399 }
5400
5401 default:
5402 pr_err("%s: default ret 0x%x\n", __func__, port_id);
5403 ret = -EINVAL;
5404 }
5405
5406 return ret;
5407}
5408
5409int afe_convert_virtual_to_portid(u16 port_id)
5410{
5411 int ret;
5412
5413 /*
5414 * if port_id is virtual, convert to physical..
5415 * if port_id is already physical, return physical
5416 */
5417 if (afe_validate_port(port_id) < 0) {
5418 if (port_id == RT_PROXY_DAI_001_RX ||
5419 port_id == RT_PROXY_DAI_001_TX ||
5420 port_id == RT_PROXY_DAI_002_RX ||
5421 port_id == RT_PROXY_DAI_002_TX) {
5422 ret = VIRTUAL_ID_TO_PORTID(port_id);
5423 } else {
5424 pr_err("%s: wrong port 0x%x\n",
5425 __func__, port_id);
5426 ret = -EINVAL;
5427 }
5428 } else
5429 ret = port_id;
5430
5431 return ret;
5432}
5433int afe_port_stop_nowait(int port_id)
5434{
5435 struct afe_port_cmd_device_stop stop;
5436 int ret = 0;
5437
5438 if (this_afe.apr == NULL) {
5439 pr_err("%s: AFE is already closed\n", __func__);
5440 ret = -EINVAL;
5441 goto fail_cmd;
5442 }
5443 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
5444 port_id = q6audio_convert_virtual_to_portid(port_id);
5445
5446 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5447 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5448 stop.hdr.pkt_size = sizeof(stop);
5449 stop.hdr.src_port = 0;
5450 stop.hdr.dest_port = 0;
5451 stop.hdr.token = 0;
5452 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
5453 stop.port_id = port_id;
5454 stop.reserved = 0;
5455
5456 ret = afe_apr_send_pkt(&stop, NULL);
5457 if (ret)
5458 pr_err("%s: AFE close failed %d\n", __func__, ret);
5459
5460fail_cmd:
5461 return ret;
5462
5463}
5464
5465int afe_close(int port_id)
5466{
5467 struct afe_port_cmd_device_stop stop;
5468 enum afe_mad_type mad_type;
5469 int ret = 0;
5470 int index = 0;
5471 uint16_t port_index;
5472
5473 if (this_afe.apr == NULL) {
5474 pr_err("%s: AFE is already closed\n", __func__);
5475 if ((port_id == RT_PROXY_DAI_001_RX) ||
5476 (port_id == RT_PROXY_DAI_002_TX))
5477 pcm_afe_instance[port_id & 0x1] = 0;
5478 if ((port_id == RT_PROXY_DAI_002_RX) ||
5479 (port_id == RT_PROXY_DAI_001_TX))
5480 proxy_afe_instance[port_id & 0x1] = 0;
5481 afe_close_done[port_id & 0x1] = true;
5482 ret = -EINVAL;
5483 goto fail_cmd;
5484 }
5485 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
5486 if ((port_id == RT_PROXY_DAI_001_RX) ||
5487 (port_id == RT_PROXY_DAI_002_TX)) {
5488 pr_debug("%s: before decrementing pcm_afe_instance %d\n",
5489 __func__, pcm_afe_instance[port_id & 0x1]);
5490 port_id = VIRTUAL_ID_TO_PORTID(port_id);
5491 pcm_afe_instance[port_id & 0x1]--;
5492 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
5493 proxy_afe_instance[port_id & 0x1] == 0)) ||
5494 afe_close_done[port_id & 0x1] == true)
5495 return 0;
5496
5497 afe_close_done[port_id & 0x1] = true;
5498 }
5499
5500 if ((port_id == RT_PROXY_DAI_002_RX) ||
5501 (port_id == RT_PROXY_DAI_001_TX)) {
5502 pr_debug("%s: before decrementing proxy_afe_instance %d\n",
5503 __func__, proxy_afe_instance[port_id & 0x1]);
5504 port_id = VIRTUAL_ID_TO_PORTID(port_id);
5505 proxy_afe_instance[port_id & 0x1]--;
5506 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
5507 proxy_afe_instance[port_id & 0x1] == 0)) ||
5508 afe_close_done[port_id & 0x1] == true)
5509 return 0;
5510
5511 afe_close_done[port_id & 0x1] = true;
5512 }
5513
5514 port_id = q6audio_convert_virtual_to_portid(port_id);
5515 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08005516 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005517 pr_err("%s: AFE port index[%d] invalid!\n",
5518 __func__, index);
5519 return -EINVAL;
5520 }
5521 ret = q6audio_validate_port(port_id);
5522 if (ret < 0) {
5523 pr_warn("%s: Not a valid port id 0x%x ret %d\n",
5524 __func__, port_id, ret);
5525 return -EINVAL;
5526 }
5527
5528 mad_type = afe_port_get_mad_type(port_id);
5529 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
5530 mad_type);
5531 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
5532 pr_debug("%s: Turn off MAD\n", __func__);
5533 ret = afe_turn_onoff_hw_mad(mad_type, false);
5534 if (ret) {
5535 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
5536 __func__, ret);
5537 return ret;
5538 }
5539 } else {
5540 pr_debug("%s: Not a MAD port\n", __func__);
5541 }
5542
5543 port_index = afe_get_port_index(port_id);
5544 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
5545 this_afe.afe_sample_rates[port_index] = 0;
5546 this_afe.topology[port_index] = 0;
Siena Richard23364c92017-01-11 16:20:55 -08005547 this_afe.dev_acdb_id[port_index] = 0;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005548 } else {
5549 pr_err("%s: port %d\n", __func__, port_index);
5550 ret = -EINVAL;
5551 goto fail_cmd;
5552 }
5553
5554 if ((port_id == this_afe.aanc_info.aanc_tx_port) &&
5555 (this_afe.aanc_info.aanc_active)) {
5556 memset(&this_afe.aanc_info, 0x00, sizeof(this_afe.aanc_info));
5557 ret = afe_aanc_mod_enable(this_afe.apr, port_id, 0);
5558 if (ret)
5559 pr_err("%s: AFE mod disable failed %d\n",
5560 __func__, ret);
5561 }
5562
5563 /*
5564 * even if ramp down configuration failed it is not serious enough to
5565 * warrant bailaing out.
5566 */
5567 if (afe_spk_ramp_dn_cfg(port_id) < 0)
5568 pr_err("%s: ramp down configuration failed\n", __func__);
5569
5570 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5571 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5572 stop.hdr.pkt_size = sizeof(stop);
5573 stop.hdr.src_port = 0;
5574 stop.hdr.dest_port = 0;
5575 stop.hdr.token = index;
5576 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
5577 stop.port_id = q6audio_get_port_id(port_id);
5578 stop.reserved = 0;
5579
5580 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
5581 if (ret)
5582 pr_err("%s: AFE close failed %d\n", __func__, ret);
5583
5584fail_cmd:
5585 return ret;
5586}
5587
5588int afe_set_digital_codec_core_clock(u16 port_id,
5589 struct afe_digital_clk_cfg *cfg)
5590{
5591 struct afe_lpass_digital_clk_config_command clk_cfg;
5592 int index = 0;
5593 int ret = 0;
5594
5595 if (!cfg) {
5596 pr_err("%s: clock cfg is NULL\n", __func__);
5597 ret = -EINVAL;
5598 return ret;
5599 }
5600
5601 ret = afe_q6_interface_prepare();
5602 if (ret != 0) {
5603 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
5604 return ret;
5605 }
5606
5607 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5608 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5609 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
5610 clk_cfg.hdr.src_port = 0;
5611 clk_cfg.hdr.dest_port = 0;
5612 clk_cfg.hdr.token = index;
5613
5614 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
5615 /*default rx port is taken to enable the codec digital clock*/
5616 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
5617 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
5618 - sizeof(clk_cfg.param);
5619 clk_cfg.param.payload_address_lsw = 0x00;
5620 clk_cfg.param.payload_address_msw = 0x00;
5621 clk_cfg.param.mem_map_handle = 0x00;
5622 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
5623 clk_cfg.pdata.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
5624 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
5625 clk_cfg.clk_cfg = *cfg;
5626
5627 pr_debug("%s: Minor version =0x%x clk val = %d\n"
5628 "clk root = 0x%x resrv = 0x%x\n",
5629 __func__, cfg->i2s_cfg_minor_version,
5630 cfg->clk_val, cfg->clk_root, cfg->reserved);
5631
5632 atomic_set(&this_afe.state, 1);
5633 atomic_set(&this_afe.status, 0);
5634 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
5635 if (ret < 0) {
5636 pr_err("%s: AFE enable for port 0x%x ret %d\n",
5637 __func__, port_id, ret);
5638 ret = -EINVAL;
5639 goto fail_cmd;
5640 }
5641
5642 ret = wait_event_timeout(this_afe.wait[index],
5643 (atomic_read(&this_afe.state) == 0),
5644 msecs_to_jiffies(TIMEOUT_MS));
5645 if (!ret) {
5646 pr_err("%s: wait_event timeout\n", __func__);
5647 ret = -EINVAL;
5648 goto fail_cmd;
5649 }
5650 if (atomic_read(&this_afe.status) > 0) {
5651 pr_err("%s: config cmd failed [%s]\n",
5652 __func__, adsp_err_get_err_str(
5653 atomic_read(&this_afe.status)));
5654 ret = adsp_err_get_lnx_err_code(
5655 atomic_read(&this_afe.status));
5656 goto fail_cmd;
5657 }
5658
5659fail_cmd:
5660 return ret;
5661}
5662
5663int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg)
5664{
5665 struct afe_lpass_clk_config_command clk_cfg;
5666 int index = 0;
5667 int ret = 0;
5668
5669 if (!cfg) {
5670 pr_err("%s: clock cfg is NULL\n", __func__);
5671 ret = -EINVAL;
5672 return ret;
5673 }
5674 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08005675 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005676 pr_err("%s: AFE port index[%d] invalid!\n",
5677 __func__, index);
5678 return -EINVAL;
5679 }
5680 ret = q6audio_is_digital_pcm_interface(port_id);
5681 if (ret < 0) {
5682 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
5683 __func__, ret);
5684 return -EINVAL;
5685 }
5686
5687 ret = afe_q6_interface_prepare();
5688 if (ret != 0) {
5689 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
5690 return ret;
5691 }
5692
5693 mutex_lock(&this_afe.afe_cmd_lock);
5694 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5695 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5696 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
5697 clk_cfg.hdr.src_port = 0;
5698 clk_cfg.hdr.dest_port = 0;
5699 clk_cfg.hdr.token = index;
5700
5701 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
5702 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
5703 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
5704 - sizeof(clk_cfg.param);
5705 clk_cfg.param.payload_address_lsw = 0x00;
5706 clk_cfg.param.payload_address_msw = 0x00;
5707 clk_cfg.param.mem_map_handle = 0x00;
5708 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
5709 clk_cfg.pdata.param_id = AFE_PARAM_ID_LPAIF_CLK_CONFIG;
5710 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
5711 clk_cfg.clk_cfg = *cfg;
5712
5713 pr_debug("%s: Minor version =0x%x clk val1 = %d\n"
5714 "clk val2 = %d, clk src = 0x%x\n"
5715 "clk root = 0x%x clk mode = 0x%x resrv = 0x%x\n"
5716 "port id = 0x%x\n",
5717 __func__, cfg->i2s_cfg_minor_version,
5718 cfg->clk_val1, cfg->clk_val2, cfg->clk_src,
5719 cfg->clk_root, cfg->clk_set_mode,
5720 cfg->reserved, q6audio_get_port_id(port_id));
5721
5722 atomic_set(&this_afe.state, 1);
5723 atomic_set(&this_afe.status, 0);
5724 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
5725 if (ret < 0) {
5726 pr_err("%s: AFE enable for port 0x%x ret %d\n",
5727 __func__, port_id, ret);
5728 ret = -EINVAL;
5729 goto fail_cmd;
5730 }
5731
5732 ret = wait_event_timeout(this_afe.wait[index],
5733 (atomic_read(&this_afe.state) == 0),
5734 msecs_to_jiffies(TIMEOUT_MS));
5735 if (!ret) {
5736 pr_err("%s: wait_event timeout\n", __func__);
5737 ret = -EINVAL;
5738 goto fail_cmd;
5739 }
5740 if (atomic_read(&this_afe.status) > 0) {
5741 pr_err("%s: config cmd failed [%s]\n",
5742 __func__, adsp_err_get_err_str(
5743 atomic_read(&this_afe.status)));
5744 ret = adsp_err_get_lnx_err_code(
5745 atomic_read(&this_afe.status));
5746 goto fail_cmd;
5747 }
5748
5749fail_cmd:
5750 mutex_unlock(&this_afe.afe_cmd_lock);
5751 return ret;
5752}
5753
Karthikeyan Mani9d63f3b2017-06-27 14:23:26 -07005754/**
5755 * afe_set_lpass_clk_cfg - Set AFE clk config
5756 *
5757 * @index: port index
5758 * @cfg: pointer to clk set struct
5759 *
5760 * Returns 0 on success, appropriate error code otherwise
5761 */
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005762int afe_set_lpass_clk_cfg(int index, struct afe_clk_set *cfg)
5763{
5764 struct afe_lpass_clk_config_command_v2 clk_cfg;
5765 int ret = 0;
5766
5767 if (!cfg) {
5768 pr_err("%s: clock cfg is NULL\n", __func__);
5769 ret = -EINVAL;
5770 return ret;
5771 }
5772
5773 if (index < 0 || index >= AFE_MAX_PORTS) {
5774 pr_err("%s: index[%d] invalid!\n", __func__, index);
5775 return -EINVAL;
5776 }
5777
5778 ret = afe_q6_interface_prepare();
5779 if (ret != 0) {
5780 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
5781 return ret;
5782 }
5783
5784 mutex_lock(&this_afe.afe_cmd_lock);
5785 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5786 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5787 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
5788 clk_cfg.hdr.src_port = 0;
5789 clk_cfg.hdr.dest_port = 0;
5790 clk_cfg.hdr.token = index;
5791
5792 clk_cfg.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
5793 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
5794 - sizeof(clk_cfg.param);
5795 clk_cfg.param.payload_address_lsw = 0x00;
5796 clk_cfg.param.payload_address_msw = 0x00;
5797 clk_cfg.param.mem_map_handle = 0x00;
5798 clk_cfg.pdata.module_id = AFE_MODULE_CLOCK_SET;
5799 clk_cfg.pdata.param_id = AFE_PARAM_ID_CLOCK_SET;
5800 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
5801 clk_cfg.clk_cfg = *cfg;
5802
5803
5804 pr_debug("%s: Minor version =0x%x clk id = %d\n"
5805 "clk freq (Hz) = %d, clk attri = 0x%x\n"
5806 "clk root = 0x%x clk enable = 0x%x\n",
5807 __func__, cfg->clk_set_minor_version,
5808 cfg->clk_id, cfg->clk_freq_in_hz, cfg->clk_attri,
5809 cfg->clk_root, cfg->enable);
5810
5811 atomic_set(&this_afe.state, 1);
5812 atomic_set(&this_afe.status, 0);
5813 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
5814 if (ret < 0) {
5815 pr_err("%s: AFE clk cfg failed with ret %d\n",
5816 __func__, ret);
5817 ret = -EINVAL;
5818 goto fail_cmd;
5819 }
5820
5821 ret = wait_event_timeout(this_afe.wait[index],
5822 (atomic_read(&this_afe.state) == 0),
5823 msecs_to_jiffies(TIMEOUT_MS));
5824 if (!ret) {
5825 pr_err("%s: wait_event timeout\n", __func__);
5826 ret = -EINVAL;
5827 goto fail_cmd;
5828 } else {
5829 /* set ret to 0 as no timeout happened */
5830 ret = 0;
5831 }
5832 if (atomic_read(&this_afe.status) != 0) {
5833 pr_err("%s: config cmd failed\n", __func__);
5834 ret = -EINVAL;
5835 goto fail_cmd;
5836 }
5837
5838fail_cmd:
5839 mutex_unlock(&this_afe.afe_cmd_lock);
5840 return ret;
5841}
Karthikeyan Mani9d63f3b2017-06-27 14:23:26 -07005842EXPORT_SYMBOL(afe_set_lpass_clk_cfg);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005843
Karthikeyan Mani9d63f3b2017-06-27 14:23:26 -07005844/**
5845 * afe_set_lpass_clock_v2 - Enable AFE lpass clock
5846 *
5847 * @port_id: AFE port id
5848 * @cfg: pointer to clk set struct
5849 *
5850 * Returns 0 on success, appropriate error code otherwise
5851 */
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005852int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
5853{
5854 int index = 0;
5855 int ret = 0;
5856
5857 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08005858 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005859 pr_err("%s: AFE port index[%d] invalid!\n",
5860 __func__, index);
5861 return -EINVAL;
5862 }
5863 ret = q6audio_is_digital_pcm_interface(port_id);
5864 if (ret < 0) {
5865 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
5866 __func__, ret);
5867 return -EINVAL;
5868 }
5869
5870 ret = afe_set_lpass_clk_cfg(index, cfg);
5871 if (ret)
5872 pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
5873 __func__, ret);
5874
5875 return ret;
5876}
Karthikeyan Mani9d63f3b2017-06-27 14:23:26 -07005877EXPORT_SYMBOL(afe_set_lpass_clock_v2);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005878
5879int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
5880 struct afe_digital_clk_cfg *cfg)
5881{
5882 struct afe_lpass_digital_clk_config_command clk_cfg;
5883 int index = 0;
5884 int ret = 0;
5885
5886 if (!cfg) {
5887 pr_err("%s: clock cfg is NULL\n", __func__);
5888 ret = -EINVAL;
5889 return ret;
5890 }
5891 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08005892 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005893 pr_err("%s: AFE port index[%d] invalid!\n",
5894 __func__, index);
5895 return -EINVAL;
5896 }
5897 ret = q6audio_is_digital_pcm_interface(port_id);
5898 if (ret < 0) {
5899 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
5900 __func__, ret);
5901 return -EINVAL;
5902 }
5903
5904 ret = afe_q6_interface_prepare();
5905 if (ret != 0) {
5906 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
5907 return ret;
5908 }
5909
5910 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5911 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5912 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
5913 clk_cfg.hdr.src_port = 0;
5914 clk_cfg.hdr.dest_port = 0;
5915 clk_cfg.hdr.token = index;
5916
5917 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
5918 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
5919 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
5920 - sizeof(clk_cfg.param);
5921 clk_cfg.param.payload_address_lsw = 0x00;
5922 clk_cfg.param.payload_address_msw = 0x00;
5923 clk_cfg.param.mem_map_handle = 0x00;
5924 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
5925 clk_cfg.pdata.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
5926 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
5927 clk_cfg.clk_cfg = *cfg;
5928
5929 pr_debug("%s: Minor version =0x%x clk val = %d\n"
5930 "clk root = 0x%x resrv = 0x%x port id = 0x%x\n",
5931 __func__, cfg->i2s_cfg_minor_version,
5932 cfg->clk_val, cfg->clk_root, cfg->reserved,
5933 q6audio_get_port_id(port_id));
5934
5935 atomic_set(&this_afe.state, 1);
5936 atomic_set(&this_afe.status, 0);
5937 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
5938 if (ret < 0) {
5939 pr_err("%s: AFE enable for port 0x0x%x ret %d\n",
5940 __func__, port_id, ret);
5941 ret = -EINVAL;
5942 goto fail_cmd;
5943 }
5944
5945 ret = wait_event_timeout(this_afe.wait[index],
5946 (atomic_read(&this_afe.state) == 0),
5947 msecs_to_jiffies(TIMEOUT_MS));
5948 if (!ret) {
5949 pr_err("%s: wait_event timeout\n", __func__);
5950 ret = -EINVAL;
5951 goto fail_cmd;
5952 }
5953 if (atomic_read(&this_afe.status) > 0) {
5954 pr_err("%s: config cmd failed [%s]\n",
5955 __func__, adsp_err_get_err_str(
5956 atomic_read(&this_afe.status)));
5957 ret = adsp_err_get_lnx_err_code(
5958 atomic_read(&this_afe.status));
5959 goto fail_cmd;
5960 }
5961
5962fail_cmd:
5963 return ret;
5964}
5965
5966int afe_enable_lpass_core_shared_clock(u16 port_id, u32 enable)
5967{
5968 struct afe_lpass_core_shared_clk_config_command clk_cfg;
5969 int index = 0;
5970 int ret = 0;
5971
5972 index = q6audio_get_port_index(port_id);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08005973 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08005974 pr_err("%s: AFE port index[%d] invalid!\n",
5975 __func__, index);
5976 return -EINVAL;
5977 }
5978 ret = q6audio_is_digital_pcm_interface(port_id);
5979 if (ret < 0) {
5980 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
5981 __func__, ret);
5982 return -EINVAL;
5983 }
5984
5985 ret = afe_q6_interface_prepare();
5986 if (ret != 0) {
5987 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
5988 return ret;
5989 }
5990
5991 mutex_lock(&this_afe.afe_cmd_lock);
5992 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5993 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5994 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
5995 clk_cfg.hdr.src_port = 0;
5996 clk_cfg.hdr.dest_port = 0;
5997 clk_cfg.hdr.token = index;
5998
5999 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6000 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6001 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6002 - sizeof(clk_cfg.param);
6003 clk_cfg.param.payload_address_lsw = 0x00;
6004 clk_cfg.param.payload_address_msw = 0x00;
6005 clk_cfg.param.mem_map_handle = 0x00;
6006 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6007 clk_cfg.pdata.param_id = AFE_PARAM_ID_LPASS_CORE_SHARED_CLOCK_CONFIG;
6008 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6009 clk_cfg.clk_cfg.lpass_core_shared_clk_cfg_minor_version =
6010 AFE_API_VERSION_LPASS_CORE_SHARED_CLK_CONFIG;
6011 clk_cfg.clk_cfg.enable = enable;
6012
6013 pr_debug("%s: port id = %d, enable = %d\n",
6014 __func__, q6audio_get_port_id(port_id), enable);
6015
6016 atomic_set(&this_afe.state, 1);
6017 atomic_set(&this_afe.status, 0);
6018 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6019 if (ret < 0) {
6020 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6021 __func__, port_id, ret);
6022 ret = -EINVAL;
6023 goto fail_cmd;
6024 }
6025
6026 ret = wait_event_timeout(this_afe.wait[index],
6027 (atomic_read(&this_afe.state) == 0),
6028 msecs_to_jiffies(TIMEOUT_MS));
6029 if (!ret) {
6030 pr_err("%s: wait_event timeout\n", __func__);
6031 ret = -EINVAL;
6032 goto fail_cmd;
6033 }
6034 if (atomic_read(&this_afe.status) > 0) {
6035 pr_err("%s: config cmd failed [%s]\n",
6036 __func__, adsp_err_get_err_str(
6037 atomic_read(&this_afe.status)));
6038 ret = adsp_err_get_lnx_err_code(
6039 atomic_read(&this_afe.status));
6040 goto fail_cmd;
6041 }
6042
6043fail_cmd:
6044 mutex_unlock(&this_afe.afe_cmd_lock);
6045 return ret;
6046}
6047
6048int q6afe_check_osr_clk_freq(u32 freq)
6049{
6050 int ret = 0;
6051
6052 switch (freq) {
6053 case Q6AFE_LPASS_OSR_CLK_12_P288_MHZ:
6054 case Q6AFE_LPASS_OSR_CLK_8_P192_MHZ:
6055 case Q6AFE_LPASS_OSR_CLK_6_P144_MHZ:
6056 case Q6AFE_LPASS_OSR_CLK_4_P096_MHZ:
6057 case Q6AFE_LPASS_OSR_CLK_3_P072_MHZ:
6058 case Q6AFE_LPASS_OSR_CLK_2_P048_MHZ:
6059 case Q6AFE_LPASS_OSR_CLK_1_P536_MHZ:
6060 case Q6AFE_LPASS_OSR_CLK_1_P024_MHZ:
6061 case Q6AFE_LPASS_OSR_CLK_768_kHZ:
6062 case Q6AFE_LPASS_OSR_CLK_512_kHZ:
6063 break;
6064 default:
6065 pr_err("%s: deafault freq 0x%x\n",
6066 __func__, freq);
6067 ret = -EINVAL;
6068 }
6069 return ret;
6070}
6071
6072int afe_get_sp_th_vi_ftm_data(struct afe_sp_th_vi_get_param *th_vi)
6073{
6074 int ret = -EINVAL;
6075 int index = 0, port = SLIMBUS_4_TX;
6076
6077 if (!th_vi) {
6078 pr_err("%s: Invalid params\n", __func__);
6079 goto done;
6080 }
6081 if (this_afe.vi_tx_port != -1)
6082 port = this_afe.vi_tx_port;
6083
6084 ret = q6audio_validate_port(port);
6085 if (ret < 0) {
6086 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6087 goto done;
6088 }
6089 index = q6audio_get_port_index(port);
6090 if (index < 0) {
6091 pr_err("%s: invalid port 0x%x, index %d\n",
6092 __func__, port, index);
6093 ret = -EINVAL;
6094 goto done;
6095 }
6096 th_vi->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6097 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6098 th_vi->hdr.pkt_size = sizeof(*th_vi);
6099 th_vi->hdr.src_port = 0;
6100 th_vi->hdr.dest_port = 0;
6101 th_vi->hdr.token = index;
6102 th_vi->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6103 th_vi->get_param.mem_map_handle = 0;
6104 th_vi->get_param.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
6105 th_vi->get_param.param_id = AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS;
6106 th_vi->get_param.payload_address_lsw = 0;
6107 th_vi->get_param.payload_address_msw = 0;
6108 th_vi->get_param.payload_size = sizeof(*th_vi)
6109 - sizeof(th_vi->get_param) - sizeof(th_vi->hdr);
6110 th_vi->get_param.port_id = q6audio_get_port_id(port);
6111 th_vi->pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
6112 th_vi->pdata.param_id = AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS;
6113 th_vi->pdata.param_size = sizeof(th_vi->param);
6114 atomic_set(&this_afe.status, 0);
6115 atomic_set(&this_afe.state, 1);
6116 ret = apr_send_pkt(this_afe.apr, (uint32_t *)th_vi);
6117 if (ret < 0) {
6118 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
6119 __func__, port, th_vi->get_param.param_id, ret);
6120 goto done;
6121 }
6122 ret = wait_event_timeout(this_afe.wait[index],
6123 (atomic_read(&this_afe.state) == 0),
6124 msecs_to_jiffies(TIMEOUT_MS));
6125 if (!ret) {
6126 pr_err("%s: wait_event timeout\n", __func__);
6127 ret = -EINVAL;
6128 goto done;
6129 }
6130 if (atomic_read(&this_afe.status) > 0) {
6131 pr_err("%s: config cmd failed [%s]\n",
6132 __func__, adsp_err_get_err_str(
6133 atomic_read(&this_afe.status)));
6134 ret = adsp_err_get_lnx_err_code(atomic_read(&this_afe.status));
6135 goto done;
6136 }
6137 memcpy(&th_vi->param, &this_afe.th_vi_resp.param,
6138 sizeof(this_afe.th_vi_resp.param));
6139 pr_debug("%s: DC resistance %d %d temp %d %d status %d %d\n",
6140 __func__, th_vi->param.dc_res_q24[SP_V2_SPKR_1],
6141 th_vi->param.dc_res_q24[SP_V2_SPKR_2],
6142 th_vi->param.temp_q22[SP_V2_SPKR_1],
6143 th_vi->param.temp_q22[SP_V2_SPKR_2],
6144 th_vi->param.status[SP_V2_SPKR_1],
6145 th_vi->param.status[SP_V2_SPKR_2]);
6146 ret = 0;
6147done:
6148 return ret;
6149}
6150
6151int afe_get_sp_ex_vi_ftm_data(struct afe_sp_ex_vi_get_param *ex_vi)
6152{
6153 int ret = -EINVAL;
6154 int index = 0, port = SLIMBUS_4_TX;
6155
6156 if (!ex_vi) {
6157 pr_err("%s: Invalid params\n", __func__);
6158 goto done;
6159 }
6160 if (this_afe.vi_tx_port != -1)
6161 port = this_afe.vi_tx_port;
6162
6163 ret = q6audio_validate_port(port);
6164 if (ret < 0) {
6165 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6166 goto done;
6167 }
6168
6169 index = q6audio_get_port_index(port);
6170 if (index < 0) {
6171 pr_err("%s: invalid index %d port 0x%x\n", __func__,
6172 index, port);
6173 ret = -EINVAL;
6174 goto done;
6175 }
6176
6177 ex_vi->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6178 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6179 ex_vi->hdr.pkt_size = sizeof(*ex_vi);
6180 ex_vi->hdr.src_port = 0;
6181 ex_vi->hdr.dest_port = 0;
6182 ex_vi->hdr.token = index;
6183 ex_vi->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6184 ex_vi->get_param.mem_map_handle = 0;
6185 ex_vi->get_param.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
6186 ex_vi->get_param.param_id = AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS;
6187 ex_vi->get_param.payload_address_lsw = 0;
6188 ex_vi->get_param.payload_address_msw = 0;
6189 ex_vi->get_param.payload_size = sizeof(*ex_vi)
6190 - sizeof(ex_vi->get_param) - sizeof(ex_vi->hdr);
6191 ex_vi->get_param.port_id = q6audio_get_port_id(port);
6192 ex_vi->pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
6193 ex_vi->pdata.param_id = AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS;
6194 ex_vi->pdata.param_size = sizeof(ex_vi->param);
6195 atomic_set(&this_afe.status, 0);
6196 atomic_set(&this_afe.state, 1);
6197 ret = apr_send_pkt(this_afe.apr, (uint32_t *)ex_vi);
6198 if (ret < 0) {
6199 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
6200 __func__, port, ex_vi->get_param.param_id, ret);
6201 goto done;
6202 }
6203 ret = wait_event_timeout(this_afe.wait[index],
6204 (atomic_read(&this_afe.state) == 0),
6205 msecs_to_jiffies(TIMEOUT_MS));
6206 if (!ret) {
6207 pr_err("%s: wait_event timeout\n", __func__);
6208 ret = -EINVAL;
6209 goto done;
6210 }
6211 if (atomic_read(&this_afe.status) > 0) {
6212 pr_err("%s: config cmd failed [%s]\n",
6213 __func__, adsp_err_get_err_str(
6214 atomic_read(&this_afe.status)));
6215 ret = adsp_err_get_lnx_err_code(atomic_read(&this_afe.status));
6216 goto done;
6217 }
6218 memcpy(&ex_vi->param, &this_afe.ex_vi_resp.param,
6219 sizeof(this_afe.ex_vi_resp.param));
6220 pr_debug("%s: freq %d %d resistance %d %d qfactor %d %d state %d %d\n",
6221 __func__, ex_vi->param.freq_q20[SP_V2_SPKR_1],
6222 ex_vi->param.freq_q20[SP_V2_SPKR_2],
6223 ex_vi->param.resis_q24[SP_V2_SPKR_1],
6224 ex_vi->param.resis_q24[SP_V2_SPKR_2],
6225 ex_vi->param.qmct_q24[SP_V2_SPKR_1],
6226 ex_vi->param.qmct_q24[SP_V2_SPKR_2],
6227 ex_vi->param.status[SP_V2_SPKR_1],
6228 ex_vi->param.status[SP_V2_SPKR_2]);
6229 ret = 0;
6230done:
6231 return ret;
6232}
6233
Manish Dewangan1903ffb2016-12-20 12:56:24 +05306234int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
6235 u16 port)
6236{
6237 int ret = -EINVAL;
6238 int index = 0;
6239 struct afe_av_dev_drift_get_param av_dev_drift;
6240
6241 if (!timing_stats) {
6242 pr_err("%s: Invalid params\n", __func__);
6243 goto exit;
6244 }
6245
6246 ret = q6audio_validate_port(port);
6247 if (ret < 0) {
6248 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6249 ret = -EINVAL;
6250 goto exit;
6251 }
6252
6253 index = q6audio_get_port_index(port);
6254 if (index < 0 || index >= AFE_MAX_PORTS) {
6255 pr_err("%s: Invalid AFE port index[%d]\n",
6256 __func__, index);
6257 ret = -EINVAL;
6258 goto exit;
6259 }
6260
6261 memset(&av_dev_drift, 0, sizeof(struct afe_av_dev_drift_get_param));
6262
6263 av_dev_drift.hdr.hdr_field =
6264 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6265 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6266 av_dev_drift.hdr.pkt_size = sizeof(av_dev_drift);
6267 av_dev_drift.hdr.src_port = 0;
6268 av_dev_drift.hdr.dest_port = 0;
6269 av_dev_drift.hdr.token = index;
6270 av_dev_drift.hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6271 av_dev_drift.get_param.mem_map_handle = 0;
6272 av_dev_drift.get_param.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6273 av_dev_drift.get_param.param_id = AFE_PARAM_ID_DEV_TIMING_STATS;
6274 av_dev_drift.get_param.payload_address_lsw = 0;
6275 av_dev_drift.get_param.payload_address_msw = 0;
6276 av_dev_drift.get_param.payload_size = sizeof(av_dev_drift)
6277 - sizeof(av_dev_drift.get_param) - sizeof(av_dev_drift.hdr);
6278 av_dev_drift.get_param.port_id = q6audio_get_port_id(port);
6279 av_dev_drift.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6280 av_dev_drift.pdata.param_id = AFE_PARAM_ID_DEV_TIMING_STATS;
6281 av_dev_drift.pdata.param_size = sizeof(av_dev_drift.timing_stats);
6282 atomic_set(&this_afe.status, 0);
6283 atomic_set(&this_afe.state, 1);
6284 ret = apr_send_pkt(this_afe.apr, (uint32_t *)&av_dev_drift);
6285 if (ret < 0) {
6286 pr_err("%s: get param port 0x%x param id[0x%x] failed %d\n",
6287 __func__, port, av_dev_drift.get_param.param_id, ret);
6288 goto exit;
6289 }
6290
6291 ret = wait_event_timeout(this_afe.wait[index],
6292 (atomic_read(&this_afe.state) == 0),
6293 msecs_to_jiffies(TIMEOUT_MS));
6294 if (!ret) {
6295 pr_err("%s: wait_event timeout\n", __func__);
6296 ret = -EINVAL;
6297 goto exit;
6298 }
6299
6300 if (atomic_read(&this_afe.status) > 0) {
6301 pr_err("%s: config cmd failed [%s]\n",
6302 __func__, adsp_err_get_err_str(
6303 atomic_read(&this_afe.status)));
6304 ret = adsp_err_get_lnx_err_code(
6305 atomic_read(&this_afe.status));
6306 goto exit;
6307 }
6308
6309 memcpy(timing_stats, &this_afe.av_dev_drift_resp.timing_stats,
6310 sizeof(this_afe.av_dev_drift_resp.timing_stats));
6311 ret = 0;
6312exit:
6313 return ret;
6314}
6315
Banajit Goswami0530e2f2016-12-09 21:34:37 -08006316int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp)
6317{
6318 int ret = -EINVAL;
6319 int index = 0, port = SLIMBUS_4_TX;
6320
6321 if (!calib_resp) {
6322 pr_err("%s: Invalid params\n", __func__);
6323 goto fail_cmd;
6324 }
6325 if (this_afe.vi_tx_port != -1)
6326 port = this_afe.vi_tx_port;
6327
6328 ret = q6audio_validate_port(port);
6329 if (ret < 0) {
6330 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6331 ret = -EINVAL;
6332 goto fail_cmd;
6333 }
6334 index = q6audio_get_port_index(port);
Xiaoyu Ye38ae2252017-01-26 18:20:06 -08006335 if (index < 0 || index >= AFE_MAX_PORTS) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08006336 pr_err("%s: AFE port index[%d] invalid!\n",
6337 __func__, index);
6338 ret = -EINVAL;
6339 goto fail_cmd;
6340 }
6341 calib_resp->hdr.hdr_field =
6342 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6343 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6344 calib_resp->hdr.pkt_size = sizeof(*calib_resp);
6345 calib_resp->hdr.src_port = 0;
6346 calib_resp->hdr.dest_port = 0;
6347 calib_resp->hdr.token = index;
6348 calib_resp->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6349 calib_resp->get_param.mem_map_handle = 0;
6350 calib_resp->get_param.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
6351 calib_resp->get_param.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2;
6352 calib_resp->get_param.payload_address_lsw = 0;
6353 calib_resp->get_param.payload_address_msw = 0;
6354 calib_resp->get_param.payload_size = sizeof(*calib_resp)
6355 - sizeof(calib_resp->get_param) - sizeof(calib_resp->hdr);
6356 calib_resp->get_param.port_id = q6audio_get_port_id(port);
6357 calib_resp->pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
6358 calib_resp->pdata.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2;
6359 calib_resp->pdata.param_size = sizeof(calib_resp->res_cfg);
6360 atomic_set(&this_afe.status, 0);
6361 atomic_set(&this_afe.state, 1);
6362 ret = apr_send_pkt(this_afe.apr, (uint32_t *)calib_resp);
6363 if (ret < 0) {
6364 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
6365 __func__, port, calib_resp->get_param.param_id, ret);
6366 goto fail_cmd;
6367 }
6368 ret = wait_event_timeout(this_afe.wait[index],
6369 (atomic_read(&this_afe.state) == 0),
6370 msecs_to_jiffies(TIMEOUT_MS));
6371 if (!ret) {
6372 pr_err("%s: wait_event timeout\n", __func__);
6373 ret = -EINVAL;
6374 goto fail_cmd;
6375 }
6376 if (atomic_read(&this_afe.status) > 0) {
6377 pr_err("%s: config cmd failed [%s]\n",
6378 __func__, adsp_err_get_err_str(
6379 atomic_read(&this_afe.status)));
6380 ret = adsp_err_get_lnx_err_code(
6381 atomic_read(&this_afe.status));
6382 goto fail_cmd;
6383 }
6384 memcpy(&calib_resp->res_cfg, &this_afe.calib_data.res_cfg,
6385 sizeof(this_afe.calib_data.res_cfg));
6386 pr_info("%s: state %s resistance %d %d\n", __func__,
6387 fbsp_state[calib_resp->res_cfg.th_vi_ca_state],
6388 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1],
6389 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]);
6390 ret = 0;
6391fail_cmd:
6392 return ret;
6393}
6394
6395int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
6396 int l_ch, int r_ch, u32 enable)
6397{
6398 int ret = -EINVAL;
6399 union afe_spkr_prot_config prot_config;
6400 int index = 0;
6401
6402 if (!enable) {
6403 pr_debug("%s: Disable Feedback tx path", __func__);
6404 this_afe.vi_tx_port = -1;
6405 this_afe.vi_rx_port = -1;
6406 return 0;
6407 }
6408
6409 if ((q6audio_validate_port(src_port) < 0) ||
6410 (q6audio_validate_port(dst_port) < 0)) {
6411 pr_err("%s: invalid ports src 0x%x dst 0x%x",
6412 __func__, src_port, dst_port);
6413 goto fail_cmd;
6414 }
6415 if (!l_ch && !r_ch) {
6416 pr_err("%s: error ch values zero\n", __func__);
6417 goto fail_cmd;
6418 }
6419 pr_debug("%s: src_port 0x%x dst_port 0x%x l_ch %d r_ch %d\n",
6420 __func__, src_port, dst_port, l_ch, r_ch);
6421 memset(&prot_config, 0, sizeof(prot_config));
6422 prot_config.feedback_path_cfg.dst_portid =
6423 q6audio_get_port_id(dst_port);
6424 if (l_ch) {
6425 prot_config.feedback_path_cfg.chan_info[index++] = 1;
6426 prot_config.feedback_path_cfg.chan_info[index++] = 2;
6427 }
6428 if (r_ch) {
6429 prot_config.feedback_path_cfg.chan_info[index++] = 3;
6430 prot_config.feedback_path_cfg.chan_info[index++] = 4;
6431 }
6432 prot_config.feedback_path_cfg.num_channels = index;
6433 pr_debug("%s no of channels: %d\n", __func__, index);
6434 prot_config.feedback_path_cfg.minor_version = 1;
6435 ret = afe_spk_prot_prepare(src_port, dst_port,
6436 AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config);
6437fail_cmd:
6438 return ret;
6439}
6440
6441static int get_cal_type_index(int32_t cal_type)
6442{
6443 int ret = -EINVAL;
6444
6445 switch (cal_type) {
6446 case AFE_COMMON_RX_CAL_TYPE:
6447 ret = AFE_COMMON_RX_CAL;
6448 break;
6449 case AFE_COMMON_TX_CAL_TYPE:
6450 ret = AFE_COMMON_TX_CAL;
6451 break;
6452 case AFE_AANC_CAL_TYPE:
6453 ret = AFE_AANC_CAL;
6454 break;
6455 case AFE_HW_DELAY_CAL_TYPE:
6456 ret = AFE_HW_DELAY_CAL;
6457 break;
6458 case AFE_FB_SPKR_PROT_CAL_TYPE:
6459 ret = AFE_FB_SPKR_PROT_CAL;
6460 break;
6461 case AFE_SIDETONE_CAL_TYPE:
6462 ret = AFE_SIDETONE_CAL;
6463 break;
Siena Richardd83d83f2016-12-15 13:49:41 -08006464 case AFE_SIDETONE_IIR_CAL_TYPE:
6465 ret = AFE_SIDETONE_IIR_CAL;
6466 break;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08006467 case AFE_TOPOLOGY_CAL_TYPE:
6468 ret = AFE_TOPOLOGY_CAL;
6469 break;
6470 case AFE_CUST_TOPOLOGY_CAL_TYPE:
6471 ret = AFE_CUST_TOPOLOGY_CAL;
6472 break;
6473 default:
6474 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
6475 }
6476 return ret;
6477}
6478
6479int afe_alloc_cal(int32_t cal_type, size_t data_size,
6480 void *data)
6481{
6482 int ret = 0;
6483 int cal_index;
6484
6485 cal_index = get_cal_type_index(cal_type);
6486 pr_debug("%s: cal_type = %d cal_index = %d\n",
6487 __func__, cal_type, cal_index);
6488
6489 if (cal_index < 0) {
6490 pr_err("%s: could not get cal index %d!\n",
6491 __func__, cal_index);
6492 ret = -EINVAL;
6493 goto done;
6494 }
6495
6496 ret = cal_utils_alloc_cal(data_size, data,
6497 this_afe.cal_data[cal_index], 0, NULL);
6498 if (ret < 0) {
6499 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
6500 __func__, ret, cal_type);
6501 ret = -EINVAL;
6502 goto done;
6503 }
6504done:
6505 return ret;
6506}
6507
6508static int afe_dealloc_cal(int32_t cal_type, size_t data_size,
6509 void *data)
6510{
6511 int ret = 0;
6512 int cal_index;
6513
6514 pr_debug("%s:\n", __func__);
6515
6516 cal_index = get_cal_type_index(cal_type);
6517 if (cal_index < 0) {
6518 pr_err("%s: could not get cal index %d!\n",
6519 __func__, cal_index);
6520 ret = -EINVAL;
6521 goto done;
6522 }
6523
6524 ret = cal_utils_dealloc_cal(data_size, data,
6525 this_afe.cal_data[cal_index]);
6526 if (ret < 0) {
6527 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
6528 __func__, ret, cal_type);
6529 ret = -EINVAL;
6530 goto done;
6531 }
6532done:
6533 return ret;
6534}
6535
6536static int afe_set_cal(int32_t cal_type, size_t data_size,
6537 void *data)
6538{
6539 int ret = 0;
6540 int cal_index;
6541
6542 pr_debug("%s:\n", __func__);
6543
6544 cal_index = get_cal_type_index(cal_type);
6545 if (cal_index < 0) {
6546 pr_err("%s: could not get cal index %d!\n",
6547 __func__, cal_index);
6548 ret = -EINVAL;
6549 goto done;
6550 }
6551
6552 ret = cal_utils_set_cal(data_size, data,
6553 this_afe.cal_data[cal_index], 0, NULL);
6554 if (ret < 0) {
6555 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
6556 __func__, ret, cal_type);
6557 ret = -EINVAL;
6558 goto done;
6559 }
6560
6561 if (cal_index == AFE_CUST_TOPOLOGY_CAL) {
6562 mutex_lock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
6563 this_afe.set_custom_topology = 1;
6564 pr_debug("%s:[AFE_CUSTOM_TOPOLOGY] ret = %d, cal type = %d!\n",
6565 __func__, ret, cal_type);
6566 mutex_unlock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
6567 }
6568
6569done:
6570 return ret;
6571}
6572
6573static struct cal_block_data *afe_find_hw_delay_by_path(
6574 struct cal_type_data *cal_type, int path)
6575{
6576 struct list_head *ptr, *next;
6577 struct cal_block_data *cal_block = NULL;
6578
6579 pr_debug("%s:\n", __func__);
6580
6581 list_for_each_safe(ptr, next,
6582 &cal_type->cal_blocks) {
6583
6584 cal_block = list_entry(ptr,
6585 struct cal_block_data, list);
6586
6587 if (((struct audio_cal_info_hw_delay *)cal_block->cal_info)
6588 ->path == path) {
6589 return cal_block;
6590 }
6591 }
6592 return NULL;
6593}
6594
6595static int afe_get_cal_hw_delay(int32_t path,
6596 struct audio_cal_hw_delay_entry *entry)
6597{
6598 int ret = 0;
6599 int i;
6600 struct cal_block_data *cal_block = NULL;
6601 struct audio_cal_hw_delay_data *hw_delay_info = NULL;
6602
6603 pr_debug("%s:\n", __func__);
6604
6605 if (this_afe.cal_data[AFE_HW_DELAY_CAL] == NULL) {
6606 pr_err("%s: AFE_HW_DELAY_CAL not initialized\n", __func__);
6607 ret = -EINVAL;
6608 goto done;
6609 }
6610 if (entry == NULL) {
6611 pr_err("%s: entry is NULL\n", __func__);
6612 ret = -EINVAL;
6613 goto done;
6614 }
6615 if ((path >= MAX_PATH_TYPE) || (path < 0)) {
6616 pr_err("%s: bad path: %d\n",
6617 __func__, path);
6618 ret = -EINVAL;
6619 goto done;
6620 }
6621
6622 mutex_lock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
6623 cal_block = afe_find_hw_delay_by_path(
6624 this_afe.cal_data[AFE_HW_DELAY_CAL], path);
6625 if (cal_block == NULL)
6626 goto unlock;
6627
6628 hw_delay_info = &((struct audio_cal_info_hw_delay *)
6629 cal_block->cal_info)->data;
6630 if (hw_delay_info->num_entries > MAX_HW_DELAY_ENTRIES) {
6631 pr_err("%s: invalid num entries: %d\n",
6632 __func__, hw_delay_info->num_entries);
6633 ret = -EINVAL;
6634 goto unlock;
6635 }
6636
6637 for (i = 0; i < hw_delay_info->num_entries; i++) {
6638 if (hw_delay_info->entry[i].sample_rate ==
6639 entry->sample_rate) {
6640 entry->delay_usec = hw_delay_info->entry[i].delay_usec;
6641 break;
6642 }
6643 }
6644 if (i == hw_delay_info->num_entries) {
6645 pr_err("%s: Unable to find delay for sample rate %d\n",
6646 __func__, entry->sample_rate);
6647 ret = -EFAULT;
6648 goto unlock;
6649 }
6650 pr_debug("%s: Path = %d samplerate = %u usec = %u status %d\n",
6651 __func__, path, entry->sample_rate, entry->delay_usec, ret);
6652unlock:
6653 mutex_unlock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
6654done:
6655 return ret;
6656}
6657
6658static int afe_set_cal_sp_th_vi_ftm_cfg(int32_t cal_type, size_t data_size,
6659 void *data)
6660{
6661 int ret = 0;
6662 struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data;
6663
6664 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
6665 cal_data == NULL ||
6666 data_size != sizeof(*cal_data))
6667 goto done;
6668
6669 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
6670 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
6671 memcpy(&this_afe.th_ftm_cfg, &cal_data->cal_info,
6672 sizeof(this_afe.th_ftm_cfg));
6673 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
6674done:
6675 return ret;
6676}
6677
6678static int afe_set_cal_sp_ex_vi_ftm_cfg(int32_t cal_type, size_t data_size,
6679 void *data)
6680{
6681 int ret = 0;
6682 struct audio_cal_type_sp_ex_vi_ftm_cfg *cal_data = data;
6683
6684 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
6685 cal_data == NULL ||
6686 data_size != sizeof(*cal_data))
6687 goto done;
6688
6689 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
6690 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
6691 memcpy(&this_afe.ex_ftm_cfg, &cal_data->cal_info,
6692 sizeof(this_afe.ex_ftm_cfg));
6693 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
6694done:
6695 return ret;
6696}
6697
6698static int afe_set_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
6699 void *data)
6700{
6701 int ret = 0;
6702 struct audio_cal_type_fb_spk_prot_cfg *cal_data = data;
6703
6704 pr_debug("%s:\n", __func__);
6705
6706 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
6707 goto done;
6708 if (cal_data == NULL)
6709 goto done;
6710 if (data_size != sizeof(*cal_data))
6711 goto done;
6712
6713 if (cal_data->cal_info.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
6714 __pm_wakeup_event(&wl.ws, jiffies_to_msecs(WAKELOCK_TIMEOUT));
6715 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
6716 memcpy(&this_afe.prot_cfg, &cal_data->cal_info,
6717 sizeof(this_afe.prot_cfg));
Banajit Goswami0530e2f2016-12-09 21:34:37 -08006718 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
6719done:
6720 return ret;
6721}
6722
6723static int afe_get_cal_sp_th_vi_ftm_param(int32_t cal_type, size_t data_size,
6724 void *data)
6725{
6726 int i, ret = 0;
6727 struct audio_cal_type_sp_th_vi_param *cal_data = data;
6728 struct afe_sp_th_vi_get_param th_vi;
6729
6730 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
6731 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
6732 cal_data == NULL ||
6733 data_size != sizeof(*cal_data))
6734 goto done;
6735
6736 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
6737 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
6738 cal_data->cal_info.status[i] = -EINVAL;
6739 cal_data->cal_info.r_dc_q24[i] = -1;
6740 cal_data->cal_info.temp_q22[i] = -1;
6741 }
6742 if (!afe_get_sp_th_vi_ftm_data(&th_vi)) {
6743 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
6744 pr_debug("%s: ftm param status = %d\n",
6745 __func__, th_vi.param.status[i]);
6746 if (th_vi.param.status[i] == FBSP_IN_PROGRESS) {
6747 cal_data->cal_info.status[i] = -EAGAIN;
6748 } else if (th_vi.param.status[i] == FBSP_SUCCESS) {
6749 cal_data->cal_info.status[i] = 0;
6750 cal_data->cal_info.r_dc_q24[i] =
6751 th_vi.param.dc_res_q24[i];
6752 cal_data->cal_info.temp_q22[i] =
6753 th_vi.param.temp_q22[i];
6754 }
6755 }
6756 }
6757 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
6758done:
6759 return ret;
6760}
6761
6762static int afe_get_cal_sp_ex_vi_ftm_param(int32_t cal_type, size_t data_size,
6763 void *data)
6764{
6765 int i, ret = 0;
6766 struct audio_cal_type_sp_ex_vi_param *cal_data = data;
6767 struct afe_sp_ex_vi_get_param ex_vi;
6768
6769 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
6770 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
6771 cal_data == NULL ||
6772 data_size != sizeof(*cal_data))
6773 goto done;
6774
6775 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
6776 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
6777 cal_data->cal_info.status[i] = -EINVAL;
6778 cal_data->cal_info.freq_q20[i] = -1;
6779 cal_data->cal_info.resis_q24[i] = -1;
6780 cal_data->cal_info.qmct_q24[i] = -1;
6781 }
6782 if (!afe_get_sp_ex_vi_ftm_data(&ex_vi)) {
6783 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
6784 pr_debug("%s: ftm param status = %d\n",
6785 __func__, ex_vi.param.status[i]);
6786 if (ex_vi.param.status[i] == FBSP_IN_PROGRESS) {
6787 cal_data->cal_info.status[i] = -EAGAIN;
6788 } else if (ex_vi.param.status[i] == FBSP_SUCCESS) {
6789 cal_data->cal_info.status[i] = 0;
6790 cal_data->cal_info.freq_q20[i] =
6791 ex_vi.param.freq_q20[i];
6792 cal_data->cal_info.resis_q24[i] =
6793 ex_vi.param.resis_q24[i];
6794 cal_data->cal_info.qmct_q24[i] =
6795 ex_vi.param.qmct_q24[i];
6796 }
6797 }
6798 }
6799 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
6800done:
6801 return ret;
6802}
6803
6804static int afe_get_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
6805 void *data)
6806{
6807 int ret = 0;
6808 struct audio_cal_type_fb_spk_prot_status *cal_data = data;
6809 struct afe_spkr_prot_get_vi_calib calib_resp;
6810
6811 pr_debug("%s:\n", __func__);
6812
6813 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
6814 goto done;
6815 if (cal_data == NULL)
6816 goto done;
6817 if (data_size != sizeof(*cal_data))
6818 goto done;
6819
6820 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
6821 if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATED) {
6822 cal_data->cal_info.r0[SP_V2_SPKR_1] =
6823 this_afe.prot_cfg.r0[SP_V2_SPKR_1];
6824 cal_data->cal_info.r0[SP_V2_SPKR_2] =
6825 this_afe.prot_cfg.r0[SP_V2_SPKR_2];
6826 cal_data->cal_info.status = 0;
6827 } else if (this_afe.prot_cfg.mode ==
6828 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
6829 /*Call AFE to query the status*/
6830 cal_data->cal_info.status = -EINVAL;
6831 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
6832 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
6833 if (!afe_spk_prot_get_calib_data(&calib_resp)) {
6834 if (calib_resp.res_cfg.th_vi_ca_state ==
6835 FBSP_IN_PROGRESS)
6836 cal_data->cal_info.status = -EAGAIN;
6837 else if (calib_resp.res_cfg.th_vi_ca_state ==
6838 FBSP_SUCCESS) {
6839 cal_data->cal_info.status = 0;
6840 cal_data->cal_info.r0[SP_V2_SPKR_1] =
6841 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_1];
6842 cal_data->cal_info.r0[SP_V2_SPKR_2] =
6843 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_2];
6844 }
6845 }
6846 if (!cal_data->cal_info.status) {
6847 this_afe.prot_cfg.mode =
6848 MSM_SPKR_PROT_CALIBRATED;
6849 this_afe.prot_cfg.r0[SP_V2_SPKR_1] =
6850 cal_data->cal_info.r0[SP_V2_SPKR_1];
6851 this_afe.prot_cfg.r0[SP_V2_SPKR_2] =
6852 cal_data->cal_info.r0[SP_V2_SPKR_2];
6853 }
6854 } else {
6855 /*Indicates calibration data is invalid*/
6856 cal_data->cal_info.status = -EINVAL;
6857 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
6858 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
6859 }
Banajit Goswami0530e2f2016-12-09 21:34:37 -08006860 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
6861 __pm_relax(&wl.ws);
6862done:
6863 return ret;
6864}
6865
6866static int afe_map_cal_data(int32_t cal_type,
6867 struct cal_block_data *cal_block)
6868{
6869 int ret = 0;
6870 int cal_index;
6871
6872 pr_debug("%s:\n", __func__);
6873
6874 cal_index = get_cal_type_index(cal_type);
6875 if (cal_index < 0) {
6876 pr_err("%s: could not get cal index %d!\n",
6877 __func__, cal_index);
6878 ret = -EINVAL;
6879 goto done;
6880 }
6881
6882
Rohit Kumara888c5c2016-11-28 12:23:18 +05306883 mutex_lock(&this_afe.afe_cmd_lock);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08006884 atomic_set(&this_afe.mem_map_cal_index, cal_index);
6885 ret = afe_cmd_memory_map(cal_block->cal_data.paddr,
6886 cal_block->map_data.map_size);
6887 atomic_set(&this_afe.mem_map_cal_index, -1);
6888 if (ret < 0) {
6889 pr_err("%s: mmap did not work! size = %zd ret %d\n",
6890 __func__,
6891 cal_block->map_data.map_size, ret);
6892 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
6893 __func__,
6894 &cal_block->cal_data.paddr,
6895 cal_block->map_data.map_size);
Rohit Kumara888c5c2016-11-28 12:23:18 +05306896 mutex_unlock(&this_afe.afe_cmd_lock);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08006897 goto done;
6898 }
6899 cal_block->map_data.q6map_handle = atomic_read(&this_afe.
6900 mem_map_cal_handles[cal_index]);
Rohit Kumara888c5c2016-11-28 12:23:18 +05306901 mutex_unlock(&this_afe.afe_cmd_lock);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08006902done:
6903 return ret;
6904}
6905
6906static int afe_unmap_cal_data(int32_t cal_type,
6907 struct cal_block_data *cal_block)
6908{
6909 int ret = 0;
6910 int cal_index;
6911
6912 pr_debug("%s:\n", __func__);
6913
6914 cal_index = get_cal_type_index(cal_type);
6915 if (cal_index < 0) {
6916 pr_err("%s: could not get cal index %d!\n",
6917 __func__, cal_index);
6918 ret = -EINVAL;
6919 goto done;
6920 }
6921
6922 if (cal_block == NULL) {
6923 pr_err("%s: Cal block is NULL!\n",
6924 __func__);
6925 goto done;
6926 }
6927
6928 if (cal_block->map_data.q6map_handle == 0) {
6929 pr_err("%s: Map handle is NULL, nothing to unmap\n",
6930 __func__);
6931 goto done;
6932 }
6933
6934 atomic_set(&this_afe.mem_map_cal_handles[cal_index],
6935 cal_block->map_data.q6map_handle);
6936 atomic_set(&this_afe.mem_map_cal_index, cal_index);
6937 ret = afe_cmd_memory_unmap_nowait(
6938 cal_block->map_data.q6map_handle);
6939 atomic_set(&this_afe.mem_map_cal_index, -1);
6940 if (ret < 0) {
6941 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
6942 __func__, cal_index, ret);
6943 }
6944 cal_block->map_data.q6map_handle = 0;
6945done:
6946 return ret;
6947}
6948
6949static void afe_delete_cal_data(void)
6950{
6951 pr_debug("%s:\n", __func__);
6952
6953 cal_utils_destroy_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data);
6954}
6955
6956static int afe_init_cal_data(void)
6957{
6958 int ret = 0;
6959 struct cal_type_info cal_type_info[] = {
6960 {{AFE_COMMON_RX_CAL_TYPE,
6961 {afe_alloc_cal, afe_dealloc_cal, NULL,
6962 afe_set_cal, NULL, NULL} },
6963 {afe_map_cal_data, afe_unmap_cal_data,
6964 cal_utils_match_buf_num} },
6965
6966 {{AFE_COMMON_TX_CAL_TYPE,
6967 {afe_alloc_cal, afe_dealloc_cal, NULL,
6968 afe_set_cal, NULL, NULL} },
6969 {afe_map_cal_data, afe_unmap_cal_data,
6970 cal_utils_match_buf_num} },
6971
6972 {{AFE_AANC_CAL_TYPE,
6973 {afe_alloc_cal, afe_dealloc_cal, NULL,
6974 afe_set_cal, NULL, NULL} },
6975 {afe_map_cal_data, afe_unmap_cal_data,
6976 cal_utils_match_buf_num} },
6977
6978 {{AFE_FB_SPKR_PROT_CAL_TYPE,
6979 {NULL, NULL, NULL, afe_set_cal_fb_spkr_prot,
6980 afe_get_cal_fb_spkr_prot, NULL} },
6981 {NULL, NULL, cal_utils_match_buf_num} },
6982
6983 {{AFE_HW_DELAY_CAL_TYPE,
6984 {NULL, NULL, NULL,
6985 afe_set_cal, NULL, NULL} },
6986 {NULL, NULL, cal_utils_match_buf_num} },
6987
6988 {{AFE_SIDETONE_CAL_TYPE,
6989 {NULL, NULL, NULL,
6990 afe_set_cal, NULL, NULL} },
6991 {NULL, NULL, cal_utils_match_buf_num} },
6992
Siena Richardd83d83f2016-12-15 13:49:41 -08006993 {{AFE_SIDETONE_IIR_CAL_TYPE,
6994 {NULL, NULL, NULL,
6995 afe_set_cal, NULL, NULL} },
6996 {NULL, NULL, cal_utils_match_buf_num} },
6997
Banajit Goswami0530e2f2016-12-09 21:34:37 -08006998 {{AFE_TOPOLOGY_CAL_TYPE,
6999 {NULL, NULL, NULL,
7000 afe_set_cal, NULL, NULL} },
7001 {NULL, NULL,
7002 cal_utils_match_buf_num} },
7003
7004 {{AFE_CUST_TOPOLOGY_CAL_TYPE,
7005 {afe_alloc_cal, afe_dealloc_cal, NULL,
7006 afe_set_cal, NULL, NULL} },
7007 {afe_map_cal_data, afe_unmap_cal_data,
7008 cal_utils_match_buf_num} },
7009
7010 {{AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE,
7011 {NULL, NULL, NULL, afe_set_cal_sp_th_vi_ftm_cfg,
7012 afe_get_cal_sp_th_vi_ftm_param, NULL} },
7013 {NULL, NULL, cal_utils_match_buf_num} },
7014
7015 {{AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE,
7016 {NULL, NULL, NULL, afe_set_cal_sp_ex_vi_ftm_cfg,
7017 afe_get_cal_sp_ex_vi_ftm_param, NULL} },
7018 {NULL, NULL, cal_utils_match_buf_num} },
7019 };
7020 pr_debug("%s:\n", __func__);
7021
7022 ret = cal_utils_create_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data,
7023 cal_type_info);
7024 if (ret < 0) {
7025 pr_err("%s: could not create cal type! %d\n",
7026 __func__, ret);
7027 ret = -EINVAL;
7028 goto err;
7029 }
7030
7031 return ret;
7032err:
7033 afe_delete_cal_data();
7034 return ret;
7035}
7036
7037int afe_map_rtac_block(struct rtac_cal_block_data *cal_block)
7038{
7039 int result = 0;
7040
7041 pr_debug("%s:\n", __func__);
7042
7043 if (cal_block == NULL) {
7044 pr_err("%s: cal_block is NULL!\n",
7045 __func__);
7046 result = -EINVAL;
7047 goto done;
7048 }
7049
7050 if (cal_block->cal_data.paddr == 0) {
7051 pr_debug("%s: No address to map!\n",
7052 __func__);
7053 result = -EINVAL;
7054 goto done;
7055 }
7056
7057 if (cal_block->map_data.map_size == 0) {
7058 pr_debug("%s: map size is 0!\n",
7059 __func__);
7060 result = -EINVAL;
7061 goto done;
7062 }
7063
7064 result = afe_cmd_memory_map(cal_block->cal_data.paddr,
7065 cal_block->map_data.map_size);
7066 if (result < 0) {
7067 pr_err("%s: afe_cmd_memory_map failed for addr = 0x%pK, size = %d, err %d\n",
7068 __func__, &cal_block->cal_data.paddr,
7069 cal_block->map_data.map_size, result);
7070 return result;
7071 }
7072 cal_block->map_data.map_handle = this_afe.mmap_handle;
7073
7074done:
7075 return result;
7076}
7077
7078int afe_unmap_rtac_block(uint32_t *mem_map_handle)
7079{
7080 int result = 0;
7081
7082 pr_debug("%s:\n", __func__);
7083
7084 if (mem_map_handle == NULL) {
7085 pr_err("%s: Map handle is NULL, nothing to unmap\n",
7086 __func__);
7087 goto done;
7088 }
7089
7090 if (*mem_map_handle == 0) {
7091 pr_debug("%s: Map handle is 0, nothing to unmap\n",
7092 __func__);
7093 goto done;
7094 }
7095
7096 result = afe_cmd_memory_unmap(*mem_map_handle);
7097 if (result) {
7098 pr_err("%s: AFE memory unmap failed %d, handle 0x%x\n",
7099 __func__, result, *mem_map_handle);
7100 goto done;
7101 } else {
7102 *mem_map_handle = 0;
7103 }
7104
7105done:
7106 return result;
7107}
7108
7109static int __init afe_init(void)
7110{
7111 int i = 0, ret;
7112
7113 atomic_set(&this_afe.state, 0);
7114 atomic_set(&this_afe.status, 0);
7115 atomic_set(&this_afe.mem_map_cal_index, -1);
7116 this_afe.apr = NULL;
7117 this_afe.dtmf_gen_rx_portid = -1;
7118 this_afe.mmap_handle = 0;
7119 this_afe.vi_tx_port = -1;
7120 this_afe.vi_rx_port = -1;
7121 this_afe.prot_cfg.mode = MSM_SPKR_PROT_DISABLED;
7122 this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
7123 this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
7124 mutex_init(&this_afe.afe_cmd_lock);
7125 for (i = 0; i < AFE_MAX_PORTS; i++) {
7126 this_afe.afe_cal_mode[i] = AFE_CAL_MODE_DEFAULT;
Siena Richard23364c92017-01-11 16:20:55 -08007127 this_afe.afe_sample_rates[i] = 0;
7128 this_afe.dev_acdb_id[i] = 0;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08007129 init_waitqueue_head(&this_afe.wait[i]);
7130 }
7131 wakeup_source_init(&wl.ws, "spkr-prot");
7132 ret = afe_init_cal_data();
7133 if (ret)
7134 pr_err("%s: could not init cal data! %d\n", __func__, ret);
7135
7136 config_debug_fs_init();
7137 return 0;
7138}
7139
7140static void __exit afe_exit(void)
7141{
7142 afe_delete_cal_data();
7143
7144 config_debug_fs_exit();
7145 mutex_destroy(&this_afe.afe_cmd_lock);
7146 wakeup_source_trash(&wl.ws);
7147}
7148
7149device_initcall(afe_init);
7150__exitcall(afe_exit);