blob: 87b2c58ec6f342645ca49db072f990735c7c10ba [file] [log] [blame]
Xiaojun Sang1cf1f1b2019-01-15 16:49:02 +08001/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302 *
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>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053018#include <linux/jiffies.h>
19#include <linux/sched.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053020#include <linux/delay.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053021#include <dsp/msm_audio_ion.h>
22#include <dsp/apr_audio-v2.h>
23#include <dsp/audio_cal_utils.h>
24#include <dsp/q6afe-v2.h>
25#include <dsp/q6audio-v2.h>
26#include <ipc/apr_tal.h>
27#include "adsp_err.h"
Raja Mallike1b2f792018-06-01 13:17:36 +053028#include <dsp/q6core.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053029
30#define WAKELOCK_TIMEOUT 5000
31enum {
32 AFE_COMMON_RX_CAL = 0,
33 AFE_COMMON_TX_CAL,
Aditya Bavanari3889b4a2017-11-21 19:52:26 +053034 AFE_LSM_TX_CAL,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053035 AFE_AANC_CAL,
36 AFE_FB_SPKR_PROT_CAL,
37 AFE_HW_DELAY_CAL,
38 AFE_SIDETONE_CAL,
39 AFE_SIDETONE_IIR_CAL,
40 AFE_TOPOLOGY_CAL,
Aditya Bavanari3889b4a2017-11-21 19:52:26 +053041 AFE_LSM_TOPOLOGY_CAL,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053042 AFE_CUST_TOPOLOGY_CAL,
43 AFE_FB_SPKR_PROT_TH_VI_CAL,
44 AFE_FB_SPKR_PROT_EX_VI_CAL,
45 MAX_AFE_CAL_TYPES
46};
47
48enum fbsp_state {
49 FBSP_INCORRECT_OP_MODE,
50 FBSP_INACTIVE,
51 FBSP_WARMUP,
52 FBSP_IN_PROGRESS,
53 FBSP_SUCCESS,
54 FBSP_FAILED,
55 MAX_FBSP_STATE
56};
57
58static char fbsp_state[MAX_FBSP_STATE][50] = {
59 [FBSP_INCORRECT_OP_MODE] = "incorrect operation mode",
60 [FBSP_INACTIVE] = "port not started",
61 [FBSP_WARMUP] = "waiting for warmup",
62 [FBSP_IN_PROGRESS] = "in progress state",
63 [FBSP_SUCCESS] = "success",
64 [FBSP_FAILED] = "failed"
65};
66
67enum {
68 USE_CALIBRATED_R0TO,
69 USE_SAFE_R0TO
70};
71
72enum {
73 QUICK_CALIB_DISABLE,
74 QUICK_CALIB_ENABLE
75};
76
77enum {
78 Q6AFE_MSM_SPKR_PROCESSING = 0,
79 Q6AFE_MSM_SPKR_CALIBRATION,
80 Q6AFE_MSM_SPKR_FTM_MODE
81};
82
83struct wlock {
84 struct wakeup_source ws;
85};
86
87static struct wlock wl;
88
89struct afe_ctl {
90 void *apr;
91 atomic_t state;
92 atomic_t status;
93 wait_queue_head_t wait[AFE_MAX_PORTS];
94 struct task_struct *task;
95 void (*tx_cb)(uint32_t opcode,
96 uint32_t token, uint32_t *payload, void *priv);
97 void (*rx_cb)(uint32_t opcode,
98 uint32_t token, uint32_t *payload, void *priv);
99 void *tx_private_data;
100 void *rx_private_data;
101 uint32_t mmap_handle;
102
103 int topology[AFE_MAX_PORTS];
104 struct cal_type_data *cal_data[MAX_AFE_CAL_TYPES];
105
106 atomic_t mem_map_cal_handles[MAX_AFE_CAL_TYPES];
107 atomic_t mem_map_cal_index;
108 u32 afe_cal_mode[AFE_MAX_PORTS];
109
110 u16 dtmf_gen_rx_portid;
111 struct audio_cal_info_spk_prot_cfg prot_cfg;
112 struct afe_spkr_prot_calib_get_resp calib_data;
113 struct audio_cal_info_sp_th_vi_ftm_cfg th_ftm_cfg;
114 struct audio_cal_info_sp_ex_vi_ftm_cfg ex_ftm_cfg;
115 struct afe_sp_th_vi_get_param_resp th_vi_resp;
116 struct afe_sp_ex_vi_get_param_resp ex_vi_resp;
117 struct afe_av_dev_drift_get_param_resp av_dev_drift_resp;
118 int vi_tx_port;
119 int vi_rx_port;
120 uint32_t afe_sample_rates[AFE_MAX_PORTS];
121 struct aanc_data aanc_info;
122 struct mutex afe_cmd_lock;
123 int set_custom_topology;
124 int dev_acdb_id[AFE_MAX_PORTS];
125 routing_cb rt_cb;
126};
127
128static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
129static unsigned long afe_configured_cmd;
130
131static struct afe_ctl this_afe;
132
133#define TIMEOUT_MS 1000
134#define Q6AFE_MAX_VOLUME 0x3FFF
Haynes Mathew George7ed9b512018-02-28 18:18:09 -0800135#define HS_USB_INTERVAL_US 125
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530136
137static int pcm_afe_instance[2];
138static int proxy_afe_instance[2];
139bool afe_close_done[2] = {true, true};
140
141#define SIZEOF_CFG_CMD(y) \
142 (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
143
144static int afe_get_cal_hw_delay(int32_t path,
145 struct audio_cal_hw_delay_entry *entry);
146static int remap_cal_data(struct cal_block_data *cal_block, int cal_index);
147
148int afe_get_topology(int port_id)
149{
150 int topology;
151 int port_index = afe_get_port_index(port_id);
152
153 if ((port_index < 0) || (port_index >= AFE_MAX_PORTS)) {
154 pr_err("%s: Invalid port index %d\n", __func__, port_index);
155 topology = -EINVAL;
156 goto done;
157 }
158
159 topology = this_afe.topology[port_index];
160done:
161 return topology;
162}
163
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530164/**
165 * afe_set_aanc_info -
166 * Update AFE AANC info
167 *
168 * @q6_aanc_info: AFE AANC info params
169 *
170 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530171void afe_set_aanc_info(struct aanc_data *q6_aanc_info)
172{
173 this_afe.aanc_info.aanc_active = q6_aanc_info->aanc_active;
174 this_afe.aanc_info.aanc_rx_port = q6_aanc_info->aanc_rx_port;
175 this_afe.aanc_info.aanc_tx_port = q6_aanc_info->aanc_tx_port;
176
177 pr_debug("%s: aanc active is %d rx port is 0x%x, tx port is 0x%x\n",
178 __func__,
179 this_afe.aanc_info.aanc_active,
180 this_afe.aanc_info.aanc_rx_port,
181 this_afe.aanc_info.aanc_tx_port);
182}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530183EXPORT_SYMBOL(afe_set_aanc_info);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530184
185static void afe_callback_debug_print(struct apr_client_data *data)
186{
187 uint32_t *payload;
188
189 payload = data->payload;
190
191 if (data->payload_size >= 8)
192 pr_debug("%s: code = 0x%x PL#0[0x%x], PL#1[0x%x], size = %d\n",
193 __func__, data->opcode, payload[0], payload[1],
194 data->payload_size);
195 else if (data->payload_size >= 4)
196 pr_debug("%s: code = 0x%x PL#0[0x%x], size = %d\n",
197 __func__, data->opcode, payload[0],
198 data->payload_size);
199 else
200 pr_debug("%s: code = 0x%x, size = %d\n",
201 __func__, data->opcode, data->payload_size);
202}
203
204static void av_dev_drift_afe_cb_handler(uint32_t *payload,
205 uint32_t payload_size)
206{
207 u32 param_id;
208 struct afe_av_dev_drift_get_param_resp *resp =
209 (struct afe_av_dev_drift_get_param_resp *) payload;
210
211 if (!(&(resp->pdata))) {
212 pr_err("%s: Error: resp pdata is NULL\n", __func__);
213 return;
214 }
215
216 param_id = resp->pdata.param_id;
217 if (param_id == AFE_PARAM_ID_DEV_TIMING_STATS) {
218 if (payload_size < sizeof(this_afe.av_dev_drift_resp)) {
219 pr_err("%s: Error: received size %d, resp size %zu\n",
220 __func__, payload_size,
221 sizeof(this_afe.av_dev_drift_resp));
222 return;
223 }
224 memcpy(&this_afe.av_dev_drift_resp, payload,
225 sizeof(this_afe.av_dev_drift_resp));
226 if (!this_afe.av_dev_drift_resp.status) {
227 atomic_set(&this_afe.state, 0);
228 } else {
229 pr_debug("%s: av_dev_drift_resp status: %d", __func__,
230 this_afe.av_dev_drift_resp.status);
231 atomic_set(&this_afe.state, -1);
232 }
233 }
234}
235
236static int32_t sp_make_afe_callback(uint32_t *payload, uint32_t payload_size)
237{
238 u32 param_id;
239 struct afe_spkr_prot_calib_get_resp *resp =
240 (struct afe_spkr_prot_calib_get_resp *) payload;
241
242 if (!(&(resp->pdata))) {
243 pr_err("%s: Error: resp pdata is NULL\n", __func__);
244 return -EINVAL;
245 }
246
247 param_id = resp->pdata.param_id;
248 if (param_id == AFE_PARAM_ID_CALIB_RES_CFG_V2) {
249 if (payload_size < sizeof(this_afe.calib_data)) {
250 pr_err("%s: Error: received size %d, calib_data size %zu\n",
251 __func__, payload_size,
252 sizeof(this_afe.calib_data));
253 return -EINVAL;
254 }
255 memcpy(&this_afe.calib_data, payload,
256 sizeof(this_afe.calib_data));
257 if (!this_afe.calib_data.status) {
258 atomic_set(&this_afe.state, 0);
259 } else {
260 pr_debug("%s: calib resp status: %d", __func__,
261 this_afe.calib_data.status);
262 atomic_set(&this_afe.state, -1);
263 }
264 }
265 if (param_id == AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS) {
266 if (payload_size < sizeof(this_afe.th_vi_resp)) {
267 pr_err("%s: Error: received size %d, th_vi_resp size %zu\n",
268 __func__, payload_size,
269 sizeof(this_afe.th_vi_resp));
270 return -EINVAL;
271 }
272 memcpy(&this_afe.th_vi_resp, payload,
273 sizeof(this_afe.th_vi_resp));
274 if (!this_afe.th_vi_resp.status) {
275 atomic_set(&this_afe.state, 0);
276 } else {
277 pr_debug("%s: th vi resp status: %d", __func__,
278 this_afe.th_vi_resp.status);
279 atomic_set(&this_afe.state, -1);
280 }
281 }
282 if (param_id == AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS) {
283 if (payload_size < sizeof(this_afe.ex_vi_resp)) {
284 pr_err("%s: Error: received size %d, ex_vi_resp size %zu\n",
285 __func__, payload_size,
286 sizeof(this_afe.ex_vi_resp));
287 return -EINVAL;
288 }
289 memcpy(&this_afe.ex_vi_resp, payload,
290 sizeof(this_afe.ex_vi_resp));
291 if (!this_afe.ex_vi_resp.status) {
292 atomic_set(&this_afe.state, 0);
293 } else {
294 pr_debug("%s: ex vi resp status: %d", __func__,
295 this_afe.ex_vi_resp.status);
296 atomic_set(&this_afe.state, -1);
297 }
298 }
299
300 return 0;
301}
302
Xiaojun Sang1cf1f1b2019-01-15 16:49:02 +0800303static bool afe_token_is_valid(uint32_t token)
304{
305 if (token >= AFE_MAX_PORTS) {
306 pr_err("%s: token %d is invalid.\n", __func__, token);
307 return false;
308 }
309 return true;
310}
311
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530312static int32_t afe_callback(struct apr_client_data *data, void *priv)
313{
314 if (!data) {
315 pr_err("%s: Invalid param data\n", __func__);
316 return -EINVAL;
317 }
318 if (data->opcode == RESET_EVENTS) {
319 pr_debug("%s: reset event = %d %d apr[%pK]\n",
320 __func__,
321 data->reset_event, data->reset_proc, this_afe.apr);
322
323 cal_utils_clear_cal_block_q6maps(MAX_AFE_CAL_TYPES,
324 this_afe.cal_data);
325
326 /* Reset the custom topology mode: to resend again to AFE. */
327 mutex_lock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
328 this_afe.set_custom_topology = 1;
329 mutex_unlock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
330 rtac_clear_mapping(AFE_RTAC_CAL);
331
332 if (this_afe.apr) {
333 apr_reset(this_afe.apr);
334 atomic_set(&this_afe.state, 0);
335 this_afe.apr = NULL;
336 rtac_set_afe_handle(this_afe.apr);
337 }
338 /* send info to user */
339 if (this_afe.task == NULL)
340 this_afe.task = current;
341 pr_debug("%s: task_name = %s pid = %d\n",
342 __func__,
343 this_afe.task->comm, this_afe.task->pid);
344
345 /*
346 * Pass reset events to proxy driver, if cb is registered
347 */
348 if (this_afe.tx_cb) {
349 this_afe.tx_cb(data->opcode, data->token,
350 data->payload,
351 this_afe.tx_private_data);
352 this_afe.tx_cb = NULL;
353 }
354 if (this_afe.rx_cb) {
355 this_afe.rx_cb(data->opcode, data->token,
356 data->payload,
357 this_afe.rx_private_data);
358 this_afe.rx_cb = NULL;
359 }
360
361 return 0;
362 }
363 afe_callback_debug_print(data);
364 if (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V2) {
365 uint32_t *payload = data->payload;
366
367 if (!payload || (data->token >= AFE_MAX_PORTS)) {
368 pr_err("%s: Error: size %d payload %pK token %d\n",
369 __func__, data->payload_size,
370 payload, data->token);
371 return -EINVAL;
372 }
373
Karthikeyan Mani95376082019-01-18 16:50:58 -0800374 if (rtac_make_afe_callback(data->payload,
375 data->payload_size))
376 return 0;
377
378 if (data->payload_size < 3 * sizeof(uint32_t)) {
379 pr_err("%s: Error: size %d is less than expected\n",
380 __func__, data->payload_size);
381 return -EINVAL;
382 }
383
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530384 if (payload[2] == AFE_PARAM_ID_DEV_TIMING_STATS) {
385 av_dev_drift_afe_cb_handler(data->payload,
386 data->payload_size);
387 } else {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530388 if (sp_make_afe_callback(data->payload,
389 data->payload_size))
390 return -EINVAL;
391 }
Xiaojun Sang1cf1f1b2019-01-15 16:49:02 +0800392 if (afe_token_is_valid(data->token))
393 wake_up(&this_afe.wait[data->token]);
394 else
395 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530396 } else if (data->payload_size) {
397 uint32_t *payload;
398 uint16_t port_id = 0;
399
400 payload = data->payload;
401 if (data->opcode == APR_BASIC_RSP_RESULT) {
Karthikeyan Mani95376082019-01-18 16:50:58 -0800402 if (data->payload_size < (2 * sizeof(uint32_t))) {
403 pr_err("%s: Error: size %d is less than expected\n",
404 __func__, data->payload_size);
405 return -EINVAL;
406 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530407 pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x token=%d\n",
408 __func__, data->opcode,
409 payload[0], payload[1], data->token);
410 /* payload[1] contains the error status for response */
411 if (payload[1] != 0) {
412 atomic_set(&this_afe.status, payload[1]);
413 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
414 __func__, payload[0], payload[1]);
415 }
416 switch (payload[0]) {
417 case AFE_PORT_CMD_SET_PARAM_V2:
418 if (rtac_make_afe_callback(payload,
419 data->payload_size))
420 return 0;
421 case AFE_PORT_CMD_DEVICE_STOP:
422 case AFE_PORT_CMD_DEVICE_START:
423 case AFE_PSEUDOPORT_CMD_START:
424 case AFE_PSEUDOPORT_CMD_STOP:
425 case AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS:
426 case AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS:
427 case AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER:
428 case AFE_PORTS_CMD_DTMF_CTL:
429 case AFE_SVC_CMD_SET_PARAM:
430 atomic_set(&this_afe.state, 0);
Xiaojun Sang1cf1f1b2019-01-15 16:49:02 +0800431 if (afe_token_is_valid(data->token))
432 wake_up(&this_afe.wait[data->token]);
433 else
434 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530435 break;
436 case AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER:
437 break;
438 case AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2:
439 port_id = RT_PROXY_PORT_001_TX;
440 break;
441 case AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2:
442 port_id = RT_PROXY_PORT_001_RX;
443 break;
444 case AFE_CMD_ADD_TOPOLOGIES:
445 atomic_set(&this_afe.state, 0);
Xiaojun Sang1cf1f1b2019-01-15 16:49:02 +0800446 if (afe_token_is_valid(data->token))
447 wake_up(&this_afe.wait[data->token]);
448 else
449 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530450 pr_debug("%s: AFE_CMD_ADD_TOPOLOGIES cmd 0x%x\n",
451 __func__, payload[1]);
452 break;
453 default:
454 pr_err("%s: Unknown cmd 0x%x\n", __func__,
455 payload[0]);
456 break;
457 }
458 } else if (data->opcode ==
459 AFE_SERVICE_CMDRSP_SHARED_MEM_MAP_REGIONS) {
460 pr_debug("%s: mmap_handle: 0x%x, cal index %d\n",
461 __func__, payload[0],
462 atomic_read(&this_afe.mem_map_cal_index));
463 if (atomic_read(&this_afe.mem_map_cal_index) != -1)
464 atomic_set(&this_afe.mem_map_cal_handles[
465 atomic_read(
466 &this_afe.mem_map_cal_index)],
467 (uint32_t)payload[0]);
468 else
469 this_afe.mmap_handle = payload[0];
470 atomic_set(&this_afe.state, 0);
Xiaojun Sang1cf1f1b2019-01-15 16:49:02 +0800471 if (afe_token_is_valid(data->token))
472 wake_up(&this_afe.wait[data->token]);
473 else
474 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530475 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
476 port_id = (uint16_t)(0x0000FFFF & payload[0]);
477 }
478 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
479 switch (port_id) {
480 case RT_PROXY_PORT_001_TX: {
481 if (this_afe.tx_cb) {
482 this_afe.tx_cb(data->opcode, data->token,
483 data->payload,
484 this_afe.tx_private_data);
485 }
486 break;
487 }
488 case RT_PROXY_PORT_001_RX: {
489 if (this_afe.rx_cb) {
490 this_afe.rx_cb(data->opcode, data->token,
491 data->payload,
492 this_afe.rx_private_data);
493 }
494 break;
495 }
496 default:
497 pr_debug("%s: default case 0x%x\n", __func__, port_id);
498 break;
499 }
500 }
501 return 0;
502}
503
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530504/**
505 * afe_get_port_type -
506 * Retrieve AFE port type whether RX or TX
507 *
508 * @port_id: AFE Port ID number
509 *
510 * Returns RX/TX type on success or -EINVAL on failure.
511 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530512int afe_get_port_type(u16 port_id)
513{
514 int ret;
515
516 switch (port_id) {
517 case PRIMARY_I2S_RX:
518 case SECONDARY_I2S_RX:
519 case MI2S_RX:
520 case HDMI_RX:
521 case DISPLAY_PORT_RX:
522 case AFE_PORT_ID_SPDIF_RX:
523 case SLIMBUS_0_RX:
524 case SLIMBUS_1_RX:
525 case SLIMBUS_2_RX:
526 case SLIMBUS_3_RX:
527 case SLIMBUS_4_RX:
528 case SLIMBUS_5_RX:
529 case SLIMBUS_6_RX:
530 case SLIMBUS_7_RX:
531 case SLIMBUS_8_RX:
532 case INT_BT_SCO_RX:
533 case INT_BT_A2DP_RX:
534 case INT_FM_RX:
535 case VOICE_PLAYBACK_TX:
536 case VOICE2_PLAYBACK_TX:
537 case RT_PROXY_PORT_001_RX:
538 case AUDIO_PORT_ID_I2S_RX:
539 case AFE_PORT_ID_PRIMARY_MI2S_RX:
540 case AFE_PORT_ID_SECONDARY_MI2S_RX:
541 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
542 case AFE_PORT_ID_TERTIARY_MI2S_RX:
543 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
544 case AFE_PORT_ID_QUINARY_MI2S_RX:
545 case AFE_PORT_ID_PRIMARY_PCM_RX:
546 case AFE_PORT_ID_SECONDARY_PCM_RX:
547 case AFE_PORT_ID_TERTIARY_PCM_RX:
548 case AFE_PORT_ID_QUATERNARY_PCM_RX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530549 case AFE_PORT_ID_QUINARY_PCM_RX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530550 case AFE_PORT_ID_PRIMARY_TDM_RX:
551 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
552 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
553 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
554 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
555 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
556 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
557 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
558 case AFE_PORT_ID_SECONDARY_TDM_RX:
559 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
560 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
561 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
562 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
563 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
564 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
565 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
566 case AFE_PORT_ID_TERTIARY_TDM_RX:
567 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
568 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
569 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
570 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
571 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
572 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
573 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
574 case AFE_PORT_ID_QUATERNARY_TDM_RX:
575 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
576 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
577 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
578 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
579 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
580 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
581 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530582 case AFE_PORT_ID_QUINARY_TDM_RX:
583 case AFE_PORT_ID_QUINARY_TDM_RX_1:
584 case AFE_PORT_ID_QUINARY_TDM_RX_2:
585 case AFE_PORT_ID_QUINARY_TDM_RX_3:
586 case AFE_PORT_ID_QUINARY_TDM_RX_4:
587 case AFE_PORT_ID_QUINARY_TDM_RX_5:
588 case AFE_PORT_ID_QUINARY_TDM_RX_6:
589 case AFE_PORT_ID_QUINARY_TDM_RX_7:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530590 case AFE_PORT_ID_USB_RX:
591 case AFE_PORT_ID_INT0_MI2S_RX:
592 case AFE_PORT_ID_INT1_MI2S_RX:
593 case AFE_PORT_ID_INT2_MI2S_RX:
594 case AFE_PORT_ID_INT3_MI2S_RX:
595 case AFE_PORT_ID_INT4_MI2S_RX:
596 case AFE_PORT_ID_INT5_MI2S_RX:
597 case AFE_PORT_ID_INT6_MI2S_RX:
598 ret = MSM_AFE_PORT_TYPE_RX;
599 break;
600
601 case PRIMARY_I2S_TX:
602 case SECONDARY_I2S_TX:
603 case MI2S_TX:
604 case DIGI_MIC_TX:
605 case VOICE_RECORD_TX:
606 case SLIMBUS_0_TX:
607 case SLIMBUS_1_TX:
608 case SLIMBUS_2_TX:
609 case SLIMBUS_3_TX:
610 case SLIMBUS_4_TX:
611 case SLIMBUS_5_TX:
612 case SLIMBUS_6_TX:
613 case SLIMBUS_7_TX:
614 case SLIMBUS_8_TX:
615 case INT_FM_TX:
616 case VOICE_RECORD_RX:
617 case INT_BT_SCO_TX:
618 case RT_PROXY_PORT_001_TX:
619 case AFE_PORT_ID_PRIMARY_MI2S_TX:
620 case AFE_PORT_ID_SECONDARY_MI2S_TX:
621 case AFE_PORT_ID_TERTIARY_MI2S_TX:
622 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
623 case AFE_PORT_ID_QUINARY_MI2S_TX:
624 case AFE_PORT_ID_SENARY_MI2S_TX:
625 case AFE_PORT_ID_PRIMARY_PCM_TX:
626 case AFE_PORT_ID_SECONDARY_PCM_TX:
627 case AFE_PORT_ID_TERTIARY_PCM_TX:
628 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530629 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530630 case AFE_PORT_ID_PRIMARY_TDM_TX:
631 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
632 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
633 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
634 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
635 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
636 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
637 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
638 case AFE_PORT_ID_SECONDARY_TDM_TX:
639 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
640 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
641 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
642 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
643 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
644 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
645 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
646 case AFE_PORT_ID_TERTIARY_TDM_TX:
647 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
648 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
649 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
650 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
651 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
652 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
653 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
654 case AFE_PORT_ID_QUATERNARY_TDM_TX:
655 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
656 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
657 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
658 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
659 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
660 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
661 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530662 case AFE_PORT_ID_QUINARY_TDM_TX:
663 case AFE_PORT_ID_QUINARY_TDM_TX_1:
664 case AFE_PORT_ID_QUINARY_TDM_TX_2:
665 case AFE_PORT_ID_QUINARY_TDM_TX_3:
666 case AFE_PORT_ID_QUINARY_TDM_TX_4:
667 case AFE_PORT_ID_QUINARY_TDM_TX_5:
668 case AFE_PORT_ID_QUINARY_TDM_TX_6:
669 case AFE_PORT_ID_QUINARY_TDM_TX_7:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530670 case AFE_PORT_ID_USB_TX:
671 case AFE_PORT_ID_INT0_MI2S_TX:
672 case AFE_PORT_ID_INT1_MI2S_TX:
673 case AFE_PORT_ID_INT2_MI2S_TX:
674 case AFE_PORT_ID_INT3_MI2S_TX:
675 case AFE_PORT_ID_INT4_MI2S_TX:
676 case AFE_PORT_ID_INT5_MI2S_TX:
677 case AFE_PORT_ID_INT6_MI2S_TX:
Raja Mallik425e1d32018-05-20 19:21:10 +0530678 case AFE_LOOPBACK_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530679 ret = MSM_AFE_PORT_TYPE_TX;
680 break;
681
682 default:
683 WARN_ON(1);
684 pr_err("%s: Invalid port id = 0x%x\n",
685 __func__, port_id);
686 ret = -EINVAL;
687 }
688
689 return ret;
690}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530691EXPORT_SYMBOL(afe_get_port_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530692
693int afe_sizeof_cfg_cmd(u16 port_id)
694{
695 int ret_size;
696
697 switch (port_id) {
698 case PRIMARY_I2S_RX:
699 case PRIMARY_I2S_TX:
700 case SECONDARY_I2S_RX:
701 case SECONDARY_I2S_TX:
702 case MI2S_RX:
703 case MI2S_TX:
704 case AFE_PORT_ID_PRIMARY_MI2S_RX:
705 case AFE_PORT_ID_PRIMARY_MI2S_TX:
706 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
707 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
708 case AFE_PORT_ID_QUINARY_MI2S_RX:
709 case AFE_PORT_ID_QUINARY_MI2S_TX:
710 ret_size = SIZEOF_CFG_CMD(afe_param_id_i2s_cfg);
711 break;
712 case HDMI_RX:
713 case DISPLAY_PORT_RX:
714 ret_size =
715 SIZEOF_CFG_CMD(afe_param_id_hdmi_multi_chan_audio_cfg);
716 break;
717 case SLIMBUS_0_RX:
718 case SLIMBUS_0_TX:
719 case SLIMBUS_1_RX:
720 case SLIMBUS_1_TX:
721 case SLIMBUS_2_RX:
722 case SLIMBUS_2_TX:
723 case SLIMBUS_3_RX:
724 case SLIMBUS_3_TX:
725 case SLIMBUS_4_RX:
726 case SLIMBUS_4_TX:
727 case SLIMBUS_5_RX:
728 case SLIMBUS_5_TX:
729 case SLIMBUS_6_RX:
730 case SLIMBUS_6_TX:
731 case SLIMBUS_7_RX:
732 case SLIMBUS_7_TX:
733 case SLIMBUS_8_RX:
734 case SLIMBUS_8_TX:
735 ret_size = SIZEOF_CFG_CMD(afe_param_id_slimbus_cfg);
736 break;
737 case VOICE_PLAYBACK_TX:
738 case VOICE2_PLAYBACK_TX:
739 case VOICE_RECORD_RX:
740 case VOICE_RECORD_TX:
741 ret_size = SIZEOF_CFG_CMD(afe_param_id_pseudo_port_cfg);
742 break;
743 case RT_PROXY_PORT_001_RX:
744 case RT_PROXY_PORT_001_TX:
745 ret_size = SIZEOF_CFG_CMD(afe_param_id_rt_proxy_port_cfg);
746 break;
747 case AFE_PORT_ID_USB_RX:
748 case AFE_PORT_ID_USB_TX:
749 ret_size = SIZEOF_CFG_CMD(afe_param_id_usb_audio_cfg);
750 break;
751 case AFE_PORT_ID_PRIMARY_PCM_RX:
752 case AFE_PORT_ID_PRIMARY_PCM_TX:
753 case AFE_PORT_ID_SECONDARY_PCM_RX:
754 case AFE_PORT_ID_SECONDARY_PCM_TX:
755 case AFE_PORT_ID_TERTIARY_PCM_RX:
756 case AFE_PORT_ID_TERTIARY_PCM_TX:
757 case AFE_PORT_ID_QUATERNARY_PCM_RX:
758 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530759 case AFE_PORT_ID_QUINARY_PCM_RX:
760 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530761 default:
762 pr_debug("%s: default case 0x%x\n", __func__, port_id);
763 ret_size = SIZEOF_CFG_CMD(afe_param_id_pcm_cfg);
764 break;
765 }
766 return ret_size;
767}
768
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530769/**
770 * afe_q6_interface_prepare -
771 * wrapper API to check Q6 AFE registered to APR otherwise registers
772 *
773 * Returns 0 on success or error on failure.
774 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530775int afe_q6_interface_prepare(void)
776{
777 int ret = 0;
778
779 pr_debug("%s:\n", __func__);
780
781 if (this_afe.apr == NULL) {
782 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
783 0xFFFFFFFF, &this_afe);
784 if (this_afe.apr == NULL) {
785 pr_err("%s: Unable to register AFE\n", __func__);
Laxminath Kasamc1880702018-04-04 10:59:57 +0530786 ret = -ENETRESET;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530787 }
788 rtac_set_afe_handle(this_afe.apr);
789 }
790 return ret;
791}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530792EXPORT_SYMBOL(afe_q6_interface_prepare);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530793
794/*
795 * afe_apr_send_pkt : returns 0 on success, negative otherwise.
796 */
797static int afe_apr_send_pkt(void *data, wait_queue_head_t *wait)
798{
799 int ret;
800
801 if (wait)
802 atomic_set(&this_afe.state, 1);
803 atomic_set(&this_afe.status, 0);
804 ret = apr_send_pkt(this_afe.apr, data);
805 if (ret > 0) {
806 if (wait) {
807 ret = wait_event_timeout(*wait,
808 (atomic_read(&this_afe.state) == 0),
809 msecs_to_jiffies(TIMEOUT_MS));
810 if (!ret) {
811 ret = -ETIMEDOUT;
812 } else if (atomic_read(&this_afe.status) > 0) {
813 pr_err("%s: DSP returned error[%s]\n", __func__,
814 adsp_err_get_err_str(atomic_read(
815 &this_afe.status)));
816 ret = adsp_err_get_lnx_err_code(
817 atomic_read(&this_afe.status));
818 } else {
819 ret = 0;
820 }
821 } else {
822 ret = 0;
823 }
824 } else if (ret == 0) {
825 pr_err("%s: packet not transmitted\n", __func__);
826 /* apr_send_pkt can return 0 when nothing is transmitted */
827 ret = -EINVAL;
828 }
829
830 pr_debug("%s: leave %d\n", __func__, ret);
831 return ret;
832}
833
834static int afe_send_cal_block(u16 port_id, struct cal_block_data *cal_block)
835{
836 int result = 0;
837 int index = 0;
838 struct afe_audioif_config_command_no_payload afe_cal;
839
840 if (!cal_block) {
841 pr_debug("%s: No AFE cal to send!\n", __func__);
842 result = -EINVAL;
843 goto done;
844 }
845 if (cal_block->cal_data.size <= 0) {
846 pr_debug("%s: AFE cal has invalid size!\n", __func__);
847 result = -EINVAL;
848 goto done;
849 }
850
851 index = q6audio_get_port_index(port_id);
852 if (index < 0 || index >= AFE_MAX_PORTS) {
853 pr_err("%s: AFE port index[%d] invalid!\n",
854 __func__, index);
855 result = -EINVAL;
856 goto done;
857 }
858
859 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
860 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
861 afe_cal.hdr.pkt_size = sizeof(afe_cal);
862 afe_cal.hdr.src_port = 0;
863 afe_cal.hdr.dest_port = 0;
864 afe_cal.hdr.token = index;
865 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
866 afe_cal.param.port_id = port_id;
867 afe_cal.param.payload_size = cal_block->cal_data.size;
868 afe_cal.param.payload_address_lsw =
869 lower_32_bits(cal_block->cal_data.paddr);
870 afe_cal.param.payload_address_msw =
871 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
872 afe_cal.param.mem_map_handle = cal_block->map_data.q6map_handle;
873
874 pr_debug("%s: AFE cal sent for device port = 0x%x, cal size = %zd, cal addr = 0x%pK\n",
875 __func__, port_id,
876 cal_block->cal_data.size, &cal_block->cal_data.paddr);
877
878 result = afe_apr_send_pkt(&afe_cal, &this_afe.wait[index]);
879 if (result)
880 pr_err("%s: AFE cal for port 0x%x failed %d\n",
881 __func__, port_id, result);
882
883done:
884 return result;
885}
886
887
888static int afe_send_custom_topology_block(struct cal_block_data *cal_block)
889{
890 int result = 0;
891 int index = 0;
892 struct cmd_set_topologies afe_cal;
893
894 if (!cal_block) {
895 pr_err("%s: No AFE SVC cal to send!\n", __func__);
896 return -EINVAL;
897 }
898 if (cal_block->cal_data.size <= 0) {
899 pr_err("%s: AFE SVC cal has invalid size: %zd!\n",
900 __func__, cal_block->cal_data.size);
901 return -EINVAL;
902 }
903
904 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
905 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
906 afe_cal.hdr.pkt_size = sizeof(afe_cal);
907 afe_cal.hdr.src_port = 0;
908 afe_cal.hdr.dest_port = 0;
909 afe_cal.hdr.token = index;
910 afe_cal.hdr.opcode = AFE_CMD_ADD_TOPOLOGIES;
911
912 afe_cal.payload_size = cal_block->cal_data.size;
913 afe_cal.payload_addr_lsw =
914 lower_32_bits(cal_block->cal_data.paddr);
915 afe_cal.payload_addr_msw =
916 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
917 afe_cal.mem_map_handle = cal_block->map_data.q6map_handle;
918
919 pr_debug("%s:cmd_id:0x%x calsize:%zd memmap_hdl:0x%x caladdr:0x%pK",
920 __func__, AFE_CMD_ADD_TOPOLOGIES, cal_block->cal_data.size,
921 afe_cal.mem_map_handle, &cal_block->cal_data.paddr);
922
923 result = afe_apr_send_pkt(&afe_cal, &this_afe.wait[index]);
924 if (result)
925 pr_err("%s: AFE send topology for command 0x%x failed %d\n",
926 __func__, AFE_CMD_ADD_TOPOLOGIES, result);
927
928 return result;
929}
930
931static void afe_send_custom_topology(void)
932{
933 struct cal_block_data *cal_block = NULL;
934 int cal_index = AFE_CUST_TOPOLOGY_CAL;
935 int ret;
936
937 if (this_afe.cal_data[cal_index] == NULL) {
938 pr_err("%s: cal_index %d not allocated!\n",
939 __func__, cal_index);
940 return;
941 }
942 mutex_lock(&this_afe.cal_data[cal_index]->lock);
943
944 if (!this_afe.set_custom_topology)
945 goto unlock;
946 this_afe.set_custom_topology = 0;
947 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -0700948 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530949 pr_err("%s cal_block not found!!\n", __func__);
950 goto unlock;
951 }
952
953 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
954
955 ret = remap_cal_data(cal_block, cal_index);
956 if (ret) {
957 pr_err("%s: Remap_cal_data failed for cal %d!\n",
958 __func__, cal_index);
959 goto unlock;
960 }
961 ret = afe_send_custom_topology_block(cal_block);
962 if (ret < 0) {
963 pr_err("%s: No cal sent for cal_index %d! ret %d\n",
964 __func__, cal_index, ret);
965 goto unlock;
966 }
967 pr_debug("%s:sent custom topology for AFE\n", __func__);
968unlock:
969 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
970}
971
972static int afe_spk_ramp_dn_cfg(int port)
973{
974 int ret = -EINVAL;
975 int index = 0;
976 struct afe_spkr_prot_config_command config;
977
978 if (afe_get_port_type(port) != MSM_AFE_PORT_TYPE_RX) {
979 pr_debug("%s: port doesn't match 0x%x\n", __func__, port);
980 return 0;
981 }
982 if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_DISABLED ||
983 (this_afe.vi_rx_port != port)) {
984 pr_debug("%s: spkr protection disabled port 0x%x %d 0x%x\n",
985 __func__, port, ret, this_afe.vi_rx_port);
986 return 0;
987 }
988 memset(&config, 0, sizeof(config));
989 ret = q6audio_validate_port(port);
990 if (ret < 0) {
991 pr_err("%s: Invalid port 0x%x ret %d", __func__, port, ret);
992 ret = -EINVAL;
993 goto fail_cmd;
994 }
995 index = q6audio_get_port_index(port);
996 if (index < 0 || index >= AFE_MAX_PORTS) {
997 pr_err("%s: AFE port index[%d] invalid!\n",
998 __func__, index);
999 ret = -EINVAL;
1000 goto fail_cmd;
1001 }
1002 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1003 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1004 config.hdr.pkt_size = sizeof(config);
1005 config.hdr.src_port = 0;
1006 config.hdr.dest_port = 0;
1007 config.hdr.token = index;
1008
1009 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1010 config.param.port_id = q6audio_get_port_id(port);
1011 config.param.payload_size =
1012 sizeof(config) - sizeof(config.hdr) - sizeof(config.param)
1013 - sizeof(config.prot_config);
1014 config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
1015 config.pdata.param_id = AFE_PARAM_ID_FBSP_PTONE_RAMP_CFG;
1016 config.pdata.param_size = 0;
1017 atomic_set(&this_afe.state, 1);
1018 atomic_set(&this_afe.status, 0);
1019 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
1020 if (ret < 0) {
1021 pr_err("%s: port = 0x%x param = 0x%x failed %d\n",
1022 __func__, port, config.pdata.param_id, ret);
1023 goto fail_cmd;
1024 }
1025 ret = wait_event_timeout(this_afe.wait[index],
1026 (atomic_read(&this_afe.state) == 0),
1027 msecs_to_jiffies(TIMEOUT_MS));
1028 if (!ret) {
1029 pr_err("%s: wait_event timeout\n", __func__);
1030 ret = -EINVAL;
1031 goto fail_cmd;
1032 }
1033 if (atomic_read(&this_afe.status) > 0) {
1034 pr_err("%s: config cmd failed [%s]\n",
1035 __func__, adsp_err_get_err_str(
1036 atomic_read(&this_afe.status)));
1037 ret = adsp_err_get_lnx_err_code(
1038 atomic_read(&this_afe.status));
1039 goto fail_cmd;
1040 }
1041 /* dsp needs atleast 15ms to ramp down pilot tone*/
1042 usleep_range(15000, 15010);
1043 ret = 0;
1044fail_cmd:
1045 pr_debug("%s: config.pdata.param_id 0x%x status %d\n",
1046 __func__, config.pdata.param_id, ret);
1047return ret;
1048}
1049
1050static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id,
1051 union afe_spkr_prot_config *prot_config)
1052{
1053 int ret = -EINVAL;
1054 int index = 0;
1055 struct afe_spkr_prot_config_command config;
1056
1057 memset(&config, 0, sizeof(config));
1058 if (!prot_config) {
1059 pr_err("%s: Invalid params\n", __func__);
1060 goto fail_cmd;
1061 }
1062 ret = q6audio_validate_port(src_port);
1063 if (ret < 0) {
1064 pr_err("%s: Invalid src port 0x%x ret %d",
1065 __func__, src_port, ret);
1066 ret = -EINVAL;
1067 goto fail_cmd;
1068 }
1069 ret = q6audio_validate_port(dst_port);
1070 if (ret < 0) {
1071 pr_err("%s: Invalid dst port 0x%x ret %d", __func__,
1072 dst_port, ret);
1073 ret = -EINVAL;
1074 goto fail_cmd;
1075 }
1076 index = q6audio_get_port_index(src_port);
1077 if (index < 0 || index >= AFE_MAX_PORTS) {
1078 pr_err("%s: AFE port index[%d] invalid!\n",
1079 __func__, index);
1080 ret = -EINVAL;
1081 goto fail_cmd;
1082 }
1083 switch (param_id) {
1084 case AFE_PARAM_ID_FBSP_MODE_RX_CFG:
Xiaojun Sang12120ab2017-09-28 18:21:21 +08001085 case AFE_PARAM_ID_SP_RX_LIMITER_TH:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301086 config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
1087 break;
1088 case AFE_PARAM_ID_FEEDBACK_PATH_CFG:
1089 this_afe.vi_tx_port = src_port;
1090 this_afe.vi_rx_port = dst_port;
1091 config.pdata.module_id = AFE_MODULE_FEEDBACK;
1092 break;
1093 /*
1094 * AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2 is same as
1095 * AFE_PARAM_ID_SP_V2_TH_VI_MODE_CFG
1096 */
1097 case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2:
1098 case AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG:
1099 config.pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
1100 break;
1101 case AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG:
1102 case AFE_PARAM_ID_SP_V2_EX_VI_FTM_CFG:
1103 config.pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
1104 break;
1105 default:
1106 pr_err("%s: default case 0x%x\n", __func__, param_id);
1107 goto fail_cmd;
1108 }
1109
1110 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1111 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1112 config.hdr.pkt_size = sizeof(config);
1113 config.hdr.src_port = 0;
1114 config.hdr.dest_port = 0;
1115 config.hdr.token = index;
1116
1117 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1118 config.param.port_id = q6audio_get_port_id(src_port);
1119 config.param.payload_size = sizeof(config) - sizeof(config.hdr)
1120 - sizeof(config.param);
1121 config.pdata.param_id = param_id;
1122 config.pdata.param_size = sizeof(config.prot_config);
1123 config.prot_config = *prot_config;
1124 atomic_set(&this_afe.state, 1);
1125 atomic_set(&this_afe.status, 0);
1126 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
1127 if (ret < 0) {
1128 pr_err("%s: port = 0x%x param = 0x%x failed %d\n",
1129 __func__, src_port, param_id, ret);
1130 goto fail_cmd;
1131 }
1132 ret = wait_event_timeout(this_afe.wait[index],
1133 (atomic_read(&this_afe.state) == 0),
1134 msecs_to_jiffies(TIMEOUT_MS));
1135 if (!ret) {
1136 pr_err("%s: wait_event timeout\n", __func__);
1137 ret = -EINVAL;
1138 goto fail_cmd;
1139 }
1140 if (atomic_read(&this_afe.status) > 0) {
1141 pr_err("%s: config cmd failed [%s]\n",
1142 __func__, adsp_err_get_err_str(
1143 atomic_read(&this_afe.status)));
1144 ret = adsp_err_get_lnx_err_code(
1145 atomic_read(&this_afe.status));
1146 goto fail_cmd;
1147 }
1148 ret = 0;
1149fail_cmd:
1150 pr_debug("%s: config.pdata.param_id 0x%x status %d 0x%x\n",
1151 __func__, config.pdata.param_id, ret, src_port);
1152 return ret;
1153}
1154
1155static void afe_send_cal_spkr_prot_tx(int port_id)
1156{
1157 union afe_spkr_prot_config afe_spk_config;
1158
1159 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL ||
1160 this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
1161 this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL)
1162 return;
1163
1164 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1165 if ((this_afe.prot_cfg.mode != MSM_SPKR_PROT_DISABLED) &&
1166 (this_afe.vi_tx_port == port_id)) {
1167 if (this_afe.prot_cfg.mode ==
1168 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
1169 afe_spk_config.vi_proc_cfg.operation_mode =
1170 Q6AFE_MSM_SPKR_CALIBRATION;
1171 afe_spk_config.vi_proc_cfg.quick_calib_flag =
1172 this_afe.prot_cfg.quick_calib_flag;
1173 } else {
1174 afe_spk_config.vi_proc_cfg.operation_mode =
1175 Q6AFE_MSM_SPKR_PROCESSING;
1176 }
1177
1178 if (this_afe.th_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE)
1179 afe_spk_config.vi_proc_cfg.operation_mode =
1180 Q6AFE_MSM_SPKR_FTM_MODE;
1181 afe_spk_config.vi_proc_cfg.minor_version = 1;
1182 afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_1] =
1183 (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1];
1184 afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_2] =
1185 (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_2];
1186 afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_1] =
1187 (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_1];
1188 afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_2] =
1189 (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_2];
1190 if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_NOT_CALIBRATED) {
1191 struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg;
1192
1193 vi_proc_cfg = &afe_spk_config.vi_proc_cfg;
1194 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] =
1195 USE_CALIBRATED_R0TO;
1196 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] =
1197 USE_CALIBRATED_R0TO;
1198 } else {
1199 struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg;
1200
1201 vi_proc_cfg = &afe_spk_config.vi_proc_cfg;
1202 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] =
1203 USE_SAFE_R0TO;
1204 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] =
1205 USE_SAFE_R0TO;
1206 }
1207 if (afe_spk_prot_prepare(port_id, 0,
1208 AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2,
1209 &afe_spk_config))
1210 pr_err("%s: SPKR_CALIB_VI_PROC_CFG failed\n",
1211 __func__);
1212 }
1213 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1214
1215 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
1216 if ((this_afe.th_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE) &&
1217 (this_afe.vi_tx_port == port_id)) {
1218 afe_spk_config.th_vi_ftm_cfg.minor_version = 1;
1219 afe_spk_config.th_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_1] =
1220 this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_1];
1221 afe_spk_config.th_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_2] =
1222 this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_2];
1223 afe_spk_config.th_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_1] =
1224 this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_1];
1225 afe_spk_config.th_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_2] =
1226 this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_2];
1227
1228 if (afe_spk_prot_prepare(port_id, 0,
1229 AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG,
1230 &afe_spk_config))
1231 pr_err("%s: th vi ftm cfg failed\n", __func__);
1232 this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
1233 }
1234 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
1235
1236 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
1237 if ((this_afe.ex_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE) &&
1238 (this_afe.vi_tx_port == port_id)) {
1239 afe_spk_config.ex_vi_mode_cfg.minor_version = 1;
1240 afe_spk_config.ex_vi_mode_cfg.operation_mode =
1241 Q6AFE_MSM_SPKR_FTM_MODE;
1242 if (afe_spk_prot_prepare(port_id, 0,
1243 AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG,
1244 &afe_spk_config))
1245 pr_err("%s: ex vi mode cfg failed\n", __func__);
1246
1247 afe_spk_config.ex_vi_ftm_cfg.minor_version = 1;
1248 afe_spk_config.ex_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_1] =
1249 this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_1];
1250 afe_spk_config.ex_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_2] =
1251 this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_2];
1252 afe_spk_config.ex_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_1] =
1253 this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_1];
1254 afe_spk_config.ex_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_2] =
1255 this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_2];
1256
1257 if (afe_spk_prot_prepare(port_id, 0,
1258 AFE_PARAM_ID_SP_V2_EX_VI_FTM_CFG,
1259 &afe_spk_config))
1260 pr_err("%s: ex vi ftm cfg failed\n", __func__);
1261 this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
1262 }
1263 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
1264
1265}
1266
1267static void afe_send_cal_spkr_prot_rx(int port_id)
1268{
1269 union afe_spkr_prot_config afe_spk_config;
Xiaojun Sang12120ab2017-09-28 18:21:21 +08001270 union afe_spkr_prot_config afe_spk_limiter_config;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301271
1272 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
1273 goto done;
1274
1275 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1276
1277 if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_DISABLED &&
1278 (this_afe.vi_rx_port == port_id)) {
1279 if (this_afe.prot_cfg.mode ==
1280 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
1281 afe_spk_config.mode_rx_cfg.mode =
1282 Q6AFE_MSM_SPKR_CALIBRATION;
1283 else
1284 afe_spk_config.mode_rx_cfg.mode =
1285 Q6AFE_MSM_SPKR_PROCESSING;
1286 afe_spk_config.mode_rx_cfg.minor_version = 1;
1287 if (afe_spk_prot_prepare(port_id, 0,
1288 AFE_PARAM_ID_FBSP_MODE_RX_CFG,
1289 &afe_spk_config))
1290 pr_err("%s: RX MODE_VI_PROC_CFG failed\n",
1291 __func__);
Xiaojun Sang12120ab2017-09-28 18:21:21 +08001292
1293 if (afe_spk_config.mode_rx_cfg.mode ==
1294 Q6AFE_MSM_SPKR_PROCESSING) {
1295 if (this_afe.prot_cfg.sp_version >=
1296 AFE_API_VERSION_SUPPORT_SPV3) {
1297 afe_spk_limiter_config.limiter_th_cfg.
1298 minor_version = 1;
1299 afe_spk_limiter_config.limiter_th_cfg.
1300 lim_thr_per_calib_q27[SP_V2_SPKR_1] =
1301 this_afe.prot_cfg.limiter_th[SP_V2_SPKR_1];
1302 afe_spk_limiter_config.limiter_th_cfg.
1303 lim_thr_per_calib_q27[SP_V2_SPKR_2] =
1304 this_afe.prot_cfg.limiter_th[SP_V2_SPKR_2];
1305 if (afe_spk_prot_prepare(port_id, 0,
1306 AFE_PARAM_ID_SP_RX_LIMITER_TH,
1307 &afe_spk_limiter_config))
1308 pr_err("%s: SP_RX_LIMITER_TH failed.\n",
1309 __func__);
1310 } else {
1311 pr_debug("%s: SPv3 failed to apply on AFE API version=%d.\n",
1312 __func__,
1313 this_afe.prot_cfg.sp_version);
1314 }
1315 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301316 }
1317 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1318done:
1319 return;
1320}
1321
1322static int afe_send_hw_delay(u16 port_id, u32 rate)
1323{
1324 struct audio_cal_hw_delay_entry delay_entry;
1325 struct afe_audioif_config_command config;
1326 int index = 0;
1327 int ret = -EINVAL;
1328
1329 pr_debug("%s:\n", __func__);
1330
1331 memset(&delay_entry, 0, sizeof(delay_entry));
1332 delay_entry.sample_rate = rate;
1333 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
1334 ret = afe_get_cal_hw_delay(TX_DEVICE, &delay_entry);
1335 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
1336 ret = afe_get_cal_hw_delay(RX_DEVICE, &delay_entry);
1337
1338 /*
1339 * HW delay is only used for IMS calls to sync audio with video
1340 * It is only needed for devices & sample rates used for IMS video
1341 * calls. Values are received from ACDB calbration files
1342 */
1343 if (ret != 0) {
1344 pr_debug("%s: debug: HW delay info not available %d\n",
1345 __func__, ret);
1346 goto fail_cmd;
1347 }
1348
1349 index = q6audio_get_port_index(port_id);
1350 if (index < 0 || index >= AFE_MAX_PORTS) {
1351 pr_err("%s: AFE port index[%d] invalid!\n",
1352 __func__, index);
1353 ret = -EINVAL;
1354 goto fail_cmd;
1355 }
1356
1357 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1358 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1359 config.hdr.pkt_size = sizeof(config);
1360 config.hdr.src_port = 0;
1361 config.hdr.dest_port = 0;
1362 config.hdr.token = index;
1363
1364 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1365 config.param.port_id = q6audio_get_port_id(port_id);
1366 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1367 sizeof(config.param);
1368 config.param.payload_address_lsw = 0x00;
1369 config.param.payload_address_msw = 0x00;
1370 config.param.mem_map_handle = 0x00;
1371 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
1372 config.pdata.param_id = AFE_PARAM_ID_DEVICE_HW_DELAY;
1373 config.pdata.param_size = sizeof(config.port);
1374
1375 config.port.hw_delay.delay_in_us = delay_entry.delay_usec;
1376 config.port.hw_delay.device_hw_delay_minor_version =
1377 AFE_API_VERSION_DEVICE_HW_DELAY;
1378
1379 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
1380 if (ret) {
1381 pr_err("%s: AFE hw delay for port 0x%x failed %d\n",
1382 __func__, port_id, ret);
1383 goto fail_cmd;
1384 }
1385
1386fail_cmd:
1387 pr_debug("%s: port_id 0x%x rate %u delay_usec %d status %d\n",
1388 __func__, port_id, rate, delay_entry.delay_usec, ret);
1389 return ret;
1390}
1391
1392static struct cal_block_data *afe_find_cal_topo_id_by_port(
1393 struct cal_type_data *cal_type, u16 port_id)
1394{
1395 struct list_head *ptr, *next;
1396 struct cal_block_data *cal_block = NULL;
1397 int32_t path;
1398 struct audio_cal_info_afe_top *afe_top;
1399 int afe_port_index = q6audio_get_port_index(port_id);
1400
1401 if (afe_port_index < 0)
1402 goto err_exit;
1403
1404 list_for_each_safe(ptr, next,
1405 &cal_type->cal_blocks) {
1406 cal_block = list_entry(ptr,
1407 struct cal_block_data, list);
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07001408 /* Skip cal_block if it is already marked stale */
1409 if (cal_utils_is_cal_stale(cal_block))
1410 continue;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301411 path = ((afe_get_port_type(port_id) ==
1412 MSM_AFE_PORT_TYPE_TX)?(TX_DEVICE):(RX_DEVICE));
1413 afe_top =
1414 (struct audio_cal_info_afe_top *)cal_block->cal_info;
1415 if (afe_top->path == path) {
1416 if (this_afe.dev_acdb_id[afe_port_index] > 0) {
1417 if (afe_top->acdb_id ==
1418 this_afe.dev_acdb_id[afe_port_index]) {
1419 pr_debug("%s: top_id:%x acdb_id:%d afe_port_id:%d\n",
1420 __func__, afe_top->topology,
1421 afe_top->acdb_id,
1422 q6audio_get_port_id(port_id));
1423 return cal_block;
1424 }
1425 } else {
1426 pr_debug("%s: top_id:%x acdb_id:%d afe_port:%d\n",
1427 __func__, afe_top->topology, afe_top->acdb_id,
1428 q6audio_get_port_id(port_id));
1429 return cal_block;
1430 }
1431 }
1432 }
1433
1434err_exit:
1435 return NULL;
1436}
1437
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07001438/*
1439 * Retrieving cal_block will mark cal_block as stale.
1440 * Hence it cannot be reused or resent unless the flag
1441 * is reset.
1442 */
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301443static int afe_get_cal_topology_id(u16 port_id, u32 *topology_id,
1444 int cal_type_index)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301445{
1446 int ret = 0;
1447
1448 struct cal_block_data *cal_block = NULL;
1449 struct audio_cal_info_afe_top *afe_top_info = NULL;
1450
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301451 if (this_afe.cal_data[cal_type_index] == NULL) {
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07001452 pr_err("%s: cal_type %d not initialized\n", __func__,
1453 cal_type_index);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301454 return -EINVAL;
1455 }
1456 if (topology_id == NULL) {
1457 pr_err("%s: topology_id is NULL\n", __func__);
1458 return -EINVAL;
1459 }
1460 *topology_id = 0;
1461
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301462 mutex_lock(&this_afe.cal_data[cal_type_index]->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301463 cal_block = afe_find_cal_topo_id_by_port(
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301464 this_afe.cal_data[cal_type_index], port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301465 if (cal_block == NULL) {
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07001466 pr_err("%s: cal_type %d not initialized for this port %d\n",
1467 __func__, cal_type_index, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301468 ret = -EINVAL;
1469 goto unlock;
1470 }
1471
1472 afe_top_info = ((struct audio_cal_info_afe_top *)
1473 cal_block->cal_info);
1474 if (!afe_top_info->topology) {
1475 pr_err("%s: invalid topology id : [%d, %d]\n",
1476 __func__, afe_top_info->acdb_id, afe_top_info->topology);
1477 ret = -EINVAL;
1478 goto unlock;
1479 }
1480 *topology_id = (u32)afe_top_info->topology;
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07001481 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301482
1483 pr_debug("%s: port_id = %u acdb_id = %d topology_id = %u ret=%d\n",
1484 __func__, port_id, afe_top_info->acdb_id,
1485 afe_top_info->topology, ret);
1486unlock:
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301487 mutex_unlock(&this_afe.cal_data[cal_type_index]->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301488 return ret;
1489}
1490
1491static int afe_send_port_topology_id(u16 port_id)
1492{
1493 struct afe_audioif_config_command config;
1494 int index = 0;
1495 int ret = 0;
1496 u32 topology_id = 0;
1497
1498 index = q6audio_get_port_index(port_id);
1499 if (index < 0 || index >= AFE_MAX_PORTS) {
1500 pr_err("%s: AFE port index[%d] invalid!\n",
1501 __func__, index);
1502 return -EINVAL;
1503 }
1504
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301505 ret = afe_get_cal_topology_id(port_id, &topology_id, AFE_TOPOLOGY_CAL);
1506 if (ret < 0) {
1507 pr_debug("%s: Check for LSM topology\n", __func__);
1508 ret = afe_get_cal_topology_id(port_id, &topology_id,
1509 AFE_LSM_TOPOLOGY_CAL);
1510 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301511 if (ret || !topology_id) {
1512 pr_debug("%s: AFE port[%d] get_cal_topology[%d] invalid!\n",
1513 __func__, port_id, topology_id);
1514 goto done;
1515 }
1516
1517 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1518 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1519 config.hdr.pkt_size = sizeof(config);
1520 config.hdr.src_port = 0;
1521 config.hdr.dest_port = 0;
1522 config.hdr.token = index;
1523
1524 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1525 config.param.port_id = q6audio_get_port_id(port_id);
1526 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1527 sizeof(config.param);
1528 config.param.payload_address_lsw = 0x00;
1529 config.param.payload_address_msw = 0x00;
1530 config.param.mem_map_handle = 0x00;
1531 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
1532 config.pdata.param_id = AFE_PARAM_ID_SET_TOPOLOGY;
1533 config.pdata.param_size = sizeof(config.port);
1534 config.port.topology.minor_version = AFE_API_VERSION_TOPOLOGY_V1;
1535 config.port.topology.topology_id = topology_id;
1536
1537 pr_debug("%s: param PL size=%d iparam_size[%d][%zd %zd %zd %zd] param_id[0x%x]\n",
1538 __func__, config.param.payload_size, config.pdata.param_size,
1539 sizeof(config), sizeof(config.param), sizeof(config.port),
1540 sizeof(struct apr_hdr), config.pdata.param_id);
1541
1542 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
1543 if (ret) {
1544 pr_err("%s: AFE set topology id enable for port 0x%x failed %d\n",
1545 __func__, port_id, ret);
1546 goto done;
1547 }
1548
1549 this_afe.topology[index] = topology_id;
1550 rtac_update_afe_topology(port_id);
1551done:
1552 pr_debug("%s: AFE set topology id 0x%x enable for port 0x%x ret %d\n",
1553 __func__, topology_id, port_id, ret);
1554 return ret;
1555
1556}
1557
1558static int remap_cal_data(struct cal_block_data *cal_block, int cal_index)
1559{
1560 int ret = 0;
1561
1562 if (cal_block->map_data.ion_client == NULL) {
1563 pr_err("%s: No ION allocation for cal index %d!\n",
1564 __func__, cal_index);
1565 ret = -EINVAL;
1566 goto done;
1567 }
1568
1569 if ((cal_block->map_data.map_size > 0) &&
1570 (cal_block->map_data.q6map_handle == 0)) {
1571 atomic_set(&this_afe.mem_map_cal_index, cal_index);
1572 ret = afe_cmd_memory_map(cal_block->cal_data.paddr,
1573 cal_block->map_data.map_size);
1574 atomic_set(&this_afe.mem_map_cal_index, -1);
1575 if (ret < 0) {
1576 pr_err("%s: mmap did not work! size = %zd ret %d\n",
1577 __func__,
1578 cal_block->map_data.map_size, ret);
1579 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
1580 __func__,
1581 &cal_block->cal_data.paddr,
1582 cal_block->map_data.map_size);
1583 goto done;
1584 }
1585 cal_block->map_data.q6map_handle = atomic_read(&this_afe.
1586 mem_map_cal_handles[cal_index]);
1587 }
1588done:
1589 return ret;
1590}
1591
1592static struct cal_block_data *afe_find_cal(int cal_index, int port_id)
1593{
1594 struct list_head *ptr, *next;
1595 struct cal_block_data *cal_block = NULL;
1596 struct audio_cal_info_afe *afe_cal_info = NULL;
1597 int afe_port_index = q6audio_get_port_index(port_id);
1598
1599 pr_debug("%s: cal_index %d port_id %d port_index %d\n", __func__,
1600 cal_index, port_id, afe_port_index);
1601 if (afe_port_index < 0) {
1602 pr_err("%s: Error getting AFE port index %d\n",
1603 __func__, afe_port_index);
1604 goto exit;
1605 }
1606
1607 list_for_each_safe(ptr, next,
1608 &this_afe.cal_data[cal_index]->cal_blocks) {
1609 cal_block = list_entry(ptr, struct cal_block_data, list);
1610 afe_cal_info = cal_block->cal_info;
1611 if ((afe_cal_info->acdb_id ==
1612 this_afe.dev_acdb_id[afe_port_index]) &&
1613 (afe_cal_info->sample_rate ==
1614 this_afe.afe_sample_rates[afe_port_index])) {
1615 pr_debug("%s: cal block is a match, size is %zd\n",
1616 __func__, cal_block->cal_data.size);
1617 goto exit;
1618 }
1619 }
1620 pr_err("%s: no matching cal_block found\n", __func__);
1621 cal_block = NULL;
1622
1623exit:
1624 return cal_block;
1625}
1626
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301627static int send_afe_cal_type(int cal_index, int port_id)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301628{
1629 struct cal_block_data *cal_block = NULL;
1630 int ret;
1631 int afe_port_index = q6audio_get_port_index(port_id);
1632
1633 pr_debug("%s:\n", __func__);
1634
1635 if (this_afe.cal_data[cal_index] == NULL) {
1636 pr_warn("%s: cal_index %d not allocated!\n",
1637 __func__, cal_index);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301638 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301639 goto done;
1640 }
1641
1642 if (afe_port_index < 0) {
1643 pr_err("%s: Error getting AFE port index %d\n",
1644 __func__, afe_port_index);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301645 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301646 goto done;
1647 }
1648
1649 mutex_lock(&this_afe.cal_data[cal_index]->lock);
1650
1651 if (((cal_index == AFE_COMMON_RX_CAL) ||
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301652 (cal_index == AFE_COMMON_TX_CAL) ||
1653 (cal_index == AFE_LSM_TX_CAL)) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301654 (this_afe.dev_acdb_id[afe_port_index] > 0))
1655 cal_block = afe_find_cal(cal_index, port_id);
1656 else
1657 cal_block = cal_utils_get_only_cal_block(
1658 this_afe.cal_data[cal_index]);
1659
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07001660 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301661 pr_err("%s cal_block not found!!\n", __func__);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301662 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301663 goto unlock;
1664 }
1665
1666 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
1667
1668 ret = remap_cal_data(cal_block, cal_index);
1669 if (ret) {
1670 pr_err("%s: Remap_cal_data failed for cal %d!\n",
1671 __func__, cal_index);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301672 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301673 goto unlock;
1674 }
1675 ret = afe_send_cal_block(port_id, cal_block);
1676 if (ret < 0)
1677 pr_debug("%s: No cal sent for cal_index %d, port_id = 0x%x! ret %d\n",
1678 __func__, cal_index, port_id, ret);
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07001679
1680 cal_utils_mark_cal_used(cal_block);
1681
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301682unlock:
1683 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
1684done:
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301685 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301686}
1687
1688void afe_send_cal(u16 port_id)
1689{
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301690 int ret;
1691
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301692 pr_debug("%s: port_id=0x%x\n", __func__, port_id);
1693
1694 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) {
1695 afe_send_cal_spkr_prot_tx(port_id);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301696 ret = send_afe_cal_type(AFE_COMMON_TX_CAL, port_id);
1697 if (ret < 0)
1698 send_afe_cal_type(AFE_LSM_TX_CAL, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301699 } else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301700 send_afe_cal_type(AFE_COMMON_RX_CAL, port_id);
Xiaojun Sang092e0ed2017-12-11 16:13:32 +08001701 afe_send_cal_spkr_prot_rx(port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301702 }
1703}
1704
1705int afe_turn_onoff_hw_mad(u16 mad_type, u16 enable)
1706{
1707 int ret;
1708 struct afe_cmd_hw_mad_ctrl config;
1709
1710 pr_debug("%s: enter\n", __func__);
1711 memset(&config, 0, sizeof(config));
1712 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1713 APR_HDR_LEN(APR_HDR_SIZE),
1714 APR_PKT_VER);
1715 config.hdr.pkt_size = sizeof(config);
1716 config.hdr.src_port = 0;
1717 config.hdr.dest_port = 0;
1718 config.hdr.token = IDX_GLOBAL_CFG;
1719 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1720 config.param.port_id = SLIMBUS_5_TX;
1721 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1722 sizeof(config.param);
1723 config.param.payload_address_lsw = 0x00;
1724 config.param.payload_address_msw = 0x00;
1725 config.param.mem_map_handle = 0x00;
1726 config.pdata.module_id = AFE_MODULE_HW_MAD;
1727 config.pdata.param_id = AFE_PARAM_ID_HW_MAD_CTRL;
1728 config.pdata.param_size = sizeof(config.payload);
1729 config.payload.minor_version = 1;
1730 config.payload.mad_type = mad_type;
1731 config.payload.mad_enable = enable;
1732
1733 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
1734 if (ret)
1735 pr_err("%s: AFE_PARAM_ID_HW_MAD_CTRL failed %d\n", __func__,
1736 ret);
1737 return ret;
1738}
1739
1740static int afe_send_slimbus_slave_cfg(
1741 struct afe_param_cdc_slimbus_slave_cfg *sb_slave_cfg)
1742{
1743 int ret;
1744 struct afe_svc_cmd_sb_slave_cfg config;
1745
1746 pr_debug("%s: enter\n", __func__);
1747
1748 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1749 APR_HDR_LEN(APR_HDR_SIZE),
1750 APR_PKT_VER);
1751 config.hdr.pkt_size = sizeof(config);
1752 config.hdr.src_port = 0;
1753 config.hdr.dest_port = 0;
1754 config.hdr.token = IDX_GLOBAL_CFG;
1755 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1756 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1757 sizeof(config.param);
1758 config.param.payload_address_lsw = 0x00;
1759 config.param.payload_address_msw = 0x00;
1760 config.param.mem_map_handle = 0x00;
1761 config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
1762 config.pdata.param_id = AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG;
1763 config.pdata.param_size =
1764 sizeof(struct afe_param_cdc_slimbus_slave_cfg);
1765 config.sb_slave_cfg = *sb_slave_cfg;
1766
1767 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
1768 if (ret)
1769 pr_err("%s: AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG failed %d\n",
1770 __func__, ret);
1771
1772 pr_debug("%s: leave %d\n", __func__, ret);
1773 return ret;
1774}
1775
1776static int afe_send_codec_reg_page_config(
1777 struct afe_param_cdc_reg_page_cfg *cdc_reg_page_cfg)
1778{
1779 struct afe_svc_cmd_cdc_reg_page_cfg config;
1780 int ret;
1781
1782 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1783 APR_HDR_LEN(APR_HDR_SIZE),
1784 APR_PKT_VER);
1785 config.hdr.pkt_size = sizeof(config);
1786 config.hdr.src_port = 0;
1787 config.hdr.dest_port = 0;
1788 config.hdr.token = IDX_GLOBAL_CFG;
1789 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1790 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1791 sizeof(config.param);
1792 config.param.payload_address_lsw = 0x00;
1793 config.param.payload_address_msw = 0x00;
1794 config.param.mem_map_handle = 0x00;
1795 config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
1796 config.pdata.param_id = AFE_PARAM_ID_CDC_REG_PAGE_CFG;
1797 config.pdata.param_size =
1798 sizeof(struct afe_param_cdc_reg_page_cfg);
1799 config.cdc_reg_page_cfg = *cdc_reg_page_cfg;
1800
1801 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
1802 if (ret)
1803 pr_err("%s: AFE_PARAM_ID_CDC_REG_PAGE_CFG failed %d\n",
1804 __func__, ret);
1805
1806 return ret;
1807}
1808
1809static int afe_send_codec_reg_config(
1810 struct afe_param_cdc_reg_cfg_data *cdc_reg_cfg)
1811{
1812 int i, j, ret = -EINVAL;
1813 int pkt_size, payload_size, reg_per_pkt, num_pkts, num_regs;
1814 struct afe_svc_cmd_cdc_reg_cfg *config;
1815 struct afe_svc_cmd_set_param *param;
1816
1817 reg_per_pkt = (APR_MAX_BUF - sizeof(*config)) /
1818 sizeof(struct afe_param_cdc_reg_cfg_payload);
1819 if (reg_per_pkt > 0) {
1820 num_pkts = (cdc_reg_cfg->num_registers / reg_per_pkt) +
1821 (cdc_reg_cfg->num_registers % reg_per_pkt == 0 ? 0 : 1);
1822 } else {
1823 pr_err("%s: Failed to build codec reg config APR packet\n",
1824 __func__);
1825 return -EINVAL;
1826 }
1827
1828 for (j = 0; j < num_pkts; ++j) {
1829 /*
1830 * num_regs is set to reg_per_pkt on each pass through the loop
1831 * except the last, when it is set to the number of registers
1832 * remaining from the total
1833 */
1834 num_regs = (j < (num_pkts - 1) ? reg_per_pkt :
1835 cdc_reg_cfg->num_registers - (reg_per_pkt * j));
1836 payload_size = sizeof(struct afe_param_cdc_reg_cfg_payload) *
1837 num_regs;
1838 pkt_size = sizeof(*config) + payload_size;
1839 pr_debug("%s: pkt_size %d, payload_size %d\n", __func__,
1840 pkt_size, payload_size);
1841 config = kzalloc(pkt_size, GFP_KERNEL);
1842 if (!config)
1843 return -ENOMEM;
1844
1845 config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1846 APR_HDR_LEN(APR_HDR_SIZE),
1847 APR_PKT_VER);
1848 config->hdr.pkt_size = pkt_size;
1849 config->hdr.src_port = 0;
1850 config->hdr.dest_port = 0;
1851 config->hdr.token = IDX_GLOBAL_CFG;
1852 config->hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1853
1854 param = &config->param;
1855 param->payload_size = payload_size;
1856 param->payload_address_lsw = 0x00;
1857 param->payload_address_msw = 0x00;
1858 param->mem_map_handle = 0x00;
1859
1860 for (i = 0; i < num_regs; i++) {
1861 config->reg_data[i].common.module_id =
1862 AFE_MODULE_CDC_DEV_CFG;
1863 config->reg_data[i].common.param_id =
1864 AFE_PARAM_ID_CDC_REG_CFG;
1865 config->reg_data[i].common.param_size =
1866 sizeof(config->reg_data[i].reg_cfg);
1867 config->reg_data[i].reg_cfg =
1868 cdc_reg_cfg->reg_data[i + (j * reg_per_pkt)];
1869 }
1870
1871 ret = afe_apr_send_pkt(config, &this_afe.wait[IDX_GLOBAL_CFG]);
1872 if (ret) {
1873 pr_err("%s: AFE_PARAM_ID_CDC_REG_CFG failed %d\n",
1874 __func__, ret);
1875 kfree(config);
1876 break;
1877 }
1878 kfree(config);
1879 }
1880
1881 return ret;
1882}
1883
1884static int afe_init_cdc_reg_config(void)
1885{
1886 int ret;
1887 struct afe_svc_cmd_init_cdc_reg_cfg config;
1888
1889 pr_debug("%s: enter\n", __func__);
1890 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1891 APR_HDR_LEN(APR_HDR_SIZE),
1892 APR_PKT_VER);
1893 config.hdr.pkt_size = sizeof(config);
1894 config.hdr.src_port = 0;
1895 config.hdr.dest_port = 0;
1896 config.hdr.token = IDX_GLOBAL_CFG;
1897 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1898
1899 config.param.payload_size = sizeof(struct afe_port_param_data_v2);
1900 config.param.payload_address_lsw = 0x00;
1901 config.param.payload_address_msw = 0x00;
1902 config.param.mem_map_handle = 0x00;
1903
1904 config.init.module_id = AFE_MODULE_CDC_DEV_CFG;
1905 config.init.param_id = AFE_PARAM_ID_CDC_REG_CFG_INIT;
1906 config.init.param_size = 0;
1907
1908 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
1909 if (ret) {
1910 pr_err("%s: AFE_PARAM_ID_CDC_INIT_REG_CFG failed %d\n",
1911 __func__, ret);
1912 }
1913
1914 return ret;
1915}
1916
1917static int afe_send_slimbus_slave_port_cfg(
1918 struct afe_param_slimbus_slave_port_cfg *port_config, u16 port_id)
1919{
1920 int ret, index;
1921 struct afe_cmd_hw_mad_slimbus_slave_port_cfg config;
1922
1923 pr_debug("%s: enter, port_id = 0x%x\n", __func__, port_id);
1924 index = q6audio_get_port_index(port_id);
1925 if (index < 0 || index >= AFE_MAX_PORTS) {
1926 pr_err("%s: AFE port index[%d] invalid!\n",
1927 __func__, index);
1928 return -EINVAL;
1929 }
1930 ret = q6audio_validate_port(port_id);
1931 if (ret < 0) {
1932 pr_err("%s: port id = 0x%x ret %d\n", __func__, port_id, ret);
1933 return -EINVAL;
1934 }
1935
1936 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1937 APR_HDR_LEN(APR_HDR_SIZE),
1938 APR_PKT_VER);
1939 config.hdr.pkt_size = sizeof(config);
1940 config.hdr.src_port = 0;
1941 config.hdr.dest_port = 0;
1942 config.hdr.token = index;
1943 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1944 config.param.port_id = port_id;
1945 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
1946 sizeof(config.param);
1947 config.param.payload_address_lsw = 0x00;
1948 config.param.payload_address_msw = 0x00;
1949 config.param.mem_map_handle = 0x00;
1950 config.pdata.module_id = AFE_MODULE_HW_MAD;
1951 config.pdata.param_id = AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG;
1952 config.pdata.param_size = sizeof(*port_config);
1953 config.sb_port_cfg = *port_config;
1954
1955 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
1956 if (ret) {
1957 pr_err("%s: AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG failed %d\n",
1958 __func__, ret);
1959 }
1960 pr_debug("%s: leave %d\n", __func__, ret);
1961 return ret;
1962}
1963static int afe_aanc_port_cfg(void *apr, uint16_t tx_port, uint16_t rx_port)
1964{
1965 struct afe_port_cmd_set_aanc_param cfg;
1966 int ret = 0;
1967 int index = 0;
1968
1969 pr_debug("%s: tx_port 0x%x, rx_port 0x%x\n",
1970 __func__, tx_port, rx_port);
1971
1972 ret = afe_q6_interface_prepare();
1973 if (ret != 0) {
1974 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
1975 return -EINVAL;
1976 }
1977
1978 index = q6audio_get_port_index(tx_port);
1979 if (index < 0 || index >= AFE_MAX_PORTS) {
1980 pr_err("%s: AFE port index[%d] invalid!\n",
1981 __func__, index);
1982 return -EINVAL;
1983 }
1984 ret = q6audio_validate_port(tx_port);
1985 if (ret < 0) {
1986 pr_err("%s: port id: 0x%x ret %d\n", __func__, tx_port, ret);
1987 return -EINVAL;
1988 }
1989 pr_debug("%s: AANC sample rate tx rate: %d rx rate %d\n",
1990 __func__, this_afe.aanc_info.aanc_tx_port_sample_rate,
1991 this_afe.aanc_info.aanc_rx_port_sample_rate);
1992 /*
1993 * If aanc tx sample rate or rx sample rate is zero, skip aanc
1994 * configuration as AFE resampler will fail for invalid sample
1995 * rates.
1996 */
1997 if (!this_afe.aanc_info.aanc_tx_port_sample_rate ||
1998 !this_afe.aanc_info.aanc_rx_port_sample_rate) {
1999 return -EINVAL;
2000 }
2001
2002 cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2003 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2004 cfg.hdr.pkt_size = sizeof(cfg);
2005 cfg.hdr.src_port = 0;
2006 cfg.hdr.dest_port = 0;
2007 cfg.hdr.token = index;
2008 cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2009
2010 cfg.param.port_id = tx_port;
2011 cfg.param.payload_size = sizeof(struct afe_port_param_data_v2) +
2012 sizeof(struct afe_param_aanc_port_cfg);
2013 cfg.param.payload_address_lsw = 0;
2014 cfg.param.payload_address_msw = 0;
2015 cfg.param.mem_map_handle = 0;
2016
2017 cfg.pdata.module_id = AFE_MODULE_AANC;
2018 cfg.pdata.param_id = AFE_PARAM_ID_AANC_PORT_CONFIG;
2019 cfg.pdata.param_size = sizeof(struct afe_param_aanc_port_cfg);
2020 cfg.pdata.reserved = 0;
2021
2022 cfg.data.aanc_port_cfg.aanc_port_cfg_minor_version =
2023 AFE_API_VERSION_AANC_PORT_CONFIG;
2024 cfg.data.aanc_port_cfg.tx_port_sample_rate =
2025 this_afe.aanc_info.aanc_tx_port_sample_rate;
2026 cfg.data.aanc_port_cfg.tx_port_channel_map[0] = AANC_TX_VOICE_MIC;
2027 cfg.data.aanc_port_cfg.tx_port_channel_map[1] = AANC_TX_NOISE_MIC;
2028 cfg.data.aanc_port_cfg.tx_port_channel_map[2] = AANC_TX_ERROR_MIC;
2029 cfg.data.aanc_port_cfg.tx_port_channel_map[3] = AANC_TX_MIC_UNUSED;
2030 cfg.data.aanc_port_cfg.tx_port_channel_map[4] = AANC_TX_MIC_UNUSED;
2031 cfg.data.aanc_port_cfg.tx_port_channel_map[5] = AANC_TX_MIC_UNUSED;
2032 cfg.data.aanc_port_cfg.tx_port_channel_map[6] = AANC_TX_MIC_UNUSED;
2033 cfg.data.aanc_port_cfg.tx_port_channel_map[7] = AANC_TX_MIC_UNUSED;
2034 cfg.data.aanc_port_cfg.tx_port_num_channels = 3;
2035 cfg.data.aanc_port_cfg.rx_path_ref_port_id = rx_port;
2036 cfg.data.aanc_port_cfg.ref_port_sample_rate =
2037 this_afe.aanc_info.aanc_rx_port_sample_rate;
2038
2039 ret = afe_apr_send_pkt((uint32_t *) &cfg, &this_afe.wait[index]);
2040 if (ret) {
2041 pr_err("%s: AFE AANC port config failed for tx_port 0x%x, rx_port 0x%x ret %d\n",
2042 __func__, tx_port, rx_port, ret);
2043 }
2044
2045 return ret;
2046}
2047
2048static int afe_aanc_mod_enable(void *apr, uint16_t tx_port, uint16_t enable)
2049{
2050 struct afe_port_cmd_set_aanc_param cfg;
2051 int ret = 0;
2052 int index = 0;
2053
2054 pr_debug("%s: tx_port 0x%x\n",
2055 __func__, tx_port);
2056
2057 ret = afe_q6_interface_prepare();
2058 if (ret != 0) {
2059 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2060 return -EINVAL;
2061 }
2062
2063 index = q6audio_get_port_index(tx_port);
2064 if (index < 0 || index >= AFE_MAX_PORTS) {
2065 pr_err("%s: AFE port index[%d] invalid!\n",
2066 __func__, index);
2067 return -EINVAL;
2068 }
2069 ret = q6audio_validate_port(tx_port);
2070 if (ret < 0) {
2071 pr_err("%s: port id: 0x%x ret %d\n", __func__, tx_port, ret);
2072 return -EINVAL;
2073 }
2074
2075 cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2076 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2077 cfg.hdr.pkt_size = sizeof(cfg);
2078 cfg.hdr.src_port = 0;
2079 cfg.hdr.dest_port = 0;
2080 cfg.hdr.token = index;
2081 cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2082
2083 cfg.param.port_id = tx_port;
2084 cfg.param.payload_size = sizeof(struct afe_port_param_data_v2) +
2085 sizeof(struct afe_mod_enable_param);
2086 cfg.param.payload_address_lsw = 0;
2087 cfg.param.payload_address_lsw = 0;
2088 cfg.param.mem_map_handle = 0;
2089
2090 cfg.pdata.module_id = AFE_MODULE_AANC;
2091 cfg.pdata.param_id = AFE_PARAM_ID_ENABLE;
2092 cfg.pdata.param_size = sizeof(struct afe_mod_enable_param);
2093 cfg.pdata.reserved = 0;
2094
2095 cfg.data.mod_enable.enable = enable;
2096 cfg.data.mod_enable.reserved = 0;
2097
2098 ret = afe_apr_send_pkt((uint32_t *) &cfg, &this_afe.wait[index]);
2099 if (ret) {
2100 pr_err("%s: AFE AANC enable failed for tx_port 0x%x ret %d\n",
2101 __func__, tx_port, ret);
2102 }
2103 return ret;
2104}
2105
2106static int afe_send_bank_selection_clip(
2107 struct afe_param_id_clip_bank_sel *param)
2108{
2109 int ret;
2110 struct afe_svc_cmd_set_clip_bank_selection config;
2111
2112 if (!param) {
2113 pr_err("%s: Invalid params", __func__);
2114 return -EINVAL;
2115 }
2116 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2117 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2118 config.hdr.pkt_size = sizeof(config);
2119 config.hdr.src_port = 0;
2120 config.hdr.dest_port = 0;
2121 config.hdr.token = IDX_GLOBAL_CFG;
2122 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
2123
2124 config.param.payload_size = sizeof(struct afe_port_param_data_v2) +
2125 sizeof(struct afe_param_id_clip_bank_sel);
2126 config.param.payload_address_lsw = 0x00;
2127 config.param.payload_address_msw = 0x00;
2128 config.param.mem_map_handle = 0x00;
2129
2130 config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
2131 config.pdata.param_id = AFE_PARAM_ID_CLIP_BANK_SEL_CFG;
2132 config.pdata.param_size =
2133 sizeof(struct afe_param_id_clip_bank_sel);
2134 config.bank_sel = *param;
2135 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
2136 if (ret) {
2137 pr_err("%s: AFE_PARAM_ID_CLIP_BANK_SEL_CFG failed %d\n",
2138 __func__, ret);
2139 }
2140 return ret;
2141}
2142int afe_send_aanc_version(
2143 struct afe_param_id_cdc_aanc_version *version_cfg)
2144{
2145 int ret;
2146 struct afe_svc_cmd_cdc_aanc_version config;
2147
2148 pr_debug("%s: enter\n", __func__);
2149 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2150 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2151 config.hdr.pkt_size = sizeof(config);
2152 config.hdr.src_port = 0;
2153 config.hdr.dest_port = 0;
2154 config.hdr.token = IDX_GLOBAL_CFG;
2155 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
2156
2157 config.param.payload_size = sizeof(struct afe_port_param_data_v2) +
2158 sizeof(struct afe_param_id_cdc_aanc_version);
2159 config.param.payload_address_lsw = 0x00;
2160 config.param.payload_address_msw = 0x00;
2161 config.param.mem_map_handle = 0x00;
2162
2163 config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
2164 config.pdata.param_id = AFE_PARAM_ID_CDC_AANC_VERSION;
2165 config.pdata.param_size =
2166 sizeof(struct afe_param_id_cdc_aanc_version);
2167 config.version = *version_cfg;
2168 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
2169 if (ret) {
2170 pr_err("%s: AFE_PARAM_ID_CDC_AANC_VERSION failed %d\n",
2171 __func__, ret);
2172 }
2173 return ret;
2174}
2175
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302176/**
2177 * afe_port_set_mad_type -
2178 * to update mad type
2179 *
2180 * @port_id: AFE port id number
2181 * @mad_type: MAD type enum value
2182 *
2183 * Returns 0 on success or error on failure.
2184 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302185int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type)
2186{
2187 int i;
2188
2189 if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
2190 port_id == AFE_PORT_ID_INT3_MI2S_TX) {
2191 mad_type = MAD_SW_AUDIO;
2192 return 0;
2193 }
2194
2195 i = port_id - SLIMBUS_0_RX;
2196 if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
2197 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2198 return -EINVAL;
2199 }
2200 atomic_set(&afe_ports_mad_type[i], mad_type);
2201 return 0;
2202}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302203EXPORT_SYMBOL(afe_port_set_mad_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302204
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302205/**
2206 * afe_port_get_mad_type -
2207 * to retrieve mad type
2208 *
2209 * @port_id: AFE port id number
2210 *
2211 * Returns valid enum value on success or MAD_HW_NONE on failure.
2212 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302213enum afe_mad_type afe_port_get_mad_type(u16 port_id)
2214{
2215 int i;
2216
2217 if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
2218 port_id == AFE_PORT_ID_INT3_MI2S_TX)
2219 return MAD_SW_AUDIO;
2220
2221 i = port_id - SLIMBUS_0_RX;
2222 if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
2223 pr_debug("%s: Non Slimbus port_id 0x%x\n", __func__, port_id);
2224 return MAD_HW_NONE;
2225 }
2226 return (enum afe_mad_type) atomic_read(&afe_ports_mad_type[i]);
2227}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302228EXPORT_SYMBOL(afe_port_get_mad_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302229
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302230/**
2231 * afe_set_config -
2232 * to configure AFE session with
2233 * specified configuration for given config type
2234 *
2235 * @config_type: config type
2236 * @config_data: configuration to pass to AFE session
2237 * @arg: argument used in specific config types
2238 *
2239 * Returns 0 on success or error value on port start failure.
2240 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302241int afe_set_config(enum afe_config_type config_type, void *config_data, int arg)
2242{
2243 int ret;
2244
2245 pr_debug("%s: enter config_type %d\n", __func__, config_type);
2246 ret = afe_q6_interface_prepare();
2247 if (ret) {
2248 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2249 return ret;
2250 }
2251
2252 switch (config_type) {
2253 case AFE_SLIMBUS_SLAVE_CONFIG:
2254 ret = afe_send_slimbus_slave_cfg(config_data);
2255 if (!ret)
2256 ret = afe_init_cdc_reg_config();
2257 else
2258 pr_err("%s: Sending slimbus slave config failed %d\n",
2259 __func__, ret);
2260 break;
2261 case AFE_CDC_REGISTERS_CONFIG:
2262 ret = afe_send_codec_reg_config(config_data);
2263 break;
2264 case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
2265 ret = afe_send_slimbus_slave_port_cfg(config_data, arg);
2266 break;
2267 case AFE_AANC_VERSION:
2268 ret = afe_send_aanc_version(config_data);
2269 break;
2270 case AFE_CLIP_BANK_SEL:
2271 ret = afe_send_bank_selection_clip(config_data);
2272 break;
2273 case AFE_CDC_CLIP_REGISTERS_CONFIG:
2274 ret = afe_send_codec_reg_config(config_data);
2275 break;
2276 case AFE_CDC_REGISTER_PAGE_CONFIG:
2277 ret = afe_send_codec_reg_page_config(config_data);
2278 break;
2279 default:
2280 pr_err("%s: unknown configuration type %d",
2281 __func__, config_type);
2282 ret = -EINVAL;
2283 }
2284
2285 if (!ret)
2286 set_bit(config_type, &afe_configured_cmd);
2287
2288 return ret;
2289}
2290EXPORT_SYMBOL(afe_set_config);
2291
2292/*
2293 * afe_clear_config - If SSR happens ADSP loses AFE configs, let AFE driver know
2294 * about the state so client driver can wait until AFE is
2295 * reconfigured.
2296 */
2297void afe_clear_config(enum afe_config_type config)
2298{
2299 clear_bit(config, &afe_configured_cmd);
2300}
2301EXPORT_SYMBOL(afe_clear_config);
2302
2303bool afe_has_config(enum afe_config_type config)
2304{
2305 return !!test_bit(config, &afe_configured_cmd);
2306}
2307
2308int afe_send_spdif_clk_cfg(struct afe_param_id_spdif_clk_cfg *cfg,
2309 u16 port_id)
2310{
2311 struct afe_spdif_clk_config_command clk_cfg;
2312 int ret = 0;
2313 int index = 0;
2314
2315 if (!cfg) {
2316 pr_err("%s: Error, no configuration data\n", __func__);
2317 ret = -EINVAL;
2318 return ret;
2319 }
2320 index = q6audio_get_port_index(port_id);
2321 if (index < 0 || index >= AFE_MAX_PORTS) {
2322 pr_err("%s: AFE port index[%d] invalid!\n",
2323 __func__, index);
2324 return -EINVAL;
2325 }
2326 ret = q6audio_validate_port(port_id);
2327 if (ret < 0) {
2328 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2329 return -EINVAL;
2330 }
2331
2332 ret = afe_q6_interface_prepare();
2333 if (ret) {
2334 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2335 return ret;
2336 }
2337 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2338 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2339 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
2340 clk_cfg.hdr.src_port = 0;
2341 clk_cfg.hdr.dest_port = 0;
2342 clk_cfg.hdr.token = index;
2343
2344 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2345 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
2346 clk_cfg.param.payload_address_lsw = 0x00;
2347 clk_cfg.param.payload_address_msw = 0x00;
2348 clk_cfg.param.mem_map_handle = 0x00;
2349 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2350 clk_cfg.pdata.param_id = AFE_PARAM_ID_SPDIF_CLK_CONFIG;
2351 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
2352 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
2353 - sizeof(clk_cfg.param);
2354 clk_cfg.clk_cfg = *cfg;
2355
2356 pr_debug("%s: Minor version = 0x%x clk val = %d\n"
2357 "clk root = 0x%x\n port id = 0x%x\n",
2358 __func__, cfg->clk_cfg_minor_version,
2359 cfg->clk_value, cfg->clk_root,
2360 q6audio_get_port_id(port_id));
2361
2362 atomic_set(&this_afe.state, 1);
2363 atomic_set(&this_afe.status, 0);
2364 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
2365 if (ret < 0) {
2366 pr_err("%s: AFE send clock config for port 0x%x failed ret = %d\n",
2367 __func__, port_id, ret);
2368 ret = -EINVAL;
2369 goto fail_cmd;
2370 }
2371
2372 ret = wait_event_timeout(this_afe.wait[index],
2373 (atomic_read(&this_afe.state) == 0),
2374 msecs_to_jiffies(TIMEOUT_MS));
2375 if (!ret) {
2376 pr_err("%s: wait_event timeout\n",
2377 __func__);
2378 ret = -EINVAL;
2379 goto fail_cmd;
2380 }
2381 if (atomic_read(&this_afe.status) > 0) {
2382 pr_err("%s: config cmd failed [%s]\n",
2383 __func__, adsp_err_get_err_str(
2384 atomic_read(&this_afe.status)));
2385 ret = adsp_err_get_lnx_err_code(
2386 atomic_read(&this_afe.status));
2387 goto fail_cmd;
2388 }
2389
2390fail_cmd:
2391 return ret;
2392}
2393
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302394/**
2395 * afe_send_spdif_ch_status_cfg -
2396 * to configure AFE session with
2397 * specified channel status configuration
2398 *
2399 * @ch_status_cfg: channel status configutation
2400 * @port_id: AFE port id number
2401 *
2402 * Returns 0 on success or error value on port start failure.
2403 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302404int afe_send_spdif_ch_status_cfg(struct afe_param_id_spdif_ch_status_cfg
2405 *ch_status_cfg, u16 port_id)
2406{
2407 struct afe_spdif_chstatus_config_command ch_status;
2408 int ret = 0;
2409 int index = 0;
2410
2411 if (!ch_status_cfg) {
2412 pr_err("%s: Error, no configuration data\n", __func__);
2413 ret = -EINVAL;
2414 return ret;
2415 }
2416 index = q6audio_get_port_index(port_id);
2417 if (index < 0 || index >= AFE_MAX_PORTS) {
2418 pr_err("%s: AFE port index[%d] invalid!\n",
2419 __func__, index);
2420 return -EINVAL;
2421 }
2422 ret = q6audio_validate_port(port_id);
2423 if (ret < 0) {
2424 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2425 return -EINVAL;
2426 }
2427
2428 ret = afe_q6_interface_prepare();
2429 if (ret != 0) {
2430 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2431 return ret;
2432 }
2433 ch_status.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2434 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2435 ch_status.hdr.pkt_size = sizeof(ch_status_cfg);
2436 ch_status.hdr.src_port = 0;
2437 ch_status.hdr.dest_port = 0;
2438 ch_status.hdr.token = index;
2439
2440 ch_status.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2441 ch_status.param.port_id = q6audio_get_port_id(port_id);
2442 ch_status.param.payload_address_lsw = 0x00;
2443 ch_status.param.payload_address_msw = 0x00;
2444 ch_status.param.mem_map_handle = 0x00;
2445 ch_status.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2446 ch_status.pdata.param_id = AFE_PARAM_ID_SPDIF_CLK_CONFIG;
2447 ch_status.pdata.param_size = sizeof(ch_status.ch_status);
2448 ch_status.param.payload_size = sizeof(ch_status)
2449 - sizeof(struct apr_hdr) - sizeof(ch_status.param);
2450 ch_status.ch_status = *ch_status_cfg;
2451
2452 atomic_set(&this_afe.state, 1);
2453 atomic_set(&this_afe.status, 0);
2454 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &ch_status);
2455 if (ret < 0) {
2456 pr_err("%s: AFE send channel status for port 0x%x failed ret = %d\n",
2457 __func__, port_id, ret);
2458 ret = -EINVAL;
2459 goto fail_cmd;
2460 }
2461
2462 ret = wait_event_timeout(this_afe.wait[index],
2463 (atomic_read(&this_afe.state) == 0),
2464 msecs_to_jiffies(TIMEOUT_MS));
2465 if (!ret) {
2466 pr_err("%s: wait_event timeout\n",
2467 __func__);
2468 ret = -EINVAL;
2469 goto fail_cmd;
2470 }
2471 if (atomic_read(&this_afe.status) > 0) {
2472 pr_err("%s: config cmd failed [%s]\n",
2473 __func__, adsp_err_get_err_str(
2474 atomic_read(&this_afe.status)));
2475 ret = adsp_err_get_lnx_err_code(
2476 atomic_read(&this_afe.status));
2477 goto fail_cmd;
2478 }
2479
2480fail_cmd:
2481 return ret;
2482}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302483EXPORT_SYMBOL(afe_send_spdif_ch_status_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302484
2485static int afe_send_cmd_port_start(u16 port_id)
2486{
2487 struct afe_port_cmd_device_start start;
2488 int ret, index;
2489
2490 pr_debug("%s: enter\n", __func__);
2491 index = q6audio_get_port_index(port_id);
2492 if (index < 0 || index >= AFE_MAX_PORTS) {
2493 pr_err("%s: AFE port index[%d] invalid!\n",
2494 __func__, index);
2495 return -EINVAL;
2496 }
2497 ret = q6audio_validate_port(port_id);
2498 if (ret < 0) {
2499 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2500 return -EINVAL;
2501 }
2502
2503 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2504 APR_HDR_LEN(APR_HDR_SIZE),
2505 APR_PKT_VER);
2506 start.hdr.pkt_size = sizeof(start);
2507 start.hdr.src_port = 0;
2508 start.hdr.dest_port = 0;
2509 start.hdr.token = index;
2510 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
2511 start.port_id = q6audio_get_port_id(port_id);
2512 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
2513 __func__, start.hdr.opcode, start.port_id);
2514
2515 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
2516 if (ret) {
2517 pr_err("%s: AFE enable for port 0x%x failed %d\n", __func__,
2518 port_id, ret);
2519 } else if (this_afe.task != current) {
2520 this_afe.task = current;
2521 pr_debug("task_name = %s pid = %d\n",
2522 this_afe.task->comm, this_afe.task->pid);
2523 }
2524
2525 return ret;
2526}
2527
2528static int afe_aanc_start(uint16_t tx_port_id, uint16_t rx_port_id)
2529{
2530 int ret;
2531
2532 pr_debug("%s: Tx port is 0x%x, Rx port is 0x%x\n",
2533 __func__, tx_port_id, rx_port_id);
2534 ret = afe_aanc_port_cfg(this_afe.apr, tx_port_id, rx_port_id);
2535 if (ret) {
2536 pr_err("%s: Send AANC Port Config failed %d\n",
2537 __func__, ret);
2538 goto fail_cmd;
2539 }
2540 send_afe_cal_type(AFE_AANC_CAL, tx_port_id);
2541
2542fail_cmd:
2543 return ret;
2544}
2545
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302546/**
2547 * afe_spdif_port_start - to configure AFE session with
2548 * specified port configuration
2549 *
2550 * @port_id: AFE port id number
2551 * @spdif_port: spdif port configutation
2552 * @rate: sampling rate of port
2553 *
2554 * Returns 0 on success or error value on port start failure.
2555 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302556int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port,
2557 u32 rate)
2558{
2559 struct afe_audioif_config_command config;
2560 int ret = 0;
2561 int index = 0;
2562 uint16_t port_index;
2563
2564 if (!spdif_port) {
2565 pr_err("%s: Error, no configuration data\n", __func__);
2566 ret = -EINVAL;
2567 return ret;
2568 }
2569
2570 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2571
2572 index = q6audio_get_port_index(port_id);
2573 if (index < 0 || index >= AFE_MAX_PORTS) {
2574 pr_err("%s: AFE port index[%d] invalid!\n",
2575 __func__, index);
2576 return -EINVAL;
2577 }
2578 ret = q6audio_validate_port(port_id);
2579 if (ret < 0) {
2580 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2581 return -EINVAL;
2582 }
2583
2584 afe_send_cal(port_id);
2585 afe_send_hw_delay(port_id, rate);
2586
2587 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2588 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2589 config.hdr.pkt_size = sizeof(config);
2590 config.hdr.src_port = 0;
2591 config.hdr.dest_port = 0;
2592 config.hdr.token = index;
2593 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2594 config.param.port_id = q6audio_get_port_id(port_id);
2595 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
2596 sizeof(config.param);
2597 config.param.payload_address_lsw = 0x00;
2598 config.param.payload_address_msw = 0x00;
2599 config.param.mem_map_handle = 0x00;
2600 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2601 config.pdata.param_id = AFE_PARAM_ID_SPDIF_CONFIG;
2602 config.pdata.param_size = sizeof(config.port);
2603 config.port.spdif = spdif_port->cfg;
2604 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2605 if (ret) {
2606 pr_err("%s: AFE enable for port 0x%x failed ret = %d\n",
2607 __func__, port_id, ret);
2608 goto fail_cmd;
2609 }
2610
2611 port_index = afe_get_port_index(port_id);
2612 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
2613 this_afe.afe_sample_rates[port_index] = rate;
2614 } else {
2615 pr_err("%s: Invalid port index %d\n", __func__, port_index);
2616 ret = -EINVAL;
2617 goto fail_cmd;
2618 }
2619
2620 ret = afe_send_spdif_ch_status_cfg(&spdif_port->ch_status, port_id);
2621 if (ret < 0) {
2622 pr_err("%s: afe send failed %d\n", __func__, ret);
2623 goto fail_cmd;
2624 }
2625
2626 return afe_send_cmd_port_start(port_id);
2627
2628fail_cmd:
2629 return ret;
2630}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302631EXPORT_SYMBOL(afe_spdif_port_start);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302632
2633int afe_send_slot_mapping_cfg(
2634 struct afe_param_id_slot_mapping_cfg *slot_mapping_cfg,
2635 u16 port_id)
2636{
2637 struct afe_slot_mapping_config_command config;
2638 int ret = 0;
2639 int index = 0;
2640
2641 if (!slot_mapping_cfg) {
2642 pr_err("%s: Error, no configuration data\n", __func__);
2643 return -EINVAL;
2644 }
2645
2646 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2647
2648 index = q6audio_get_port_index(port_id);
2649 if (index < 0 || index >= AFE_MAX_PORTS) {
2650 pr_err("%s: AFE port index[%d] invalid!\n",
2651 __func__, index);
2652 return -EINVAL;
2653 }
2654 ret = q6audio_validate_port(port_id);
2655 if (ret < 0) {
2656 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2657 return -EINVAL;
2658 }
2659
2660 memset(&config, 0, sizeof(config));
2661 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2662 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2663 config.hdr.pkt_size = sizeof(config);
2664 config.hdr.src_port = 0;
2665 config.hdr.dest_port = 0;
2666 config.hdr.token = index;
2667
2668 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2669 config.param.port_id = q6audio_get_port_id(port_id);
2670 config.param.payload_size = sizeof(config)
2671 - sizeof(struct apr_hdr) - sizeof(config.param);
2672 config.param.payload_address_lsw = 0x00;
2673 config.param.payload_address_msw = 0x00;
2674 config.param.mem_map_handle = 0x00;
2675 config.pdata.module_id = AFE_MODULE_TDM;
2676 config.pdata.param_id = AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG;
2677 config.pdata.param_size = sizeof(config.slot_mapping);
2678 config.slot_mapping = *slot_mapping_cfg;
2679
2680 atomic_set(&this_afe.state, 1);
2681 atomic_set(&this_afe.status, 0);
2682 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
2683 if (ret < 0) {
2684 pr_err("%s: AFE send slot mapping for port 0x%x failed ret = %d\n",
2685 __func__, port_id, ret);
2686 ret = -EINVAL;
2687 goto fail_cmd;
2688 }
2689
2690 ret = wait_event_timeout(this_afe.wait[index],
2691 (atomic_read(&this_afe.state) == 0),
2692 msecs_to_jiffies(TIMEOUT_MS));
2693 if (!ret) {
2694 pr_err("%s: wait_event timeout\n",
2695 __func__);
2696 ret = -EINVAL;
2697 goto fail_cmd;
2698 }
2699 if (atomic_read(&this_afe.status) > 0) {
2700 pr_err("%s: config cmd failed [%s]\n",
2701 __func__, adsp_err_get_err_str(
2702 atomic_read(&this_afe.status)));
2703 ret = adsp_err_get_lnx_err_code(
2704 atomic_read(&this_afe.status));
2705 goto fail_cmd;
2706 }
2707
2708fail_cmd:
2709 return ret;
2710}
2711
2712int afe_send_custom_tdm_header_cfg(
2713 struct afe_param_id_custom_tdm_header_cfg *custom_tdm_header_cfg,
2714 u16 port_id)
2715{
2716 struct afe_custom_tdm_header_config_command config;
2717 int ret = 0;
2718 int index = 0;
2719
2720 if (!custom_tdm_header_cfg) {
2721 pr_err("%s: Error, no configuration data\n", __func__);
2722 return -EINVAL;
2723 }
2724
2725 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2726
2727 index = q6audio_get_port_index(port_id);
2728 if (index < 0 || index >= AFE_MAX_PORTS) {
2729 pr_err("%s: AFE port index[%d] invalid!\n",
2730 __func__, index);
2731 return -EINVAL;
2732 }
2733 ret = q6audio_validate_port(port_id);
2734 if (ret < 0) {
2735 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2736 return -EINVAL;
2737 }
2738
2739 memset(&config, 0, sizeof(config));
2740 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2741 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2742 config.hdr.pkt_size = sizeof(config);
2743 config.hdr.src_port = 0;
2744 config.hdr.dest_port = 0;
2745 config.hdr.token = index;
2746
2747 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2748 config.param.port_id = q6audio_get_port_id(port_id);
2749 config.param.payload_size = sizeof(config)
2750 - sizeof(struct apr_hdr) - sizeof(config.param);
2751 config.param.payload_address_lsw = 0x00;
2752 config.param.payload_address_msw = 0x00;
2753 config.param.mem_map_handle = 0x00;
2754 config.pdata.module_id = AFE_MODULE_TDM;
2755 config.pdata.param_id = AFE_PARAM_ID_CUSTOM_TDM_HEADER_CONFIG;
2756 config.pdata.param_size = sizeof(config.custom_tdm_header);
2757 config.custom_tdm_header = *custom_tdm_header_cfg;
2758
2759 atomic_set(&this_afe.state, 1);
2760 atomic_set(&this_afe.status, 0);
2761 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
2762 if (ret < 0) {
2763 pr_err("%s: AFE send custom tdm header for port 0x%x failed ret = %d\n",
2764 __func__, port_id, ret);
2765 ret = -EINVAL;
2766 goto fail_cmd;
2767 }
2768
2769 ret = wait_event_timeout(this_afe.wait[index],
2770 (atomic_read(&this_afe.state) == 0),
2771 msecs_to_jiffies(TIMEOUT_MS));
2772 if (!ret) {
2773 pr_err("%s: wait_event timeout\n",
2774 __func__);
2775 ret = -EINVAL;
2776 goto fail_cmd;
2777 }
2778 if (atomic_read(&this_afe.status) > 0) {
2779 pr_err("%s: config cmd failed [%s]\n",
2780 __func__, adsp_err_get_err_str(
2781 atomic_read(&this_afe.status)));
2782 ret = adsp_err_get_lnx_err_code(
2783 atomic_read(&this_afe.status));
2784 goto fail_cmd;
2785 }
2786
2787fail_cmd:
2788 return ret;
2789}
2790
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302791/**
2792 * afe_tdm_port_start - to configure AFE session with
2793 * specified port configuration
2794 *
2795 * @port_id: AFE port id number
2796 * @tdm_port: TDM port configutation
2797 * @rate: sampling rate of port
2798 * @num_groups: number of TDM groups
2799 *
2800 * Returns 0 on success or error value on port start failure.
2801 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302802int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
2803 u32 rate, u16 num_groups)
2804{
2805 struct afe_audioif_config_command config;
2806 int ret = 0;
2807 int index = 0;
2808 uint16_t port_index = 0;
2809 enum afe_mad_type mad_type = MAD_HW_NONE;
2810
2811 if (!tdm_port) {
2812 pr_err("%s: Error, no configuration data\n", __func__);
2813 return -EINVAL;
2814 }
2815
2816 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2817
2818 index = q6audio_get_port_index(port_id);
2819 if (index < 0 || index >= AFE_MAX_PORTS) {
2820 pr_err("%s: AFE port index[%d] invalid!\n",
2821 __func__, index);
2822 return -EINVAL;
2823 }
2824 ret = q6audio_validate_port(port_id);
2825 if (ret < 0) {
2826 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2827 return -EINVAL;
2828 }
2829
2830 ret = afe_q6_interface_prepare();
2831 if (ret != 0) {
2832 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2833 return ret;
2834 }
2835
2836 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
2837 this_afe.afe_sample_rates[index] = rate;
2838
2839 if (this_afe.rt_cb)
2840 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
2841 }
2842
Xiaoyu Ye13da4822017-09-18 17:46:30 -07002843 /* Also send the topology id here: */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302844 port_index = afe_get_port_index(port_id);
Xiaoyu Ye13da4822017-09-18 17:46:30 -07002845 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302846 /* One time call: only for first time */
2847 afe_send_custom_topology();
2848 afe_send_port_topology_id(port_id);
2849 afe_send_cal(port_id);
2850 afe_send_hw_delay(port_id, rate);
2851 }
2852
2853 /* Start SW MAD module */
2854 mad_type = afe_port_get_mad_type(port_id);
2855 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
2856 mad_type);
2857 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
2858 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
2859 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
2860 pr_err("%s: AFE isn't configured yet for\n"
2861 "HW MAD try Again\n", __func__);
2862 ret = -EAGAIN;
2863 goto fail_cmd;
2864 }
2865 ret = afe_turn_onoff_hw_mad(mad_type, true);
2866 if (ret) {
2867 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
2868 __func__, ret);
2869 goto fail_cmd;
2870 }
2871 }
2872
2873 memset(&config, 0, sizeof(config));
2874 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2875 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2876 config.hdr.pkt_size = sizeof(config);
2877 config.hdr.src_port = 0;
2878 config.hdr.dest_port = 0;
2879 config.hdr.token = index;
2880 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2881 config.param.port_id = q6audio_get_port_id(port_id);
2882 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
2883 sizeof(config.param);
2884 config.param.payload_address_lsw = 0x00;
2885 config.param.payload_address_msw = 0x00;
2886 config.param.mem_map_handle = 0x00;
2887 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2888 config.pdata.param_id = AFE_PARAM_ID_TDM_CONFIG;
2889 config.pdata.param_size = sizeof(config.port);
2890 config.port.tdm = tdm_port->tdm;
2891
2892 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2893 if (ret) {
2894 pr_err("%s: AFE enable for port 0x%x failed ret = %d\n",
2895 __func__, port_id, ret);
2896 goto fail_cmd;
2897 }
2898
2899 port_index = afe_get_port_index(port_id);
2900 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
2901 this_afe.afe_sample_rates[port_index] = rate;
2902 } else {
2903 pr_err("%s: Invalid port index %d\n", __func__, port_index);
2904 ret = -EINVAL;
2905 goto fail_cmd;
2906 }
Xiaoyu Ye13da4822017-09-18 17:46:30 -07002907
2908 ret = afe_send_slot_mapping_cfg(&tdm_port->slot_mapping,
2909 port_id);
2910 if (ret < 0) {
2911 pr_err("%s: afe send failed %d\n", __func__, ret);
2912 goto fail_cmd;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302913 }
2914
2915 if (tdm_port->custom_tdm_header.header_type) {
2916 ret = afe_send_custom_tdm_header_cfg(
2917 &tdm_port->custom_tdm_header, port_id);
2918 if (ret < 0) {
2919 pr_err("%s: afe send failed %d\n", __func__, ret);
2920 goto fail_cmd;
2921 }
2922 }
2923
2924 ret = afe_send_cmd_port_start(port_id);
2925
2926fail_cmd:
2927 return ret;
2928}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302929EXPORT_SYMBOL(afe_tdm_port_start);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302930
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302931/**
2932 * afe_set_cal_mode -
2933 * set cal mode for AFE calibration
2934 *
2935 * @port_id: AFE port id number
2936 * @afe_cal_mode: AFE calib mode
2937 *
2938 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302939void afe_set_cal_mode(u16 port_id, enum afe_cal_mode afe_cal_mode)
2940{
2941 uint16_t port_index;
2942
2943 port_index = afe_get_port_index(port_id);
2944 this_afe.afe_cal_mode[port_index] = afe_cal_mode;
2945}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302946EXPORT_SYMBOL(afe_set_cal_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302947
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302948/**
2949 * afe_set_routing_callback -
2950 * Update callback function for routing
2951 *
2952 * @cb: callback function to update with
2953 *
2954 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302955void afe_set_routing_callback(routing_cb cb)
2956{
2957 this_afe.rt_cb = cb;
2958}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302959EXPORT_SYMBOL(afe_set_routing_callback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302960
2961int afe_port_send_usb_dev_param(u16 port_id, union afe_port_config *afe_config)
2962{
2963 struct afe_usb_audio_dev_param_command config;
2964 int ret = 0, index = 0;
2965
2966 if (!afe_config) {
2967 pr_err("%s: Error, no configuration data\n", __func__);
2968 ret = -EINVAL;
2969 goto exit;
2970 }
2971 index = q6audio_get_port_index(port_id);
2972 if (index < 0 || index >= AFE_MAX_PORTS) {
2973 pr_err("%s: AFE port index[%d] invalid! for port ID 0x%x\n",
2974 __func__, index, port_id);
2975 ret = -EINVAL;
2976 goto exit;
2977 }
2978 memset(&config, 0, sizeof(config));
2979 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2980 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2981 config.hdr.pkt_size = sizeof(config);
2982 config.hdr.src_port = 0;
2983 config.hdr.dest_port = 0;
2984 config.hdr.token = index;
2985 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2986 config.param.port_id = q6audio_get_port_id(port_id);
2987 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
2988 sizeof(config.param);
2989 config.param.payload_address_lsw = 0x00;
2990 config.param.payload_address_msw = 0x00;
2991 config.param.mem_map_handle = 0x00;
2992 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2993 config.pdata.param_id = AFE_PARAM_ID_USB_AUDIO_DEV_PARAMS;
2994 config.pdata.param_size = sizeof(config.usb_dev);
2995 config.usb_dev.cfg_minor_version =
2996 AFE_API_MINIOR_VERSION_USB_AUDIO_CONFIG;
2997 config.usb_dev.dev_token = afe_config->usb_audio.dev_token;
2998
2999 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3000 if (ret) {
3001 pr_err("%s: AFE device param cmd failed %d\n",
3002 __func__, ret);
3003 ret = -EINVAL;
3004 goto exit;
3005 }
3006
3007 config.pdata.param_id = AFE_PARAM_ID_USB_AUDIO_DEV_LPCM_FMT;
3008 config.pdata.param_size = sizeof(config.lpcm_fmt);
3009 config.lpcm_fmt.cfg_minor_version =
3010 AFE_API_MINIOR_VERSION_USB_AUDIO_CONFIG;
3011 config.lpcm_fmt.endian = afe_config->usb_audio.endian;
3012
3013 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3014 if (ret) {
3015 pr_err("%s: AFE device param cmd LPCM_FMT failed %d\n",
3016 __func__, ret);
3017 ret = -EINVAL;
3018 goto exit;
3019 }
3020
Haynes Mathew George7ed9b512018-02-28 18:18:09 -08003021 config.pdata.param_id = AFE_PARAM_ID_PORT_LATENCY_MODE_CONFIG;
3022 config.pdata.param_size = sizeof(config.latency_config);
3023 config.latency_config.minor_version =
3024 AFE_API_MINOR_VERSION_USB_AUDIO_LATENCY_MODE;
3025 if (afe_config->usb_audio.service_interval > 0 &&
3026 afe_config->usb_audio.service_interval <= HS_USB_INTERVAL_US)
3027 config.latency_config.mode = AFE_PORT_LOW_LATENCY_MODE;
3028 else
3029 config.latency_config.mode = AFE_PORT_DEFAULT_LATENCY_MODE;
3030
3031 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3032 if (ret) {
3033 pr_debug("%s: AFE device param cmd latency mode failed %d\n",
3034 __func__, ret);
3035 /* latency mode is an optimization, not a requirement */
3036 ret = 0;
3037 goto exit;
3038 }
3039
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303040exit:
3041 return ret;
3042}
3043
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003044static int q6afe_send_dec_config(u16 port_id,
3045 union afe_port_config afe_config,
3046 struct afe_dec_config *cfg)
3047{
3048 struct afe_audioif_config_command config;
3049 int index = 0;
3050 int ret = 0;
3051 size_t payload_size = sizeof(config) - sizeof(struct apr_hdr) -
3052 sizeof(config.param) - sizeof(config.port);
3053
3054 index = q6audio_get_port_index(port_id);
3055 if (index < 0) {
3056 pr_err("%s: Invalid index number: %d\n", __func__, index);
3057 return -EINVAL;
3058 }
3059 memset(&config, 0, sizeof(config));
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 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3069 config.param.port_id = q6audio_get_port_id(port_id);
3070 config.param.payload_address_lsw = 0x00;
3071 config.param.payload_address_msw = 0x00;
3072 config.param.mem_map_handle = 0x00;
3073 config.pdata.module_id = AFE_MODULE_ID_DECODER;
3074 config.param.payload_size =
3075 payload_size + sizeof(config.port.dec_depkt_id_param);
3076 pr_debug("%s:sending AFE_DECODER_PARAM_ID_DEPACKETIZER to DSP payload = %d\n",
3077 __func__, config.param.payload_size);
3078 config.pdata.param_id = AFE_DECODER_PARAM_ID_DEPACKETIZER_ID;
3079 config.pdata.param_size = sizeof(config.port.dec_depkt_id_param);
3080 config.port.dec_depkt_id_param.dec_depacketizer_id =
3081 AFE_MODULE_ID_DEPACKETIZER_COP;
3082 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3083 if (ret) {
3084 pr_err("%s: AFE_DECODER_PARAM_ID_DEPACKETIZER for port 0x%x failed %d\n",
3085 __func__, port_id, ret);
3086 goto exit;
3087 }
3088
3089 config.param.payload_size =
3090 payload_size + sizeof(config.port.imc_info_param);
3091 pr_debug("%s:sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload = %d\n",
3092 __func__, config.param.payload_size);
3093 config.pdata.param_id = AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION;
3094 config.pdata.param_size = sizeof(config.port.imc_info_param);
3095 config.port.imc_info_param.imc_info = cfg->abr_dec_cfg.imc_info;
3096 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3097 if (ret) {
3098 pr_err("%s: AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION for port 0x%x failed %d\n",
3099 __func__, port_id, ret);
3100 goto exit;
3101 }
3102
3103 config.param.payload_size =
3104 payload_size + sizeof(config.port.media_type);
3105 config.pdata.param_size = sizeof(config.port.media_type);
3106
3107 pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP\n",
3108 __func__);
3109 config.pdata.module_id = AFE_MODULE_PORT;
3110 config.pdata.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
3111 config.port.media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
3112 config.port.media_type.sample_rate = afe_config.slim_sch.sample_rate;
3113 config.port.media_type.bit_width =
3114 afe_config.slim_sch.bit_width;
3115 config.port.media_type.num_channels =
3116 afe_config.slim_sch.num_channels;
3117 config.port.media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
3118 config.port.media_type.reserved = 0;
3119
3120 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3121 if (ret) {
3122 pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
3123 __func__, port_id, ret);
3124 goto exit;
3125 }
3126
3127exit:
3128 return ret;
3129}
3130
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303131static int q6afe_send_enc_config(u16 port_id,
3132 union afe_enc_config_data *cfg, u32 format,
3133 union afe_port_config afe_config,
Preetam Singh Ranawatf746a872017-10-20 18:13:14 +05303134 u16 afe_in_channels, u16 afe_in_bit_width,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303135 u32 scrambler_mode, u32 mono_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303136{
3137 struct afe_audioif_config_command config;
3138 int index;
3139 int ret;
3140 int payload_size = sizeof(config) - sizeof(struct apr_hdr) -
3141 sizeof(config.param) - sizeof(config.port);
3142
3143 pr_debug("%s:update DSP for enc format = %d\n", __func__, format);
3144 if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 &&
Preetam Singh Ranawat54028492017-09-04 11:42:26 +05303145 format != ASM_MEDIA_FMT_APTX && format != ASM_MEDIA_FMT_APTX_HD &&
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05303146 format != ASM_MEDIA_FMT_CELT && format != ASM_MEDIA_FMT_LDAC) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303147 pr_err("%s:Unsuppported format Ignore AFE config\n", __func__);
3148 return 0;
3149 }
3150 memset(&config, 0, sizeof(config));
3151 index = q6audio_get_port_index(port_id);
3152 if (index < 0) {
3153 pr_err("%s: Invalid index number: %d\n", __func__, index);
3154 return -EINVAL;
3155 }
3156
3157 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3158 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3159 config.hdr.pkt_size = sizeof(config);
3160 config.hdr.src_port = 0;
3161 config.hdr.dest_port = 0;
3162 config.hdr.token = index;
3163
3164 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3165 config.param.port_id = q6audio_get_port_id(port_id);
3166 config.param.payload_size = payload_size + sizeof(config.port.enc_fmt);
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_ID_ENCODER;
3171 config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_FMT_ID;
3172 config.pdata.param_size = sizeof(config.port.enc_fmt);
3173 config.port.enc_fmt.fmt_id = format;
3174 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENC_FMT_ID payload: %d\n",
3175 __func__, config.param.payload_size);
3176 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3177 if (ret) {
3178 pr_err("%s:unable to send AFE_ENCODER_PARAM_ID_ENC_FMT_ID",
3179 __func__);
3180 goto exit;
3181 }
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003182 if (format == ASM_MEDIA_FMT_LDAC) {
3183 config.param.payload_size = payload_size
3184 + sizeof(config.port.enc_blk_param)
3185 - sizeof(struct afe_abr_enc_cfg_t);
3186 config.pdata.param_size = sizeof(config.port.enc_blk_param)
3187 - sizeof(struct afe_abr_enc_cfg_t);
3188 config.port.enc_blk_param.enc_cfg_blk_size =
3189 sizeof(config.port.enc_blk_param.enc_blk_config)
3190 - sizeof(struct afe_abr_enc_cfg_t);
3191 } else {
3192 config.param.payload_size = payload_size
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303193 + sizeof(config.port.enc_blk_param);
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003194 config.pdata.param_size = sizeof(config.port.enc_blk_param);
3195 config.port.enc_blk_param.enc_cfg_blk_size =
3196 sizeof(config.port.enc_blk_param.enc_blk_config);
3197 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303198 pr_debug("%s:send AFE_ENCODER_PARAM_ID_ENC_CFG_BLK to DSP payload:%d\n",
3199 __func__, config.param.payload_size);
3200 config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_CFG_BLK;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303201 config.port.enc_blk_param.enc_blk_config = *cfg;
3202 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3203 if (ret) {
3204 pr_err("%s: AFE_ENCODER_PARAM_ID_ENC_CFG_BLK for port 0x%x failed %d\n",
3205 __func__, port_id, ret);
3206 goto exit;
3207 }
3208
Preetam Singh Ranawat899b78b2017-09-07 12:36:06 -07003209 if (format == ASM_MEDIA_FMT_APTX) {
3210 config.param.payload_size =
3211 payload_size + sizeof(config.port.sync_mode_param);
3212 pr_debug("%s: sending AFE_PARAM_ID_APTX_SYNC_MODE to DSP",
3213 __func__);
3214 config.pdata.param_id = AFE_PARAM_ID_APTX_SYNC_MODE;
3215 config.pdata.param_size = sizeof(config.port.sync_mode_param);
3216 config.port.sync_mode_param.sync_mode =
3217 config.port.enc_blk_param.enc_blk_config.aptx_config.
3218 aptx_v2_cfg.sync_mode;
3219 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3220 if (ret) {
3221 pr_err("%s: AFE_PARAM_ID_APTX_SYNC_MODE for port 0x%x failed %d\n",
3222 __func__, port_id, ret);
3223 goto exit;
3224 }
3225 }
3226
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303227 config.param.payload_size =
3228 payload_size + sizeof(config.port.enc_pkt_id_param);
3229 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_PACKETIZER to DSP payload = %d",
3230 __func__, config.param.payload_size);
3231 config.pdata.param_id = AFE_ENCODER_PARAM_ID_PACKETIZER_ID;
3232 config.pdata.param_size = sizeof(config.port.enc_pkt_id_param);
3233 config.port.enc_pkt_id_param.enc_packetizer_id =
3234 AFE_MODULE_ID_PACKETIZER_COP;
3235 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3236 if (ret) {
3237 pr_err("%s: AFE_ENCODER_PARAM_ID_PACKETIZER for port 0x%x failed %d\n",
3238 __func__, port_id, ret);
3239 goto exit;
3240 }
3241
3242 config.param.payload_size =
Preetam Singh Ranawatf746a872017-10-20 18:13:14 +05303243 payload_size + sizeof(config.port.enc_set_scrambler_param);
3244 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING mode= %d to DSP payload = %d\n",
3245 __func__, scrambler_mode, config.param.payload_size);
3246 config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING;
3247 config.pdata.param_size = sizeof(config.port.enc_set_scrambler_param);
3248 config.port.enc_set_scrambler_param.enable_scrambler = scrambler_mode;
3249 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3250 if (ret) {
3251 pr_err("%s: AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING for port 0x%x failed %d\n",
3252 __func__, port_id, ret);
3253 goto exit;
3254 }
3255
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303256 if (format == ASM_MEDIA_FMT_APTX) {
3257 config.param.payload_size =
3258 payload_size + sizeof(config.port.channel_mode_param);
3259 pr_debug("%s:sending CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO mode= %d to DSP payload\n",
3260 __func__, mono_mode);
3261 config.pdata.param_id = CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO;
3262 config.pdata.param_size = sizeof(config.port.channel_mode_param);
3263 config.port.channel_mode_param.channel_mode = mono_mode;
3264 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3265 if (ret) {
3266 pr_err("%s: CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO for port 0x%x failed %d\n",
3267 __func__, port_id, ret);
3268 }
3269 }
3270
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003271 if (format == ASM_MEDIA_FMT_LDAC) {
3272 config.param.payload_size =
3273 payload_size + sizeof(config.port.map_param);
3274 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP to DSP payload = %d\n",
3275 __func__, config.param.payload_size);
3276 config.pdata.param_id = AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP;
3277 config.pdata.param_size = sizeof(config.port.map_param);
3278 config.port.map_param.mapping_table =
3279 cfg->ldac_config.abr_config.mapping_info;
3280 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3281 if (ret) {
3282 pr_err("%s: AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP for port 0x%x failed %d\n",
3283 __func__, port_id, ret);
3284 goto exit;
3285 }
3286
3287 config.param.payload_size =
3288 payload_size + sizeof(config.port.imc_info_param);
3289 pr_debug("%s:sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload = %d\n",
3290 __func__, config.param.payload_size);
3291 config.pdata.param_id =
3292 AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION;
3293 config.pdata.param_size = sizeof(config.port.imc_info_param);
3294 config.port.imc_info_param.imc_info =
3295 cfg->ldac_config.abr_config.imc_info;
3296 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3297 if (ret) {
3298 pr_err("%s: AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION for port 0x%x failed %d\n",
3299 __func__, port_id, ret);
3300 goto exit;
3301 }
3302 }
3303
Preetam Singh Ranawatf746a872017-10-20 18:13:14 +05303304 config.param.payload_size =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303305 payload_size + sizeof(config.port.media_type);
3306 config.pdata.param_size = sizeof(config.port.media_type);
3307
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003308 pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP\n",
3309 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303310 config.pdata.module_id = AFE_MODULE_PORT;
3311 config.pdata.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
3312 config.port.media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003313 if (format == ASM_MEDIA_FMT_LDAC)
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05303314 config.port.media_type.sample_rate =
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003315 cfg->ldac_config.custom_config.sample_rate;
3316 else
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05303317 config.port.media_type.sample_rate =
3318 afe_config.slim_sch.sample_rate;
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05303319
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303320 if (afe_in_bit_width)
3321 config.port.media_type.bit_width = afe_in_bit_width;
3322 else
3323 config.port.media_type.bit_width =
3324 afe_config.slim_sch.bit_width;
3325
3326 if (afe_in_channels)
3327 config.port.media_type.num_channels = afe_in_channels;
3328 else
3329 config.port.media_type.num_channels =
3330 afe_config.slim_sch.num_channels;
3331 config.port.media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
3332 config.port.media_type.reserved = 0;
3333
3334 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3335 if (ret) {
3336 pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
3337 __func__, port_id, ret);
3338 goto exit;
3339 }
3340
3341exit:
3342 return ret;
3343}
3344
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303345int afe_set_tws_channel_mode(u16 port_id, u32 channel_mode)
3346{
3347 struct aptx_channel_mode_param_t channel_mode_param;
3348 int ret = 0;
3349 int index = 0;
3350
3351 pr_debug("%s: enter\n", __func__);
3352 index = q6audio_get_port_index(port_id);
3353 if (index < 0 || index >= AFE_MAX_PORTS) {
3354 pr_err("%s: AFE port index[%d] invalid!\n",
3355 __func__, index);
3356 return -EINVAL;
3357 }
3358
3359 ret = q6audio_validate_port(port_id);
3360 if (ret < 0) {
3361 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
3362 return -EINVAL;
3363 }
3364
3365 channel_mode_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3366 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3367 channel_mode_param.hdr.pkt_size = sizeof(channel_mode_param);
3368 channel_mode_param.hdr.src_port = 0;
3369 channel_mode_param.hdr.dest_port = 0;
3370 channel_mode_param.hdr.token = index;
3371
3372 channel_mode_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3373 channel_mode_param.param.payload_size = sizeof(channel_mode_param) - sizeof(struct apr_hdr)
3374 - sizeof(channel_mode_param.param);
3375
3376 channel_mode_param.param.payload_address_lsw = 0x00;
3377 channel_mode_param.param.payload_address_msw = 0x00;
3378 channel_mode_param.param.mem_map_handle = 0x00;
3379 channel_mode_param.param.port_id = q6audio_get_port_id(port_id);
3380 channel_mode_param.pdata.module_id = AFE_MODULE_ID_ENCODER;
3381 channel_mode_param.pdata.param_id = CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO;
3382 channel_mode_param.pdata.param_size = sizeof(channel_mode_param.channel_mode);
3383
3384 channel_mode_param.channel_mode = channel_mode;
3385
3386 ret = afe_apr_send_pkt(&channel_mode_param, &this_afe.wait[index]);
3387
3388 if (ret)
3389 pr_err("%s: AFE set channel mode cfg for port 0x%x failed %d\n",
3390 __func__, port_id, ret);
3391
3392 return ret;
3393}
3394EXPORT_SYMBOL(afe_set_tws_channel_mode);
3395
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303396static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
3397 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003398 union afe_enc_config_data *enc_cfg,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303399 u32 codec_format, u32 scrambler_mode, u32 mono_mode,
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003400 struct afe_dec_config *dec_cfg)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303401{
3402 struct afe_audioif_config_command config;
3403 int ret = 0;
3404 int cfg_type;
3405 int index = 0;
3406 enum afe_mad_type mad_type;
3407 uint16_t port_index;
3408
3409 if (!afe_config) {
3410 pr_err("%s: Error, no configuration data\n", __func__);
3411 ret = -EINVAL;
3412 return ret;
3413 }
3414
3415 if ((port_id == RT_PROXY_DAI_001_RX) ||
3416 (port_id == RT_PROXY_DAI_002_TX)) {
3417 pr_debug("%s: before incrementing pcm_afe_instance %d port_id 0x%x\n",
3418 __func__,
3419 pcm_afe_instance[port_id & 0x1], port_id);
3420 port_id = VIRTUAL_ID_TO_PORTID(port_id);
3421 pcm_afe_instance[port_id & 0x1]++;
3422 return 0;
3423 }
3424 if ((port_id == RT_PROXY_DAI_002_RX) ||
3425 (port_id == RT_PROXY_DAI_001_TX)) {
3426 pr_debug("%s: before incrementing proxy_afe_instance %d port_id 0x%x\n",
3427 __func__,
3428 proxy_afe_instance[port_id & 0x1], port_id);
3429
3430 if (!afe_close_done[port_id & 0x1]) {
3431 /*close pcm dai corresponding to the proxy dai*/
3432 afe_close(port_id - 0x10);
3433 pcm_afe_instance[port_id & 0x1]++;
3434 pr_debug("%s: reconfigure afe port again\n", __func__);
3435 }
3436 proxy_afe_instance[port_id & 0x1]++;
3437 afe_close_done[port_id & 0x1] = false;
3438 port_id = VIRTUAL_ID_TO_PORTID(port_id);
3439 }
3440
3441 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
3442
3443 index = q6audio_get_port_index(port_id);
3444 if (index < 0 || index >= AFE_MAX_PORTS) {
3445 pr_err("%s: AFE port index[%d] invalid!\n",
3446 __func__, index);
3447 return -EINVAL;
3448 }
3449 ret = q6audio_validate_port(port_id);
3450 if (ret < 0) {
3451 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
3452 return -EINVAL;
3453 }
3454
3455 ret = afe_q6_interface_prepare();
3456 if (ret != 0) {
3457 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3458 return ret;
3459 }
3460
3461 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
3462 this_afe.afe_sample_rates[index] = rate;
3463
3464 if (this_afe.rt_cb)
3465 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
3466 }
3467
3468 mutex_lock(&this_afe.afe_cmd_lock);
3469 /* Also send the topology id here: */
3470 port_index = afe_get_port_index(port_id);
3471 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
3472 /* One time call: only for first time */
3473 afe_send_custom_topology();
3474 afe_send_port_topology_id(port_id);
3475 afe_send_cal(port_id);
3476 afe_send_hw_delay(port_id, rate);
3477 }
3478
3479 /* Start SW MAD module */
3480 mad_type = afe_port_get_mad_type(port_id);
3481 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
3482 mad_type);
3483 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
3484 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
3485 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
3486 pr_err("%s: AFE isn't configured yet for\n"
3487 "HW MAD try Again\n", __func__);
3488 ret = -EAGAIN;
3489 goto fail_cmd;
3490 }
3491 ret = afe_turn_onoff_hw_mad(mad_type, true);
3492 if (ret) {
3493 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
3494 __func__, ret);
3495 goto fail_cmd;
3496 }
3497 }
3498
3499 if ((this_afe.aanc_info.aanc_active) &&
3500 (this_afe.aanc_info.aanc_tx_port == port_id)) {
3501 this_afe.aanc_info.aanc_tx_port_sample_rate = rate;
3502 port_index =
3503 afe_get_port_index(this_afe.aanc_info.aanc_rx_port);
3504 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3505 this_afe.aanc_info.aanc_rx_port_sample_rate =
3506 this_afe.afe_sample_rates[port_index];
3507 } else {
3508 pr_err("%s: Invalid port index %d\n",
3509 __func__, port_index);
3510 ret = -EINVAL;
3511 goto fail_cmd;
3512 }
3513 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
3514 this_afe.aanc_info.aanc_rx_port);
3515 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
3516 }
3517
3518 if ((port_id == AFE_PORT_ID_USB_RX) ||
3519 (port_id == AFE_PORT_ID_USB_TX)) {
3520 ret = afe_port_send_usb_dev_param(port_id, afe_config);
3521 if (ret) {
3522 pr_err("%s: AFE device param for port 0x%x failed %d\n",
3523 __func__, port_id, ret);
3524 ret = -EINVAL;
3525 goto fail_cmd;
3526 }
3527 }
3528
3529 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3530 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3531 config.hdr.pkt_size = sizeof(config);
3532 config.hdr.src_port = 0;
3533 config.hdr.dest_port = 0;
3534 config.hdr.token = index;
3535
3536 switch (port_id) {
3537 case AFE_PORT_ID_PRIMARY_PCM_RX:
3538 case AFE_PORT_ID_PRIMARY_PCM_TX:
3539 case AFE_PORT_ID_SECONDARY_PCM_RX:
3540 case AFE_PORT_ID_SECONDARY_PCM_TX:
3541 case AFE_PORT_ID_TERTIARY_PCM_RX:
3542 case AFE_PORT_ID_TERTIARY_PCM_TX:
3543 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3544 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303545 case AFE_PORT_ID_QUINARY_PCM_RX:
3546 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303547 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
3548 break;
3549 case PRIMARY_I2S_RX:
3550 case PRIMARY_I2S_TX:
3551 case SECONDARY_I2S_RX:
3552 case SECONDARY_I2S_TX:
3553 case MI2S_RX:
3554 case MI2S_TX:
3555 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3556 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3557 case AFE_PORT_ID_SECONDARY_MI2S_RX:
3558 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
3559 case AFE_PORT_ID_SECONDARY_MI2S_TX:
3560 case AFE_PORT_ID_TERTIARY_MI2S_RX:
3561 case AFE_PORT_ID_TERTIARY_MI2S_TX:
3562 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3563 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3564 case AFE_PORT_ID_QUINARY_MI2S_RX:
3565 case AFE_PORT_ID_QUINARY_MI2S_TX:
3566 case AFE_PORT_ID_SENARY_MI2S_TX:
3567 case AFE_PORT_ID_INT0_MI2S_RX:
3568 case AFE_PORT_ID_INT0_MI2S_TX:
3569 case AFE_PORT_ID_INT1_MI2S_RX:
3570 case AFE_PORT_ID_INT1_MI2S_TX:
3571 case AFE_PORT_ID_INT2_MI2S_RX:
3572 case AFE_PORT_ID_INT2_MI2S_TX:
3573 case AFE_PORT_ID_INT3_MI2S_RX:
3574 case AFE_PORT_ID_INT3_MI2S_TX:
3575 case AFE_PORT_ID_INT4_MI2S_RX:
3576 case AFE_PORT_ID_INT4_MI2S_TX:
3577 case AFE_PORT_ID_INT5_MI2S_RX:
3578 case AFE_PORT_ID_INT5_MI2S_TX:
3579 case AFE_PORT_ID_INT6_MI2S_RX:
3580 case AFE_PORT_ID_INT6_MI2S_TX:
3581 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
3582 break;
3583 case HDMI_RX:
3584 case DISPLAY_PORT_RX:
3585 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
3586 break;
3587 case VOICE_PLAYBACK_TX:
3588 case VOICE2_PLAYBACK_TX:
3589 case VOICE_RECORD_RX:
3590 case VOICE_RECORD_TX:
3591 cfg_type = AFE_PARAM_ID_PSEUDO_PORT_CONFIG;
3592 break;
3593 case SLIMBUS_0_RX:
3594 case SLIMBUS_0_TX:
3595 case SLIMBUS_1_RX:
3596 case SLIMBUS_1_TX:
3597 case SLIMBUS_2_RX:
3598 case SLIMBUS_2_TX:
3599 case SLIMBUS_3_RX:
3600 case SLIMBUS_3_TX:
3601 case SLIMBUS_4_RX:
3602 case SLIMBUS_4_TX:
3603 case SLIMBUS_5_RX:
3604 case SLIMBUS_5_TX:
3605 case SLIMBUS_6_RX:
3606 case SLIMBUS_6_TX:
3607 case SLIMBUS_7_RX:
3608 case SLIMBUS_7_TX:
3609 case SLIMBUS_8_RX:
3610 case SLIMBUS_8_TX:
3611 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
3612 break;
3613 case AFE_PORT_ID_USB_RX:
3614 case AFE_PORT_ID_USB_TX:
3615 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
3616 break;
3617 case RT_PROXY_PORT_001_RX:
3618 case RT_PROXY_PORT_001_TX:
3619 cfg_type = AFE_PARAM_ID_RT_PROXY_CONFIG;
3620 break;
3621 case INT_BT_SCO_RX:
3622 case INT_BT_A2DP_RX:
3623 case INT_BT_SCO_TX:
3624 case INT_FM_RX:
3625 case INT_FM_TX:
3626 cfg_type = AFE_PARAM_ID_INTERNAL_BT_FM_CONFIG;
3627 break;
3628 default:
3629 pr_err("%s: Invalid port id 0x%x\n", __func__, port_id);
3630 ret = -EINVAL;
3631 goto fail_cmd;
3632 }
3633 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3634 config.param.port_id = q6audio_get_port_id(port_id);
3635 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
3636 sizeof(config.param);
3637 config.param.payload_address_lsw = 0x00;
3638 config.param.payload_address_msw = 0x00;
3639 config.param.mem_map_handle = 0x00;
3640 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3641 config.pdata.param_id = cfg_type;
3642 config.pdata.param_size = sizeof(config.port);
3643
3644 config.port = *afe_config;
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003645 if (((enc_cfg != NULL) || (dec_cfg != NULL)) &&
3646 (codec_format != ASM_MEDIA_FMT_NONE) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303647 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
3648 config.port.slim_sch.data_format =
3649 AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED;
3650 }
3651 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3652 if (ret) {
3653 pr_err("%s: AFE enable for port 0x%x failed %d\n",
3654 __func__, port_id, ret);
3655 goto fail_cmd;
3656 }
3657
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003658 if ((codec_format != ASM_MEDIA_FMT_NONE) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303659 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003660 if (enc_cfg != NULL) {
3661 pr_debug("%s: Found AFE encoder support for SLIMBUS enc_format = %d\n",
3662 __func__, codec_format);
3663 ret = q6afe_send_enc_config(port_id, enc_cfg,
3664 codec_format, *afe_config,
3665 afe_in_channels,
3666 afe_in_bit_width,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303667 scrambler_mode, mono_mode);
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003668 if (ret) {
3669 pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
3670 __func__, port_id, ret);
3671 goto fail_cmd;
3672 }
3673 }
3674 if (dec_cfg != NULL) {
3675 pr_debug("%s: Found AFE decoder support for SLIMBUS dec_format = %d\n",
3676 __func__, codec_format);
3677 ret = q6afe_send_dec_config(port_id, *afe_config,
3678 dec_cfg);
3679 if (ret) {
3680 pr_err("%s: AFE decoder config for port 0x%x failed %d\n",
3681 __func__, port_id, ret);
3682 goto fail_cmd;
3683 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303684 }
3685 }
3686
3687 port_index = afe_get_port_index(port_id);
3688 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3689 /*
3690 * If afe_port_start() for tx port called before
3691 * rx port, then aanc rx sample rate is zero. So,
3692 * AANC state machine in AFE will not get triggered.
3693 * Make sure to check whether aanc is active during
3694 * afe_port_start() for rx port and if aanc rx
3695 * sample rate is zero, call afe_aanc_start to configure
3696 * aanc with valid sample rates.
3697 */
3698 if (this_afe.aanc_info.aanc_active &&
3699 !this_afe.aanc_info.aanc_rx_port_sample_rate) {
3700 this_afe.aanc_info.aanc_rx_port_sample_rate =
3701 this_afe.afe_sample_rates[port_index];
3702 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
3703 this_afe.aanc_info.aanc_rx_port);
3704 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
3705 }
3706 } else {
3707 pr_err("%s: Invalid port index %d\n", __func__, port_index);
3708 ret = -EINVAL;
3709 goto fail_cmd;
3710 }
3711 ret = afe_send_cmd_port_start(port_id);
3712
3713fail_cmd:
3714 mutex_unlock(&this_afe.afe_cmd_lock);
3715 return ret;
3716}
3717
3718/**
3719 * afe_port_start - to configure AFE session with
3720 * specified port configuration
3721 *
3722 * @port_id: AFE port id number
3723 * @afe_config: port configutation
3724 * @rate: sampling rate of port
3725 *
3726 * Returns 0 on success or error value on port start failure.
3727 */
3728int afe_port_start(u16 port_id, union afe_port_config *afe_config,
3729 u32 rate)
3730{
3731 return __afe_port_start(port_id, afe_config, rate,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303732 0, 0, NULL, ASM_MEDIA_FMT_NONE, 0, 0, NULL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303733}
3734EXPORT_SYMBOL(afe_port_start);
3735
3736/**
3737 * afe_port_start_v2 - to configure AFE session with
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003738 * specified port configuration and encoder/decoder params
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303739 *
3740 * @port_id: AFE port id number
3741 * @afe_config: port configutation
3742 * @rate: sampling rate of port
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003743 * @enc_cfg: AFE enc configuration information to setup encoder
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303744 * @afe_in_channels: AFE input channel configuration, this needs
3745 * update only if input channel is differ from AFE output
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003746 * @dec_cfg: AFE dec configuration information to set up decoder
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303747 *
3748 * Returns 0 on success or error value on port start failure.
3749 */
3750int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
3751 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003752 struct afe_enc_config *enc_cfg,
3753 struct afe_dec_config *dec_cfg)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303754{
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003755 int ret = 0;
3756
3757 if (enc_cfg != NULL)
3758 ret = __afe_port_start(port_id, afe_config, rate,
3759 afe_in_channels, afe_in_bit_width,
3760 &enc_cfg->data, enc_cfg->format,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303761 enc_cfg->scrambler_mode,
3762 enc_cfg->mono_mode, NULL);
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003763 else if (dec_cfg != NULL)
3764 ret = __afe_port_start(port_id, afe_config, rate,
3765 afe_in_channels, afe_in_bit_width,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303766 NULL, dec_cfg->format, 0, 0, dec_cfg);
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003767
3768 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303769}
3770EXPORT_SYMBOL(afe_port_start_v2);
3771
3772int afe_get_port_index(u16 port_id)
3773{
3774 switch (port_id) {
3775 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
3776 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
3777 case AFE_PORT_ID_PRIMARY_PCM_RX:
3778 return IDX_AFE_PORT_ID_PRIMARY_PCM_RX;
3779 case AFE_PORT_ID_PRIMARY_PCM_TX:
3780 return IDX_AFE_PORT_ID_PRIMARY_PCM_TX;
3781 case AFE_PORT_ID_SECONDARY_PCM_RX:
3782 return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
3783 case AFE_PORT_ID_SECONDARY_PCM_TX:
3784 return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
3785 case AFE_PORT_ID_TERTIARY_PCM_RX:
3786 return IDX_AFE_PORT_ID_TERTIARY_PCM_RX;
3787 case AFE_PORT_ID_TERTIARY_PCM_TX:
3788 return IDX_AFE_PORT_ID_TERTIARY_PCM_TX;
3789 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3790 return IDX_AFE_PORT_ID_QUATERNARY_PCM_RX;
3791 case AFE_PORT_ID_QUATERNARY_PCM_TX:
3792 return IDX_AFE_PORT_ID_QUATERNARY_PCM_TX;
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303793 case AFE_PORT_ID_QUINARY_PCM_RX:
3794 return IDX_AFE_PORT_ID_QUINARY_PCM_RX;
3795 case AFE_PORT_ID_QUINARY_PCM_TX:
3796 return IDX_AFE_PORT_ID_QUINARY_PCM_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303797 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
3798 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
3799 case MI2S_RX: return IDX_MI2S_RX;
3800 case MI2S_TX: return IDX_MI2S_TX;
3801 case HDMI_RX: return IDX_HDMI_RX;
3802 case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX;
3803 case AFE_PORT_ID_SPDIF_RX: return IDX_SPDIF_RX;
3804 case RSVD_2: return IDX_RSVD_2;
3805 case RSVD_3: return IDX_RSVD_3;
3806 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
3807 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
3808 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
3809 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
3810 case VOICE2_PLAYBACK_TX: return IDX_VOICE2_PLAYBACK_TX;
3811 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
3812 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
3813 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
3814 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
3815 case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
3816 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
3817 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
3818 case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
3819 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
3820 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
3821 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
3822 case INT_FM_RX: return IDX_INT_FM_RX;
3823 case INT_FM_TX: return IDX_INT_FM_TX;
3824 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
3825 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
3826 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
3827 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
3828 case SLIMBUS_5_RX: return IDX_SLIMBUS_5_RX;
3829 case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX;
3830 case SLIMBUS_6_RX: return IDX_SLIMBUS_6_RX;
3831 case SLIMBUS_6_TX: return IDX_SLIMBUS_6_TX;
3832 case SLIMBUS_7_RX: return IDX_SLIMBUS_7_RX;
3833 case SLIMBUS_7_TX: return IDX_SLIMBUS_7_TX;
3834 case SLIMBUS_8_RX: return IDX_SLIMBUS_8_RX;
3835 case SLIMBUS_8_TX: return IDX_SLIMBUS_8_TX;
3836 case AFE_PORT_ID_USB_RX: return IDX_AFE_PORT_ID_USB_RX;
3837 case AFE_PORT_ID_USB_TX: return IDX_AFE_PORT_ID_USB_TX;
3838 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3839 return IDX_AFE_PORT_ID_PRIMARY_MI2S_RX;
3840 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3841 return IDX_AFE_PORT_ID_PRIMARY_MI2S_TX;
3842 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3843 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
3844 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3845 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX;
3846 case AFE_PORT_ID_SECONDARY_MI2S_RX:
3847 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX;
3848 case AFE_PORT_ID_SECONDARY_MI2S_TX:
3849 return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX;
3850 case AFE_PORT_ID_TERTIARY_MI2S_RX:
3851 return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX;
3852 case AFE_PORT_ID_TERTIARY_MI2S_TX:
3853 return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX;
3854 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
3855 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_SD1;
3856 case AFE_PORT_ID_QUINARY_MI2S_RX:
3857 return IDX_AFE_PORT_ID_QUINARY_MI2S_RX;
3858 case AFE_PORT_ID_QUINARY_MI2S_TX:
3859 return IDX_AFE_PORT_ID_QUINARY_MI2S_TX;
3860 case AFE_PORT_ID_SENARY_MI2S_TX:
3861 return IDX_AFE_PORT_ID_SENARY_MI2S_TX;
3862 case AFE_PORT_ID_PRIMARY_TDM_RX:
3863 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_0;
3864 case AFE_PORT_ID_PRIMARY_TDM_TX:
3865 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_0;
3866 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
3867 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_1;
3868 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
3869 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_1;
3870 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
3871 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_2;
3872 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
3873 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_2;
3874 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
3875 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_3;
3876 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
3877 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_3;
3878 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
3879 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_4;
3880 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
3881 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_4;
3882 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
3883 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_5;
3884 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
3885 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_5;
3886 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
3887 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_6;
3888 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
3889 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_6;
3890 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
3891 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_7;
3892 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
3893 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_7;
3894 case AFE_PORT_ID_SECONDARY_TDM_RX:
3895 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_0;
3896 case AFE_PORT_ID_SECONDARY_TDM_TX:
3897 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_0;
3898 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
3899 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_1;
3900 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
3901 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_1;
3902 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
3903 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_2;
3904 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
3905 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_2;
3906 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
3907 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_3;
3908 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
3909 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_3;
3910 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
3911 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_4;
3912 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
3913 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_4;
3914 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
3915 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_5;
3916 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
3917 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_5;
3918 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
3919 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_6;
3920 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
3921 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_6;
3922 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
3923 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_7;
3924 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
3925 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_7;
3926 case AFE_PORT_ID_TERTIARY_TDM_RX:
3927 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_0;
3928 case AFE_PORT_ID_TERTIARY_TDM_TX:
3929 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_0;
3930 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
3931 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_1;
3932 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
3933 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_1;
3934 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
3935 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_2;
3936 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
3937 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_2;
3938 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
3939 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_3;
3940 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
3941 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_3;
3942 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
3943 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_4;
3944 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
3945 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_4;
3946 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
3947 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_5;
3948 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
3949 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_5;
3950 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
3951 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_6;
3952 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
3953 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_6;
3954 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
3955 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_7;
3956 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
3957 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_7;
3958 case AFE_PORT_ID_QUATERNARY_TDM_RX:
3959 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_0;
3960 case AFE_PORT_ID_QUATERNARY_TDM_TX:
3961 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_0;
3962 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
3963 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_1;
3964 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
3965 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_1;
3966 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
3967 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_2;
3968 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
3969 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_2;
3970 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
3971 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_3;
3972 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
3973 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_3;
3974 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
3975 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_4;
3976 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
3977 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_4;
3978 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
3979 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_5;
3980 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
3981 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_5;
3982 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
3983 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_6;
3984 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
3985 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_6;
3986 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
3987 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_7;
3988 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
3989 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_7;
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303990 case AFE_PORT_ID_QUINARY_TDM_RX:
3991 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_0;
3992 case AFE_PORT_ID_QUINARY_TDM_TX:
3993 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_0;
3994 case AFE_PORT_ID_QUINARY_TDM_RX_1:
3995 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_1;
3996 case AFE_PORT_ID_QUINARY_TDM_TX_1:
3997 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_1;
3998 case AFE_PORT_ID_QUINARY_TDM_RX_2:
3999 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_2;
4000 case AFE_PORT_ID_QUINARY_TDM_TX_2:
4001 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_2;
4002 case AFE_PORT_ID_QUINARY_TDM_RX_3:
4003 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_3;
4004 case AFE_PORT_ID_QUINARY_TDM_TX_3:
4005 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_3;
4006 case AFE_PORT_ID_QUINARY_TDM_RX_4:
4007 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_4;
4008 case AFE_PORT_ID_QUINARY_TDM_TX_4:
4009 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_4;
4010 case AFE_PORT_ID_QUINARY_TDM_RX_5:
4011 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_5;
4012 case AFE_PORT_ID_QUINARY_TDM_TX_5:
4013 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_5;
4014 case AFE_PORT_ID_QUINARY_TDM_RX_6:
4015 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_6;
4016 case AFE_PORT_ID_QUINARY_TDM_TX_6:
4017 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_6;
4018 case AFE_PORT_ID_QUINARY_TDM_RX_7:
4019 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_7;
4020 case AFE_PORT_ID_QUINARY_TDM_TX_7:
4021 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_7;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304022 case AFE_PORT_ID_INT0_MI2S_RX:
4023 return IDX_AFE_PORT_ID_INT0_MI2S_RX;
4024 case AFE_PORT_ID_INT0_MI2S_TX:
4025 return IDX_AFE_PORT_ID_INT0_MI2S_TX;
4026 case AFE_PORT_ID_INT1_MI2S_RX:
4027 return IDX_AFE_PORT_ID_INT1_MI2S_RX;
4028 case AFE_PORT_ID_INT1_MI2S_TX:
4029 return IDX_AFE_PORT_ID_INT1_MI2S_TX;
4030 case AFE_PORT_ID_INT2_MI2S_RX:
4031 return IDX_AFE_PORT_ID_INT2_MI2S_RX;
4032 case AFE_PORT_ID_INT2_MI2S_TX:
4033 return IDX_AFE_PORT_ID_INT2_MI2S_TX;
4034 case AFE_PORT_ID_INT3_MI2S_RX:
4035 return IDX_AFE_PORT_ID_INT3_MI2S_RX;
4036 case AFE_PORT_ID_INT3_MI2S_TX:
4037 return IDX_AFE_PORT_ID_INT3_MI2S_TX;
4038 case AFE_PORT_ID_INT4_MI2S_RX:
4039 return IDX_AFE_PORT_ID_INT4_MI2S_RX;
4040 case AFE_PORT_ID_INT4_MI2S_TX:
4041 return IDX_AFE_PORT_ID_INT4_MI2S_TX;
4042 case AFE_PORT_ID_INT5_MI2S_RX:
4043 return IDX_AFE_PORT_ID_INT5_MI2S_RX;
4044 case AFE_PORT_ID_INT5_MI2S_TX:
4045 return IDX_AFE_PORT_ID_INT5_MI2S_TX;
4046 case AFE_PORT_ID_INT6_MI2S_RX:
4047 return IDX_AFE_PORT_ID_INT6_MI2S_RX;
4048 case AFE_PORT_ID_INT6_MI2S_TX:
4049 return IDX_AFE_PORT_ID_INT6_MI2S_TX;
Raja Mallik425e1d32018-05-20 19:21:10 +05304050 case AFE_LOOPBACK_TX:
4051 return IDX_AFE_LOOPBACK_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304052 default:
4053 pr_err("%s: port 0x%x\n", __func__, port_id);
4054 return -EINVAL;
4055 }
4056}
4057
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304058/**
4059 * afe_open -
4060 * command to open AFE port
4061 *
4062 * @port_id: AFE port id
4063 * @afe_config: AFE port config to pass
4064 * @rate: sample rate
4065 *
4066 * Returns 0 on success or error on failure
4067 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304068int afe_open(u16 port_id,
4069 union afe_port_config *afe_config, int rate)
4070{
4071 struct afe_port_cmd_device_start start;
4072 struct afe_audioif_config_command config;
4073 int ret = 0;
4074 int cfg_type;
4075 int index = 0;
4076
4077 if (!afe_config) {
4078 pr_err("%s: Error, no configuration data\n", __func__);
4079 ret = -EINVAL;
4080 return ret;
4081 }
4082
4083 pr_err("%s: port_id 0x%x rate %d\n", __func__, port_id, rate);
4084
4085 index = q6audio_get_port_index(port_id);
4086 if (index < 0 || index >= AFE_MAX_PORTS) {
4087 pr_err("%s: AFE port index[%d] invalid!\n",
4088 __func__, index);
4089 return -EINVAL;
4090 }
4091 ret = q6audio_validate_port(port_id);
4092 if (ret < 0) {
4093 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
4094 return -EINVAL;
4095 }
4096
4097 if ((port_id == RT_PROXY_DAI_001_RX) ||
4098 (port_id == RT_PROXY_DAI_002_TX)) {
4099 pr_err("%s: wrong port 0x%x\n", __func__, port_id);
4100 return -EINVAL;
4101 }
4102 if ((port_id == RT_PROXY_DAI_002_RX) ||
4103 (port_id == RT_PROXY_DAI_001_TX))
4104 port_id = VIRTUAL_ID_TO_PORTID(port_id);
4105
4106 ret = afe_q6_interface_prepare();
4107 if (ret != 0) {
4108 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4109 return -EINVAL;
4110 }
4111
4112 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
4113 this_afe.afe_sample_rates[index] = rate;
4114
4115 if (this_afe.rt_cb)
4116 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
4117 }
4118
4119 /* Also send the topology id here: */
4120 afe_send_custom_topology(); /* One time call: only for first time */
4121 afe_send_port_topology_id(port_id);
4122
4123 ret = q6audio_validate_port(port_id);
4124 if (ret < 0) {
4125 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
4126 __func__, port_id, ret);
4127 return -EINVAL;
4128 }
4129 mutex_lock(&this_afe.afe_cmd_lock);
4130
4131 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4132 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4133 config.hdr.pkt_size = sizeof(config);
4134 config.hdr.src_port = 0;
4135 config.hdr.dest_port = 0;
4136 config.hdr.token = index;
4137 switch (port_id) {
4138 case PRIMARY_I2S_RX:
4139 case PRIMARY_I2S_TX:
4140 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
4141 break;
4142 case AFE_PORT_ID_PRIMARY_PCM_RX:
4143 case AFE_PORT_ID_PRIMARY_PCM_TX:
4144 case AFE_PORT_ID_SECONDARY_PCM_RX:
4145 case AFE_PORT_ID_SECONDARY_PCM_TX:
4146 case AFE_PORT_ID_TERTIARY_PCM_RX:
4147 case AFE_PORT_ID_TERTIARY_PCM_TX:
4148 case AFE_PORT_ID_QUATERNARY_PCM_RX:
4149 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304150 case AFE_PORT_ID_QUINARY_PCM_RX:
4151 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304152 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
4153 break;
4154 case SECONDARY_I2S_RX:
4155 case SECONDARY_I2S_TX:
4156 case AFE_PORT_ID_PRIMARY_MI2S_RX:
4157 case AFE_PORT_ID_PRIMARY_MI2S_TX:
4158 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
4159 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
4160 case MI2S_RX:
4161 case MI2S_TX:
4162 case AFE_PORT_ID_QUINARY_MI2S_RX:
4163 case AFE_PORT_ID_QUINARY_MI2S_TX:
4164 case AFE_PORT_ID_SENARY_MI2S_TX:
4165 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
4166 break;
4167 case HDMI_RX:
4168 case DISPLAY_PORT_RX:
4169 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
4170 break;
4171 case SLIMBUS_0_RX:
4172 case SLIMBUS_0_TX:
4173 case SLIMBUS_1_RX:
4174 case SLIMBUS_1_TX:
4175 case SLIMBUS_2_RX:
4176 case SLIMBUS_2_TX:
4177 case SLIMBUS_3_RX:
4178 case SLIMBUS_3_TX:
4179 case SLIMBUS_4_RX:
4180 case SLIMBUS_4_TX:
4181 case SLIMBUS_5_RX:
4182 case SLIMBUS_6_RX:
4183 case SLIMBUS_6_TX:
4184 case SLIMBUS_7_RX:
4185 case SLIMBUS_7_TX:
4186 case SLIMBUS_8_RX:
4187 case SLIMBUS_8_TX:
4188 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
4189 break;
4190 case AFE_PORT_ID_USB_RX:
4191 case AFE_PORT_ID_USB_TX:
4192 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
4193 break;
4194 default:
4195 pr_err("%s: Invalid port id 0x%x\n",
4196 __func__, port_id);
4197 ret = -EINVAL;
4198 goto fail_cmd;
4199 }
4200 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
4201 config.param.port_id = q6audio_get_port_id(port_id);
4202 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr)
4203 - sizeof(config.param);
4204 config.param.payload_address_lsw = 0x00;
4205 config.param.payload_address_msw = 0x00;
4206 config.param.mem_map_handle = 0x00;
4207 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
4208 config.pdata.param_id = cfg_type;
4209 config.pdata.param_size = sizeof(config.port);
4210
4211 config.port = *afe_config;
4212 pr_debug("%s: param PL size=%d iparam_size[%d][%zd %zd %zd %zd] param_id[0x%x]\n",
4213 __func__, config.param.payload_size, config.pdata.param_size,
4214 sizeof(config), sizeof(config.param), sizeof(config.port),
4215 sizeof(struct apr_hdr), config.pdata.param_id);
4216
4217 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
4218 if (ret) {
4219 pr_err("%s: AFE enable for port 0x%x opcode[0x%x]failed %d\n",
4220 __func__, port_id, cfg_type, ret);
4221 goto fail_cmd;
4222 }
4223 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4224 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4225 start.hdr.pkt_size = sizeof(start);
4226 start.hdr.src_port = 0;
4227 start.hdr.dest_port = 0;
4228 start.hdr.token = index;
4229 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
4230 start.port_id = q6audio_get_port_id(port_id);
4231 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
4232 __func__, start.hdr.opcode, start.port_id);
4233
4234 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
4235 if (ret) {
4236 pr_err("%s: AFE enable for port 0x%x failed %d\n", __func__,
4237 port_id, ret);
4238 goto fail_cmd;
4239 }
4240
4241fail_cmd:
4242 mutex_unlock(&this_afe.afe_cmd_lock);
4243 return ret;
4244}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304245EXPORT_SYMBOL(afe_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304246
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304247/**
4248 * afe_loopback -
4249 * command to set loopback between AFE ports
4250 *
4251 * @enable: enable or disable loopback
4252 * @rx_port: AFE RX port ID
4253 * @tx_port: AFE TX port ID
4254 *
4255 * Returns 0 on success or error on failure
4256 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304257int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
4258{
4259 struct afe_loopback_cfg_v1 lb_cmd;
4260 int ret = 0;
4261 int index = 0;
4262
4263 if (rx_port == MI2S_RX)
4264 rx_port = AFE_PORT_ID_PRIMARY_MI2S_RX;
4265 if (tx_port == MI2S_TX)
4266 tx_port = AFE_PORT_ID_PRIMARY_MI2S_TX;
4267
4268 ret = afe_q6_interface_prepare();
4269 if (ret != 0) {
4270 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4271 return ret;
4272 }
4273
4274 index = q6audio_get_port_index(rx_port);
4275 if (index < 0 || index >= AFE_MAX_PORTS) {
4276 pr_err("%s: AFE port index[%d] invalid!\n",
4277 __func__, index);
4278 return -EINVAL;
4279 }
4280 ret = q6audio_validate_port(rx_port);
4281 if (ret < 0) {
4282 pr_err("%s: Invalid port 0x%x ret %d", __func__, rx_port, ret);
4283 return -EINVAL;
4284 }
4285
4286 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4287 APR_HDR_LEN(20), APR_PKT_VER);
4288 lb_cmd.hdr.pkt_size = sizeof(lb_cmd);
4289 lb_cmd.hdr.src_port = 0;
4290 lb_cmd.hdr.dest_port = 0;
4291 lb_cmd.hdr.token = index;
4292 lb_cmd.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
4293 lb_cmd.param.port_id = tx_port;
4294 lb_cmd.param.payload_size = (sizeof(lb_cmd) - sizeof(struct apr_hdr) -
4295 sizeof(struct afe_port_cmd_set_param_v2));
4296 lb_cmd.param.payload_address_lsw = 0x00;
4297 lb_cmd.param.payload_address_msw = 0x00;
4298 lb_cmd.param.mem_map_handle = 0x00;
4299 lb_cmd.pdata.module_id = AFE_MODULE_LOOPBACK;
4300 lb_cmd.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
4301 lb_cmd.pdata.param_size = lb_cmd.param.payload_size -
4302 sizeof(struct afe_port_param_data_v2);
4303
4304 lb_cmd.dst_port_id = rx_port;
4305 lb_cmd.routing_mode = LB_MODE_DEFAULT;
4306 lb_cmd.enable = (enable ? 1 : 0);
4307 lb_cmd.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
4308
4309 ret = afe_apr_send_pkt(&lb_cmd, &this_afe.wait[index]);
4310 if (ret)
4311 pr_err("%s: AFE loopback failed %d\n", __func__, ret);
4312 return ret;
4313}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304314EXPORT_SYMBOL(afe_loopback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304315
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304316/**
4317 * afe_loopback_gain -
4318 * command to set gain for AFE loopback
4319 *
4320 * @port_id: AFE port id
4321 * @volume: gain value to set
4322 *
4323 * Returns 0 on success or error on failure
4324 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304325int afe_loopback_gain(u16 port_id, u16 volume)
4326{
4327 struct afe_loopback_gain_per_path_param set_param;
4328 int ret = 0;
4329 int index = 0;
4330
4331 if (this_afe.apr == NULL) {
4332 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4333 0xFFFFFFFF, &this_afe);
4334 pr_debug("%s: Register AFE\n", __func__);
4335 if (this_afe.apr == NULL) {
4336 pr_err("%s: Unable to register AFE\n", __func__);
4337 ret = -ENODEV;
4338 return ret;
4339 }
4340 rtac_set_afe_handle(this_afe.apr);
4341 }
4342
4343 ret = q6audio_validate_port(port_id);
4344 if (ret < 0) {
4345 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
4346 __func__, port_id, ret);
4347 ret = -EINVAL;
4348 goto fail_cmd;
4349 }
4350 index = q6audio_get_port_index(port_id);
4351 if (index < 0 || index >= AFE_MAX_PORTS) {
4352 pr_err("%s: AFE port index[%d] invalid!\n",
4353 __func__, index);
4354 return -EINVAL;
4355 }
4356 ret = q6audio_validate_port(port_id);
4357 if (ret < 0) {
4358 pr_err("%s: Invalid port 0x%x ret %d",
4359 __func__, port_id, ret);
4360 return -EINVAL;
4361 }
4362
4363 /* RX ports numbers are even .TX ports numbers are odd. */
4364 if (port_id % 2 == 0) {
4365 pr_err("%s: Failed : afe loopback gain only for TX ports. port_id %d\n",
4366 __func__, port_id);
4367 ret = -EINVAL;
4368 goto fail_cmd;
4369 }
4370
4371 pr_debug("%s: port 0x%x volume %d\n", __func__, port_id, volume);
4372
4373 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4374 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4375 set_param.hdr.pkt_size = sizeof(set_param);
4376 set_param.hdr.src_port = 0;
4377 set_param.hdr.dest_port = 0;
4378 set_param.hdr.token = index;
4379 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
4380
4381 set_param.param.port_id = port_id;
4382 set_param.param.payload_size =
4383 (sizeof(struct afe_loopback_gain_per_path_param) -
4384 sizeof(struct apr_hdr) - sizeof(struct afe_port_cmd_set_param_v2));
4385 set_param.param.payload_address_lsw = 0;
4386 set_param.param.payload_address_msw = 0;
4387 set_param.param.mem_map_handle = 0;
4388
4389 set_param.pdata.module_id = AFE_MODULE_LOOPBACK;
4390 set_param.pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
4391 set_param.pdata.param_size =
4392 (set_param.param.payload_size -
4393 sizeof(struct afe_port_param_data_v2));
4394 set_param.rx_port_id = port_id;
4395 set_param.gain = volume;
4396
4397 ret = afe_apr_send_pkt(&set_param, &this_afe.wait[index]);
4398 if (ret) {
4399 pr_err("%s: AFE param set failed for port 0x%x ret %d\n",
4400 __func__, port_id, ret);
4401 goto fail_cmd;
4402 }
4403
4404fail_cmd:
4405 return ret;
4406}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304407EXPORT_SYMBOL(afe_loopback_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304408
4409int afe_pseudo_port_start_nowait(u16 port_id)
4410{
4411 struct afe_pseudoport_start_command start;
4412 int ret = 0;
4413
4414 pr_debug("%s: port_id=0x%x\n", __func__, port_id);
4415 if (this_afe.apr == NULL) {
4416 pr_err("%s: AFE APR is not registered\n", __func__);
4417 return -ENODEV;
4418 }
4419
4420
4421 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4422 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4423 start.hdr.pkt_size = sizeof(start);
4424 start.hdr.src_port = 0;
4425 start.hdr.dest_port = 0;
4426 start.hdr.token = 0;
4427 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
4428 start.port_id = port_id;
4429 start.timing = 1;
4430
4431 ret = afe_apr_send_pkt(&start, NULL);
4432 if (ret) {
4433 pr_err("%s: AFE enable for port 0x%x failed %d\n",
4434 __func__, port_id, ret);
4435 return ret;
4436 }
4437 return 0;
4438}
4439
4440int afe_start_pseudo_port(u16 port_id)
4441{
4442 int ret = 0;
4443 struct afe_pseudoport_start_command start;
4444 int index = 0;
4445
4446 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4447
4448 ret = afe_q6_interface_prepare();
4449 if (ret != 0) {
4450 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4451 return ret;
4452 }
4453
4454 index = q6audio_get_port_index(port_id);
4455 if (index < 0 || index >= AFE_MAX_PORTS) {
4456 pr_err("%s: AFE port index[%d] invalid!\n",
4457 __func__, index);
4458 return -EINVAL;
4459 }
4460 ret = q6audio_validate_port(port_id);
4461 if (ret < 0) {
4462 pr_err("%s: Invalid port 0x%x ret %d",
4463 __func__, port_id, ret);
4464 return -EINVAL;
4465 }
4466
4467 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4468 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4469 start.hdr.pkt_size = sizeof(start);
4470 start.hdr.src_port = 0;
4471 start.hdr.dest_port = 0;
4472 start.hdr.token = 0;
4473 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
4474 start.port_id = port_id;
4475 start.timing = 1;
4476 start.hdr.token = index;
4477
4478 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
4479 if (ret)
4480 pr_err("%s: AFE enable for port 0x%x failed %d\n",
4481 __func__, port_id, ret);
4482 return ret;
4483}
4484
4485int afe_pseudo_port_stop_nowait(u16 port_id)
4486{
4487 int ret = 0;
4488 struct afe_pseudoport_stop_command stop;
4489 int index = 0;
4490
4491 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4492
4493 if (this_afe.apr == NULL) {
4494 pr_err("%s: AFE is already closed\n", __func__);
4495 return -EINVAL;
4496 }
4497 index = q6audio_get_port_index(port_id);
4498 if (index < 0 || index >= AFE_MAX_PORTS) {
4499 pr_err("%s: AFE port index[%d] invalid!\n",
4500 __func__, index);
4501 return -EINVAL;
4502 }
4503 ret = q6audio_validate_port(port_id);
4504 if (ret < 0) {
4505 pr_err("%s: Invalid port 0x%x ret %d",
4506 __func__, port_id, ret);
4507 return -EINVAL;
4508 }
4509
4510 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4511 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4512 stop.hdr.pkt_size = sizeof(stop);
4513 stop.hdr.src_port = 0;
4514 stop.hdr.dest_port = 0;
4515 stop.hdr.token = 0;
4516 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
4517 stop.port_id = port_id;
4518 stop.reserved = 0;
4519 stop.hdr.token = index;
4520
4521 ret = afe_apr_send_pkt(&stop, NULL);
4522 if (ret)
4523 pr_err("%s: AFE close failed %d\n", __func__, ret);
4524
4525 return ret;
4526}
4527
4528int afe_port_group_set_param(u16 group_id,
4529 union afe_port_group_config *afe_group_config)
4530{
4531 int ret;
4532 struct afe_port_group_create config;
4533 int cfg_type;
4534
4535 if (!afe_group_config) {
4536 pr_err("%s: Error, no configuration data\n", __func__);
4537 return -EINVAL;
4538 }
4539
4540 pr_debug("%s: group id: 0x%x\n", __func__, group_id);
4541
4542 ret = afe_q6_interface_prepare();
4543 if (ret != 0) {
4544 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4545 return ret;
4546 }
4547
4548 switch (group_id) {
4549 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX:
4550 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX:
4551 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_RX:
4552 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_TX:
4553 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_RX:
4554 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_TX:
4555 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_RX:
4556 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304557 case AFE_GROUP_DEVICE_ID_QUINARY_TDM_RX:
4558 case AFE_GROUP_DEVICE_ID_QUINARY_TDM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304559 cfg_type = AFE_PARAM_ID_GROUP_DEVICE_TDM_CONFIG;
4560 break;
4561 default:
4562 pr_err("%s: Invalid group id 0x%x\n", __func__, group_id);
4563 return -EINVAL;
4564 }
4565
4566 memset(&config, 0, sizeof(config));
4567 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4568 APR_HDR_LEN(APR_HDR_SIZE),
4569 APR_PKT_VER);
4570 config.hdr.pkt_size = sizeof(config);
4571 config.hdr.src_port = 0;
4572 config.hdr.dest_port = 0;
4573 config.hdr.token = IDX_GLOBAL_CFG;
4574 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
4575
4576 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
4577 sizeof(config.param);
4578 config.param.payload_address_lsw = 0x00;
4579 config.param.payload_address_msw = 0x00;
4580 config.param.mem_map_handle = 0x00;
4581 config.pdata.module_id = AFE_MODULE_GROUP_DEVICE;
4582 config.pdata.param_id = cfg_type;
4583 config.pdata.param_size = sizeof(config.data);
4584 config.data = *afe_group_config;
4585
4586 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
4587 if (ret)
4588 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_CFG failed %d\n",
4589 __func__, ret);
4590
4591 return ret;
4592}
4593
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304594/**
4595 * afe_port_group_enable -
4596 * command to enable AFE port group
4597 *
4598 * @group_id: group ID for AFE port group
4599 * @afe_group_config: config for AFE group
4600 * @enable: flag to indicate enable or disable
4601 *
4602 * Returns 0 on success or error on failure
4603 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304604int afe_port_group_enable(u16 group_id,
4605 union afe_port_group_config *afe_group_config,
4606 u16 enable)
4607{
4608 int ret;
4609 struct afe_port_group_create config;
4610
4611 pr_debug("%s: group id: 0x%x enable: %d\n", __func__,
4612 group_id, enable);
4613
4614 ret = afe_q6_interface_prepare();
4615 if (ret != 0) {
4616 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4617 return ret;
4618 }
4619
4620 if (enable) {
4621 ret = afe_port_group_set_param(group_id, afe_group_config);
4622 if (ret < 0) {
4623 pr_err("%s: afe send failed %d\n", __func__, ret);
4624 return ret;
4625 }
4626 }
4627
4628 memset(&config, 0, sizeof(config));
4629 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4630 APR_HDR_LEN(APR_HDR_SIZE),
4631 APR_PKT_VER);
4632 config.hdr.pkt_size = sizeof(config);
4633 config.hdr.src_port = 0;
4634 config.hdr.dest_port = 0;
4635 config.hdr.token = IDX_GLOBAL_CFG;
4636 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
4637
4638 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
4639 sizeof(config.param);
4640 config.param.payload_address_lsw = 0x00;
4641 config.param.payload_address_msw = 0x00;
4642 config.param.mem_map_handle = 0x00;
4643 config.pdata.module_id = AFE_MODULE_GROUP_DEVICE;
4644 config.pdata.param_id = AFE_PARAM_ID_GROUP_DEVICE_ENABLE;
4645 config.pdata.param_size = sizeof(config.data);
4646 config.data.group_enable.group_id = group_id;
4647 config.data.group_enable.enable = enable;
4648
4649 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
4650 if (ret)
4651 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_ENABLE failed %d\n",
4652 __func__, ret);
4653
4654 return ret;
4655}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304656EXPORT_SYMBOL(afe_port_group_enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304657
4658int afe_stop_pseudo_port(u16 port_id)
4659{
4660 int ret = 0;
4661 struct afe_pseudoport_stop_command stop;
4662 int index = 0;
4663
4664 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4665
4666 if (this_afe.apr == NULL) {
4667 pr_err("%s: AFE is already closed\n", __func__);
4668 return -EINVAL;
4669 }
4670
4671 index = q6audio_get_port_index(port_id);
4672 if (index < 0 || index >= AFE_MAX_PORTS) {
4673 pr_err("%s: AFE port index[%d] invalid!\n",
4674 __func__, index);
4675 return -EINVAL;
4676 }
4677 ret = q6audio_validate_port(port_id);
4678 if (ret < 0) {
4679 pr_err("%s: Invalid port 0x%x ret %d\n",
4680 __func__, port_id, ret);
4681 return -EINVAL;
4682 }
4683
4684 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4685 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4686 stop.hdr.pkt_size = sizeof(stop);
4687 stop.hdr.src_port = 0;
4688 stop.hdr.dest_port = 0;
4689 stop.hdr.token = 0;
4690 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
4691 stop.port_id = port_id;
4692 stop.reserved = 0;
4693 stop.hdr.token = index;
4694
4695 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
4696 if (ret)
4697 pr_err("%s: AFE close failed %d\n", __func__, ret);
4698
4699 return ret;
4700}
4701
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304702/**
4703 * afe_req_mmap_handle -
4704 * Retrieve AFE memory map handle
4705 *
4706 * @ac: AFE audio client
4707 *
4708 * Returns memory map handle
4709 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304710uint32_t afe_req_mmap_handle(struct afe_audio_client *ac)
4711{
4712 return ac->mem_map_handle;
4713}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304714EXPORT_SYMBOL(afe_req_mmap_handle);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304715
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304716/**
4717 * q6afe_audio_client_alloc -
4718 * Assign new AFE audio client
4719 *
4720 * @priv: privata data to hold for audio client
4721 *
4722 * Returns ac pointer on success or NULL on failure
4723 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304724struct afe_audio_client *q6afe_audio_client_alloc(void *priv)
4725{
4726 struct afe_audio_client *ac;
4727 int lcnt = 0;
4728
4729 ac = kzalloc(sizeof(struct afe_audio_client), GFP_KERNEL);
4730 if (!ac)
4731 return NULL;
4732
4733 ac->priv = priv;
4734
4735 init_waitqueue_head(&ac->cmd_wait);
4736 INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
4737 INIT_LIST_HEAD(&ac->port[1].mem_map_handle);
4738 pr_debug("%s: mem_map_handle list init'ed\n", __func__);
4739 mutex_init(&ac->cmd_lock);
4740 for (lcnt = 0; lcnt <= OUT; lcnt++) {
4741 mutex_init(&ac->port[lcnt].lock);
4742 spin_lock_init(&ac->port[lcnt].dsp_lock);
4743 }
4744 atomic_set(&ac->cmd_state, 0);
4745
4746 return ac;
4747}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304748EXPORT_SYMBOL(q6afe_audio_client_alloc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304749
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304750/**
4751 * q6afe_audio_client_buf_alloc_contiguous -
4752 * Allocate contiguous shared buffers
4753 *
4754 * @dir: RX or TX direction of AFE port
4755 * @ac: AFE audio client handle
4756 * @bufsz: size of each shared buffer
4757 * @bufcnt: number of buffers
4758 *
4759 * Returns 0 on success or error on failure
4760 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304761int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir,
4762 struct afe_audio_client *ac,
4763 unsigned int bufsz,
4764 unsigned int bufcnt)
4765{
4766 int cnt = 0;
4767 int rc = 0;
4768 struct afe_audio_buffer *buf;
4769 size_t len;
4770
4771 if (!(ac) || ((dir != IN) && (dir != OUT))) {
4772 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
4773 return -EINVAL;
4774 }
4775
4776 pr_debug("%s: bufsz[%d]bufcnt[%d]\n",
4777 __func__,
4778 bufsz, bufcnt);
4779
4780 if (ac->port[dir].buf) {
4781 pr_debug("%s: buffer already allocated\n", __func__);
4782 return 0;
4783 }
4784 mutex_lock(&ac->cmd_lock);
4785 buf = kzalloc(((sizeof(struct afe_audio_buffer))*bufcnt),
4786 GFP_KERNEL);
4787
4788 if (!buf) {
4789 pr_err("%s: null buf\n", __func__);
4790 mutex_unlock(&ac->cmd_lock);
4791 goto fail;
4792 }
4793
4794 ac->port[dir].buf = buf;
4795
4796 rc = msm_audio_ion_alloc("afe_client", &buf[0].client,
4797 &buf[0].handle, bufsz*bufcnt,
4798 &buf[0].phys, &len,
4799 &buf[0].data);
4800 if (rc) {
4801 pr_err("%s: audio ION alloc failed, rc = %d\n",
4802 __func__, rc);
4803 mutex_unlock(&ac->cmd_lock);
4804 goto fail;
4805 }
4806
4807 buf[0].used = dir ^ 1;
4808 buf[0].size = bufsz;
4809 buf[0].actual_size = bufsz;
4810 cnt = 1;
4811 while (cnt < bufcnt) {
4812 if (bufsz > 0) {
4813 buf[cnt].data = buf[0].data + (cnt * bufsz);
4814 buf[cnt].phys = buf[0].phys + (cnt * bufsz);
4815 if (!buf[cnt].data) {
4816 pr_err("%s: Buf alloc failed\n",
4817 __func__);
4818 mutex_unlock(&ac->cmd_lock);
4819 goto fail;
4820 }
4821 buf[cnt].used = dir ^ 1;
4822 buf[cnt].size = bufsz;
4823 buf[cnt].actual_size = bufsz;
4824 pr_debug("%s: data[%pK]phys[%pK][%pK]\n", __func__,
4825 buf[cnt].data,
4826 &buf[cnt].phys,
4827 &buf[cnt].phys);
4828 }
4829 cnt++;
4830 }
4831 ac->port[dir].max_buf_cnt = cnt;
4832 mutex_unlock(&ac->cmd_lock);
4833 return 0;
4834fail:
4835 pr_err("%s: jump fail\n", __func__);
4836 q6afe_audio_client_buf_free_contiguous(dir, ac);
4837 return -EINVAL;
4838}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304839EXPORT_SYMBOL(q6afe_audio_client_buf_alloc_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304840
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304841/**
4842 * afe_memory_map -
4843 * command to map shared buffers to AFE
4844 *
4845 * @dma_addr_p: DMA physical address
4846 * @dma_buf_sz: shared DMA buffer size
4847 * @ac: AFE audio client handle
4848 *
4849 * Returns 0 on success or error on failure
4850 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304851int afe_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz,
4852 struct afe_audio_client *ac)
4853{
4854 int ret = 0;
4855
4856 mutex_lock(&this_afe.afe_cmd_lock);
4857 ac->mem_map_handle = 0;
4858 ret = afe_cmd_memory_map(dma_addr_p, dma_buf_sz);
4859 if (ret < 0) {
4860 pr_err("%s: afe_cmd_memory_map failed %d\n",
4861 __func__, ret);
4862
4863 mutex_unlock(&this_afe.afe_cmd_lock);
4864 return ret;
4865 }
4866 ac->mem_map_handle = this_afe.mmap_handle;
4867 mutex_unlock(&this_afe.afe_cmd_lock);
4868
4869 return ret;
4870}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304871EXPORT_SYMBOL(afe_memory_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304872
4873int afe_cmd_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz)
4874{
4875 int ret = 0;
4876 int cmd_size = 0;
4877 void *payload = NULL;
4878 void *mmap_region_cmd = NULL;
4879 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
4880 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
4881 int index = 0;
4882
4883 pr_debug("%s:\n", __func__);
4884
4885 if (this_afe.apr == NULL) {
4886 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4887 0xFFFFFFFF, &this_afe);
4888 pr_debug("%s: Register AFE\n", __func__);
4889 if (this_afe.apr == NULL) {
4890 pr_err("%s: Unable to register AFE\n", __func__);
4891 ret = -ENODEV;
4892 return ret;
4893 }
4894 rtac_set_afe_handle(this_afe.apr);
4895 }
4896 if (dma_buf_sz % SZ_4K != 0) {
4897 /*
4898 * The memory allocated by msm_audio_ion_alloc is always 4kB
4899 * aligned, ADSP expects the size to be 4kB aligned as well
4900 * so re-adjusts the buffer size before passing to ADSP.
4901 */
4902 dma_buf_sz = PAGE_ALIGN(dma_buf_sz);
4903 }
4904
4905 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
4906 + sizeof(struct afe_service_shared_map_region_payload);
4907
4908 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
4909 if (!mmap_region_cmd)
4910 return -ENOMEM;
4911
4912 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
4913 mmap_region_cmd;
4914 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4915 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4916 mregion->hdr.pkt_size = cmd_size;
4917 mregion->hdr.src_port = 0;
4918 mregion->hdr.dest_port = 0;
4919 mregion->hdr.token = 0;
4920 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
4921 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
4922 mregion->num_regions = 1;
4923 mregion->property_flag = 0x00;
4924 /* Todo */
4925 index = mregion->hdr.token = IDX_RSVD_2;
4926
4927 payload = ((u8 *) mmap_region_cmd +
4928 sizeof(struct afe_service_cmd_shared_mem_map_regions));
4929
4930 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
4931
4932 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
4933 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
4934 mregion_pl->mem_size_bytes = dma_buf_sz;
4935
4936 pr_debug("%s: dma_addr_p 0x%pK , size %d\n", __func__,
4937 &dma_addr_p, dma_buf_sz);
4938 atomic_set(&this_afe.state, 1);
4939 atomic_set(&this_afe.status, 0);
4940 this_afe.mmap_handle = 0;
4941 ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
4942 if (ret < 0) {
4943 pr_err("%s: AFE memory map cmd failed %d\n",
4944 __func__, ret);
4945 ret = -EINVAL;
4946 goto fail_cmd;
4947 }
4948
4949 ret = wait_event_timeout(this_afe.wait[index],
4950 (atomic_read(&this_afe.state) == 0),
4951 msecs_to_jiffies(TIMEOUT_MS));
4952 if (!ret) {
4953 pr_err("%s: wait_event timeout\n", __func__);
4954 ret = -EINVAL;
4955 goto fail_cmd;
4956 }
4957 if (atomic_read(&this_afe.status) > 0) {
4958 pr_err("%s: config cmd failed [%s]\n",
4959 __func__, adsp_err_get_err_str(
4960 atomic_read(&this_afe.status)));
4961 ret = adsp_err_get_lnx_err_code(
4962 atomic_read(&this_afe.status));
4963 goto fail_cmd;
4964 }
4965
4966 kfree(mmap_region_cmd);
4967 return 0;
4968fail_cmd:
4969 kfree(mmap_region_cmd);
4970 pr_err("%s: fail_cmd\n", __func__);
4971 return ret;
4972}
4973
4974int afe_cmd_memory_map_nowait(int port_id, phys_addr_t dma_addr_p,
4975 u32 dma_buf_sz)
4976{
4977 int ret = 0;
4978 int cmd_size = 0;
4979 void *payload = NULL;
4980 void *mmap_region_cmd = NULL;
4981 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
4982 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
4983 int index = 0;
4984
4985 pr_debug("%s:\n", __func__);
4986
4987 if (this_afe.apr == NULL) {
4988 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4989 0xFFFFFFFF, &this_afe);
4990 pr_debug("%s: Register AFE\n", __func__);
4991 if (this_afe.apr == NULL) {
4992 pr_err("%s: Unable to register AFE\n", __func__);
4993 ret = -ENODEV;
4994 return ret;
4995 }
4996 rtac_set_afe_handle(this_afe.apr);
4997 }
4998 index = q6audio_get_port_index(port_id);
4999 if (index < 0 || index >= AFE_MAX_PORTS) {
5000 pr_err("%s: AFE port index[%d] invalid!\n",
5001 __func__, index);
5002 return -EINVAL;
5003 }
5004 ret = q6audio_validate_port(port_id);
5005 if (ret < 0) {
5006 pr_err("%s: Invalid port 0x%x ret %d",
5007 __func__, port_id, ret);
5008 return -EINVAL;
5009 }
5010
5011 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
5012 + sizeof(struct afe_service_shared_map_region_payload);
5013
5014 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
5015 if (!mmap_region_cmd)
5016 return -ENOMEM;
5017
5018 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
5019 mmap_region_cmd;
5020 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5021 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5022 mregion->hdr.pkt_size = sizeof(mregion);
5023 mregion->hdr.src_port = 0;
5024 mregion->hdr.dest_port = 0;
5025 mregion->hdr.token = 0;
5026 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
5027 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
5028 mregion->num_regions = 1;
5029 mregion->property_flag = 0x00;
5030
5031 payload = ((u8 *) mmap_region_cmd +
5032 sizeof(struct afe_service_cmd_shared_mem_map_regions));
5033 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
5034
5035 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
5036 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
5037 mregion_pl->mem_size_bytes = dma_buf_sz;
5038
5039 ret = afe_apr_send_pkt(mmap_region_cmd, NULL);
5040 if (ret)
5041 pr_err("%s: AFE memory map cmd failed %d\n",
5042 __func__, ret);
5043 kfree(mmap_region_cmd);
5044 return ret;
5045}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305046
5047/**
5048 * q6afe_audio_client_buf_free_contiguous -
5049 * frees the shared contiguous memory
5050 *
5051 * @dir: RX or TX direction of port
5052 * @ac: AFE audio client handle
5053 *
5054 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305055int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
5056 struct afe_audio_client *ac)
5057{
5058 struct afe_audio_port_data *port;
5059 int cnt = 0;
5060
5061 mutex_lock(&ac->cmd_lock);
5062 port = &ac->port[dir];
5063 if (!port->buf) {
5064 pr_err("%s: buf is null\n", __func__);
5065 mutex_unlock(&ac->cmd_lock);
5066 return 0;
5067 }
5068 cnt = port->max_buf_cnt - 1;
5069
5070 if (port->buf[0].data) {
5071 pr_debug("%s: data[%pK]phys[%pK][%pK] , client[%pK] handle[%pK]\n",
5072 __func__,
5073 port->buf[0].data,
5074 &port->buf[0].phys,
5075 &port->buf[0].phys,
5076 port->buf[0].client,
5077 port->buf[0].handle);
5078 msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
5079 port->buf[0].client = NULL;
5080 port->buf[0].handle = NULL;
5081 }
5082
5083 while (cnt >= 0) {
5084 port->buf[cnt].data = NULL;
5085 port->buf[cnt].phys = 0;
5086 cnt--;
5087 }
5088 port->max_buf_cnt = 0;
5089 kfree(port->buf);
5090 port->buf = NULL;
5091 mutex_unlock(&ac->cmd_lock);
5092 return 0;
5093}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305094EXPORT_SYMBOL(q6afe_audio_client_buf_free_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305095
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305096/**
5097 * q6afe_audio_client_free -
5098 * frees the audio client from AFE
5099 *
5100 * @ac: AFE audio client handle
5101 *
5102 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305103void q6afe_audio_client_free(struct afe_audio_client *ac)
5104{
5105 int loopcnt;
5106 struct afe_audio_port_data *port;
5107
5108 if (!ac) {
5109 pr_err("%s: audio client is NULL\n", __func__);
5110 return;
5111 }
5112 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
5113 port = &ac->port[loopcnt];
5114 if (!port->buf)
5115 continue;
5116 pr_debug("%s: loopcnt = %d\n", __func__, loopcnt);
5117 q6afe_audio_client_buf_free_contiguous(loopcnt, ac);
5118 }
5119 kfree(ac);
5120}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305121EXPORT_SYMBOL(q6afe_audio_client_free);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305122
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305123/**
5124 * afe_cmd_memory_unmap -
5125 * command to unmap memory for AFE shared buffer
5126 *
5127 * @mem_map_handle: memory map handle to be unmapped
5128 *
5129 * Returns 0 on success or error on failure
5130 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305131int afe_cmd_memory_unmap(u32 mem_map_handle)
5132{
5133 int ret = 0;
5134 struct afe_service_cmd_shared_mem_unmap_regions mregion;
5135 int index = 0;
5136
5137 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
5138
5139 if (this_afe.apr == NULL) {
5140 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5141 0xFFFFFFFF, &this_afe);
5142 pr_debug("%s: Register AFE\n", __func__);
5143 if (this_afe.apr == NULL) {
5144 pr_err("%s: Unable to register AFE\n", __func__);
5145 ret = -ENODEV;
5146 return ret;
5147 }
5148 rtac_set_afe_handle(this_afe.apr);
5149 }
5150
5151 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5152 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5153 mregion.hdr.pkt_size = sizeof(mregion);
5154 mregion.hdr.src_port = 0;
5155 mregion.hdr.dest_port = 0;
5156 mregion.hdr.token = 0;
5157 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
5158 mregion.mem_map_handle = mem_map_handle;
5159
5160 /* Todo */
5161 index = mregion.hdr.token = IDX_RSVD_2;
5162
5163 atomic_set(&this_afe.status, 0);
5164 ret = afe_apr_send_pkt(&mregion, &this_afe.wait[index]);
5165 if (ret)
5166 pr_err("%s: AFE memory unmap cmd failed %d\n",
5167 __func__, ret);
5168
5169 return ret;
5170}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305171EXPORT_SYMBOL(afe_cmd_memory_unmap);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305172
5173int afe_cmd_memory_unmap_nowait(u32 mem_map_handle)
5174{
5175 int ret = 0;
5176 struct afe_service_cmd_shared_mem_unmap_regions mregion;
5177
5178 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
5179
5180 if (this_afe.apr == NULL) {
5181 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5182 0xFFFFFFFF, &this_afe);
5183 pr_debug("%s: Register AFE\n", __func__);
5184 if (this_afe.apr == NULL) {
5185 pr_err("%s: Unable to register AFE\n", __func__);
5186 ret = -ENODEV;
5187 return ret;
5188 }
5189 rtac_set_afe_handle(this_afe.apr);
5190 }
5191
5192 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5193 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5194 mregion.hdr.pkt_size = sizeof(mregion);
5195 mregion.hdr.src_port = 0;
5196 mregion.hdr.dest_port = 0;
5197 mregion.hdr.token = 0;
5198 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
5199 mregion.mem_map_handle = mem_map_handle;
5200
5201 ret = afe_apr_send_pkt(&mregion, NULL);
5202 if (ret)
5203 pr_err("%s: AFE memory unmap cmd failed %d\n",
5204 __func__, ret);
5205 return ret;
5206}
5207
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305208/**
5209 * afe_register_get_events -
5210 * register for events from proxy port
5211 *
5212 * @port_id: Port ID to register events
5213 * @cb: callback function to invoke for events from proxy port
5214 * @private_data: private data to sent back in callback fn
5215 *
5216 * Returns 0 on success or error on failure
5217 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305218int afe_register_get_events(u16 port_id,
5219 void (*cb)(uint32_t opcode,
5220 uint32_t token, uint32_t *payload, void *priv),
5221 void *private_data)
5222{
5223 int ret = 0;
5224 struct afe_service_cmd_register_rt_port_driver rtproxy;
5225
5226 pr_debug("%s: port_id: 0x%x\n", __func__, port_id);
5227
5228 if (this_afe.apr == NULL) {
5229 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5230 0xFFFFFFFF, &this_afe);
5231 pr_debug("%s: Register AFE\n", __func__);
5232 if (this_afe.apr == NULL) {
5233 pr_err("%s: Unable to register AFE\n", __func__);
5234 ret = -ENODEV;
5235 return ret;
5236 }
5237 rtac_set_afe_handle(this_afe.apr);
5238 }
5239 if ((port_id == RT_PROXY_DAI_002_RX) ||
5240 (port_id == RT_PROXY_DAI_001_TX)) {
5241 port_id = VIRTUAL_ID_TO_PORTID(port_id);
5242 } else {
5243 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
5244 return -EINVAL;
5245 }
5246
5247 if (port_id == RT_PROXY_PORT_001_TX) {
5248 this_afe.tx_cb = cb;
5249 this_afe.tx_private_data = private_data;
5250 } else if (port_id == RT_PROXY_PORT_001_RX) {
5251 this_afe.rx_cb = cb;
5252 this_afe.rx_private_data = private_data;
5253 }
5254
5255 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5256 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5257 rtproxy.hdr.pkt_size = sizeof(rtproxy);
5258 rtproxy.hdr.src_port = 1;
5259 rtproxy.hdr.dest_port = 1;
5260 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER;
5261 rtproxy.port_id = port_id;
5262 rtproxy.reserved = 0;
5263
5264 ret = afe_apr_send_pkt(&rtproxy, NULL);
5265 if (ret)
5266 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
5267 __func__, ret);
5268 return ret;
5269}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305270EXPORT_SYMBOL(afe_register_get_events);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305271
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305272/**
5273 * afe_unregister_get_events -
5274 * unregister for events from proxy port
5275 *
5276 * @port_id: Port ID to unregister events
5277 *
5278 * Returns 0 on success or error on failure
5279 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305280int afe_unregister_get_events(u16 port_id)
5281{
5282 int ret = 0;
5283 struct afe_service_cmd_unregister_rt_port_driver rtproxy;
5284 int index = 0;
5285
5286 pr_debug("%s:\n", __func__);
5287
5288 if (this_afe.apr == NULL) {
5289 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5290 0xFFFFFFFF, &this_afe);
5291 pr_debug("%s: Register AFE\n", __func__);
5292 if (this_afe.apr == NULL) {
5293 pr_err("%s: Unable to register AFE\n", __func__);
5294 ret = -ENODEV;
5295 return ret;
5296 }
5297 rtac_set_afe_handle(this_afe.apr);
5298 }
5299
5300 if ((port_id == RT_PROXY_DAI_002_RX) ||
5301 (port_id == RT_PROXY_DAI_001_TX)) {
5302 port_id = VIRTUAL_ID_TO_PORTID(port_id);
5303 } else {
5304 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
5305 return -EINVAL;
5306 }
5307
5308 index = q6audio_get_port_index(port_id);
5309 if (index < 0 || index >= AFE_MAX_PORTS) {
5310 pr_err("%s: AFE port index[%d] invalid!\n",
5311 __func__, index);
5312 return -EINVAL;
5313 }
5314 ret = q6audio_validate_port(port_id);
5315 if (ret < 0) {
5316 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
5317 return -EINVAL;
5318 }
5319
5320 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5321 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5322 rtproxy.hdr.pkt_size = sizeof(rtproxy);
5323 rtproxy.hdr.src_port = 0;
5324 rtproxy.hdr.dest_port = 0;
5325 rtproxy.hdr.token = 0;
5326 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER;
5327 rtproxy.port_id = port_id;
5328 rtproxy.reserved = 0;
5329
5330 rtproxy.hdr.token = index;
5331
5332 if (port_id == RT_PROXY_PORT_001_TX) {
5333 this_afe.tx_cb = NULL;
5334 this_afe.tx_private_data = NULL;
5335 } else if (port_id == RT_PROXY_PORT_001_RX) {
5336 this_afe.rx_cb = NULL;
5337 this_afe.rx_private_data = NULL;
5338 }
5339
5340 ret = afe_apr_send_pkt(&rtproxy, &this_afe.wait[index]);
5341 if (ret)
5342 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
5343 __func__, ret);
5344 return ret;
5345}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305346EXPORT_SYMBOL(afe_unregister_get_events);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305347
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305348/**
5349 * afe_rt_proxy_port_write -
5350 * command for AFE RT proxy port write
5351 *
5352 * @buf_addr_p: Physical buffer address with
5353 * playback data to proxy port
5354 * @mem_map_handle: memory map handle of write buffer
5355 * @bytes: number of bytes to write
5356 *
5357 * Returns 0 on success or error on failure
5358 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305359int afe_rt_proxy_port_write(phys_addr_t buf_addr_p,
5360 u32 mem_map_handle, int bytes)
5361{
5362 int ret = 0;
5363 struct afe_port_data_cmd_rt_proxy_port_write_v2 afecmd_wr;
5364
5365 if (this_afe.apr == NULL) {
5366 pr_err("%s: register to AFE is not done\n", __func__);
5367 ret = -ENODEV;
5368 return ret;
5369 }
5370 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
5371 &buf_addr_p, bytes);
5372
5373 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5374 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5375 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
5376 afecmd_wr.hdr.src_port = 0;
5377 afecmd_wr.hdr.dest_port = 0;
5378 afecmd_wr.hdr.token = 0;
5379 afecmd_wr.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2;
5380 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
5381 afecmd_wr.buffer_address_lsw = lower_32_bits(buf_addr_p);
5382 afecmd_wr.buffer_address_msw =
5383 msm_audio_populate_upper_32_bits(buf_addr_p);
5384 afecmd_wr.mem_map_handle = mem_map_handle;
5385 afecmd_wr.available_bytes = bytes;
5386 afecmd_wr.reserved = 0;
5387
5388 ret = afe_apr_send_pkt(&afecmd_wr, NULL);
5389 if (ret)
5390 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
5391 __func__, afecmd_wr.port_id, ret);
5392 return ret;
5393
5394}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305395EXPORT_SYMBOL(afe_rt_proxy_port_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305396
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305397/**
5398 * afe_rt_proxy_port_read -
5399 * command for AFE RT proxy port read
5400 *
5401 * @buf_addr_p: Physical buffer address to fill read data
5402 * @mem_map_handle: memory map handle for buffer read
5403 * @bytes: number of bytes to read
5404 *
5405 * Returns 0 on success or error on failure
5406 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305407int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
5408 u32 mem_map_handle, int bytes)
5409{
5410 int ret = 0;
5411 struct afe_port_data_cmd_rt_proxy_port_read_v2 afecmd_rd;
5412
5413 if (this_afe.apr == NULL) {
5414 pr_err("%s: register to AFE is not done\n", __func__);
5415 ret = -ENODEV;
5416 return ret;
5417 }
5418 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
5419 &buf_addr_p, bytes);
5420
5421 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5422 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5423 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
5424 afecmd_rd.hdr.src_port = 0;
5425 afecmd_rd.hdr.dest_port = 0;
5426 afecmd_rd.hdr.token = 0;
5427 afecmd_rd.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2;
5428 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
5429 afecmd_rd.buffer_address_lsw = lower_32_bits(buf_addr_p);
5430 afecmd_rd.buffer_address_msw =
5431 msm_audio_populate_upper_32_bits(buf_addr_p);
5432 afecmd_rd.available_bytes = bytes;
5433 afecmd_rd.mem_map_handle = mem_map_handle;
5434
5435 ret = afe_apr_send_pkt(&afecmd_rd, NULL);
5436 if (ret)
5437 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
5438 __func__, afecmd_rd.port_id, ret);
5439 return ret;
5440}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305441EXPORT_SYMBOL(afe_rt_proxy_port_read);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305442
5443#ifdef CONFIG_DEBUG_FS
5444static struct dentry *debugfs_afelb;
5445static struct dentry *debugfs_afelb_gain;
5446
5447static int afe_debug_open(struct inode *inode, struct file *file)
5448{
5449 file->private_data = inode->i_private;
5450 pr_info("%s: debug intf %s\n", __func__, (char *) file->private_data);
5451 return 0;
5452}
5453
5454static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
5455{
5456 char *token;
5457 int base, cnt;
5458
5459 token = strsep(&buf, " ");
5460
5461 for (cnt = 0; cnt < num_of_par; cnt++) {
5462 if (token != NULL) {
5463 if ((token[1] == 'x') || (token[1] == 'X'))
5464 base = 16;
5465 else
5466 base = 10;
5467
5468 if (kstrtoul(token, base, &param1[cnt]) != 0) {
5469 pr_err("%s: kstrtoul failed\n",
5470 __func__);
5471 return -EINVAL;
5472 }
5473
5474 token = strsep(&buf, " ");
5475 } else {
5476 pr_err("%s: token NULL\n", __func__);
5477 return -EINVAL;
5478 }
5479 }
5480 return 0;
5481}
5482#define AFE_LOOPBACK_ON (1)
5483#define AFE_LOOPBACK_OFF (0)
5484static ssize_t afe_debug_write(struct file *filp,
5485 const char __user *ubuf, size_t cnt, loff_t *ppos)
5486{
5487 char *lb_str = filp->private_data;
5488 char lbuf[32];
5489 int rc;
5490 unsigned long param[5];
5491
5492 if (cnt > sizeof(lbuf) - 1) {
5493 pr_err("%s: cnt %zd size %zd\n", __func__, cnt, sizeof(lbuf)-1);
5494 return -EINVAL;
5495 }
5496
5497 rc = copy_from_user(lbuf, ubuf, cnt);
5498 if (rc) {
5499 pr_err("%s: copy from user failed %d\n", __func__, rc);
5500 return -EFAULT;
5501 }
5502
5503 lbuf[cnt] = '\0';
5504
5505 if (!strcmp(lb_str, "afe_loopback")) {
5506 rc = afe_get_parameters(lbuf, param, 3);
5507 if (!rc) {
5508 pr_info("%s: %lu %lu %lu\n", lb_str, param[0], param[1],
5509 param[2]);
5510
5511 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
5512 AFE_LOOPBACK_OFF)) {
5513 pr_err("%s: Error, parameter 0 incorrect\n",
5514 __func__);
5515 rc = -EINVAL;
5516 goto afe_error;
5517 }
5518 if ((q6audio_validate_port(param[1]) < 0) ||
5519 (q6audio_validate_port(param[2])) < 0) {
5520 pr_err("%s: Error, invalid afe port\n",
5521 __func__);
5522 }
5523 if (this_afe.apr == NULL) {
5524 pr_err("%s: Error, AFE not opened\n", __func__);
5525 rc = -EINVAL;
5526 } else {
5527 rc = afe_loopback(param[0], param[1], param[2]);
5528 }
5529 } else {
5530 pr_err("%s: Error, invalid parameters\n", __func__);
5531 rc = -EINVAL;
5532 }
5533
5534 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
5535 rc = afe_get_parameters(lbuf, param, 2);
5536 if (!rc) {
5537 pr_info("%s: %s %lu %lu\n",
5538 __func__, lb_str, param[0], param[1]);
5539
5540 rc = q6audio_validate_port(param[0]);
5541 if (rc < 0) {
5542 pr_err("%s: Error, invalid afe port %d %lu\n",
5543 __func__, rc, param[0]);
5544 rc = -EINVAL;
5545 goto afe_error;
5546 }
5547
5548 if (param[1] > 100) {
5549 pr_err("%s: Error, volume should be 0 to 100 percentage param = %lu\n",
5550 __func__, param[1]);
5551 rc = -EINVAL;
5552 goto afe_error;
5553 }
5554
5555 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
5556
5557 if (this_afe.apr == NULL) {
5558 pr_err("%s: Error, AFE not opened\n", __func__);
5559 rc = -EINVAL;
5560 } else {
5561 rc = afe_loopback_gain(param[0], param[1]);
5562 }
5563 } else {
5564 pr_err("%s: Error, invalid parameters\n", __func__);
5565 rc = -EINVAL;
5566 }
5567 }
5568
5569afe_error:
5570 if (rc == 0)
5571 rc = cnt;
5572 else
5573 pr_err("%s: rc = %d\n", __func__, rc);
5574
5575 return rc;
5576}
5577
5578static const struct file_operations afe_debug_fops = {
5579 .open = afe_debug_open,
5580 .write = afe_debug_write
5581};
5582
5583static void config_debug_fs_init(void)
5584{
5585 debugfs_afelb = debugfs_create_file("afe_loopback",
5586 0664, NULL, (void *) "afe_loopback",
5587 &afe_debug_fops);
5588
5589 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
5590 0664, NULL, (void *) "afe_loopback_gain",
5591 &afe_debug_fops);
5592}
5593static void config_debug_fs_exit(void)
5594{
5595 debugfs_remove(debugfs_afelb);
5596 debugfs_remove(debugfs_afelb_gain);
5597}
5598#else
5599static void config_debug_fs_init(void)
5600{
5601}
5602static void config_debug_fs_exit(void)
5603{
5604}
5605#endif
5606
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305607/**
5608 * afe_set_dtmf_gen_rx_portid -
5609 * Set port_id for DTMF tone generation
5610 *
5611 * @port_id: AFE port id
5612 * @set: set or reset port id value for dtmf gen
5613 *
5614 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305615void afe_set_dtmf_gen_rx_portid(u16 port_id, int set)
5616{
5617 if (set)
5618 this_afe.dtmf_gen_rx_portid = port_id;
5619 else if (this_afe.dtmf_gen_rx_portid == port_id)
5620 this_afe.dtmf_gen_rx_portid = -1;
5621}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305622EXPORT_SYMBOL(afe_set_dtmf_gen_rx_portid);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305623
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305624/**
5625 * afe_dtmf_generate_rx - command to generate AFE DTMF RX
5626 *
5627 * @duration_in_ms: Duration in ms for dtmf tone
5628 * @high_freq: Higher frequency for dtmf
5629 * @low_freq: lower frequency for dtmf
5630 * @gain: Gain value for DTMF tone
5631 *
5632 * Returns 0 on success, appropriate error code otherwise
5633 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305634int afe_dtmf_generate_rx(int64_t duration_in_ms,
5635 uint16_t high_freq,
5636 uint16_t low_freq, uint16_t gain)
5637{
5638 int ret = 0;
5639 int index = 0;
5640 struct afe_dtmf_generation_command cmd_dtmf;
5641
5642 pr_debug("%s: DTMF AFE Gen\n", __func__);
5643
5644 if (afe_validate_port(this_afe.dtmf_gen_rx_portid) < 0) {
5645 pr_err("%s: Failed : Invalid Port id = 0x%x\n",
5646 __func__, this_afe.dtmf_gen_rx_portid);
5647 ret = -EINVAL;
5648 goto fail_cmd;
5649 }
5650
5651 if (this_afe.apr == NULL) {
5652 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5653 0xFFFFFFFF, &this_afe);
5654 pr_debug("%s: Register AFE\n", __func__);
5655 if (this_afe.apr == NULL) {
5656 pr_err("%s: Unable to register AFE\n", __func__);
5657 ret = -ENODEV;
5658 return ret;
5659 }
5660 rtac_set_afe_handle(this_afe.apr);
5661 }
5662
5663 pr_debug("%s: dur=%lld: hfreq=%d lfreq=%d gain=%d portid=0x%x\n",
5664 __func__,
5665 duration_in_ms, high_freq, low_freq, gain,
5666 this_afe.dtmf_gen_rx_portid);
5667
5668 cmd_dtmf.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5669 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5670 cmd_dtmf.hdr.pkt_size = sizeof(cmd_dtmf);
5671 cmd_dtmf.hdr.src_port = 0;
5672 cmd_dtmf.hdr.dest_port = 0;
5673 cmd_dtmf.hdr.token = 0;
5674 cmd_dtmf.hdr.opcode = AFE_PORTS_CMD_DTMF_CTL;
5675 cmd_dtmf.duration_in_ms = duration_in_ms;
5676 cmd_dtmf.high_freq = high_freq;
5677 cmd_dtmf.low_freq = low_freq;
5678 cmd_dtmf.gain = gain;
5679 cmd_dtmf.num_ports = 1;
5680 cmd_dtmf.port_ids = q6audio_get_port_id(this_afe.dtmf_gen_rx_portid);
5681
5682 atomic_set(&this_afe.state, 1);
5683 atomic_set(&this_afe.status, 0);
5684 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_dtmf);
5685 if (ret < 0) {
5686 pr_err("%s: AFE DTMF failed for num_ports:%d ids:0x%x\n",
5687 __func__, cmd_dtmf.num_ports, cmd_dtmf.port_ids);
5688 ret = -EINVAL;
5689 goto fail_cmd;
5690 }
5691 index = q6audio_get_port_index(this_afe.dtmf_gen_rx_portid);
5692 if (index < 0 || index >= AFE_MAX_PORTS) {
5693 pr_err("%s: AFE port index[%d] invalid!\n",
5694 __func__, index);
5695 ret = -EINVAL;
5696 goto fail_cmd;
5697 }
5698 ret = wait_event_timeout(this_afe.wait[index],
5699 (atomic_read(&this_afe.state) == 0),
5700 msecs_to_jiffies(TIMEOUT_MS));
5701 if (!ret) {
5702 pr_err("%s: wait_event timeout\n", __func__);
5703 ret = -EINVAL;
5704 goto fail_cmd;
5705 }
5706 if (atomic_read(&this_afe.status) > 0) {
5707 pr_err("%s: config cmd failed [%s]\n",
5708 __func__, adsp_err_get_err_str(
5709 atomic_read(&this_afe.status)));
5710 ret = adsp_err_get_lnx_err_code(
5711 atomic_read(&this_afe.status));
5712 goto fail_cmd;
5713 }
5714 return 0;
5715
5716fail_cmd:
5717 pr_err("%s: failed %d\n", __func__, ret);
5718 return ret;
5719}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305720EXPORT_SYMBOL(afe_dtmf_generate_rx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305721
5722static int afe_sidetone_iir(u16 tx_port_id)
5723{
5724 struct afe_loopback_iir_cfg_v2 iir_sidetone;
5725 int ret;
5726 int index = 0;
5727 uint16_t size = 0;
5728 int cal_index = AFE_SIDETONE_IIR_CAL;
5729 int iir_pregain = 0;
5730 int iir_num_biquad_stages = 0;
5731 int iir_enable;
5732 struct cal_block_data *cal_block;
5733 int mid;
5734
5735 memset(&iir_sidetone, 0, sizeof(iir_sidetone));
5736 index = q6audio_get_port_index(tx_port_id);
5737 iir_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5738 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5739 iir_sidetone.hdr.pkt_size = sizeof(iir_sidetone);
5740 iir_sidetone.hdr.src_port = 0;
5741 iir_sidetone.hdr.dest_port = 0;
5742 iir_sidetone.hdr.token = index;
5743 iir_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
5744 iir_sidetone.param.port_id = tx_port_id;
5745 iir_sidetone.param.payload_address_lsw = 0x00;
5746 iir_sidetone.param.payload_address_msw = 0x00;
5747 iir_sidetone.param.mem_map_handle = 0x00;
5748
5749 if (this_afe.cal_data[cal_index] == NULL) {
5750 pr_err("%s: cal data is NULL\n", __func__);
5751 ret = -EINVAL;
5752 goto done;
5753 }
5754 mutex_lock(&this_afe.cal_data[cal_index]->lock);
5755 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07005756 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305757 pr_err("%s: cal_block not found\n ", __func__);
5758 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5759 ret = -EINVAL;
5760 goto done;
5761 }
5762
5763 iir_pregain = ((struct audio_cal_info_sidetone_iir *)
5764 cal_block->cal_info)->pregain;
5765 iir_enable = ((struct audio_cal_info_sidetone_iir *)
5766 cal_block->cal_info)->iir_enable;
5767 iir_num_biquad_stages = ((struct audio_cal_info_sidetone_iir *)
5768 cal_block->cal_info)->num_biquad_stages;
5769 mid = ((struct audio_cal_info_sidetone_iir *)
5770 cal_block->cal_info)->mid;
5771
5772 /*
5773 * calculate the actual size of payload based on no of stages
5774 * enabled in calibration
5775 */
5776 size = (MAX_SIDETONE_IIR_DATA_SIZE / MAX_NO_IIR_FILTER_STAGE) *
5777 iir_num_biquad_stages;
5778 /*
5779 * For an odd number of stages, 2 bytes of padding are
5780 * required at the end of the payload.
5781 */
5782 if (iir_num_biquad_stages % 2) {
5783 pr_debug("%s: adding 2 to size:%d\n", __func__, size);
5784 size = size + 2;
5785 }
5786 memcpy(&iir_sidetone.st_iir_filter_config_data.iir_config,
5787 &((struct audio_cal_info_sidetone_iir *)
5788 cal_block->cal_info)->iir_config,
5789 sizeof(iir_sidetone.st_iir_filter_config_data.iir_config));
5790 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5791
5792 /*
5793 * Calculate the payload size for setparams command
5794 */
5795 iir_sidetone.param.payload_size = (sizeof(iir_sidetone) -
5796 sizeof(struct apr_hdr) -
5797 sizeof(struct afe_port_cmd_set_param_v2) -
5798 (MAX_SIDETONE_IIR_DATA_SIZE - size));
5799
5800 pr_debug("%s: payload size :%d\n", __func__,
5801 iir_sidetone.param.payload_size);
5802
5803 /*
5804 * Set IIR enable params
5805 */
5806 iir_sidetone.st_iir_enable_pdata.module_id = mid;
5807 iir_sidetone.st_iir_enable_pdata.param_id =
5808 AFE_PARAM_ID_ENABLE;
5809 iir_sidetone.st_iir_enable_pdata.param_size =
5810 sizeof(iir_sidetone.st_iir_mode_enable_data);
5811 iir_sidetone.st_iir_mode_enable_data.enable = iir_enable;
5812
5813 /*
5814 * Set IIR filter config params
5815 */
5816 iir_sidetone.st_iir_filter_config_pdata.module_id = mid;
5817 iir_sidetone.st_iir_filter_config_pdata.param_id =
5818 AFE_PARAM_ID_SIDETONE_IIR_FILTER_CONFIG;
5819 iir_sidetone.st_iir_filter_config_pdata.param_size =
5820 sizeof(iir_sidetone.st_iir_filter_config_data.num_biquad_stages)
5821 +
5822 sizeof(iir_sidetone.st_iir_filter_config_data.pregain) + size;
5823 iir_sidetone.st_iir_filter_config_pdata.reserved = 0;
5824 iir_sidetone.st_iir_filter_config_data.num_biquad_stages =
5825 iir_num_biquad_stages;
5826 iir_sidetone.st_iir_filter_config_data.pregain = iir_pregain;
5827 pr_debug("%s: tx(0x%x)mid(0x%x)iir_en(%d)stg(%d)gain(0x%x)size(%d)\n",
5828 __func__, tx_port_id, mid,
5829 iir_sidetone.st_iir_mode_enable_data.enable,
5830 iir_sidetone.st_iir_filter_config_data.num_biquad_stages,
5831 iir_sidetone.st_iir_filter_config_data.pregain,
5832 iir_sidetone.st_iir_filter_config_pdata.param_size);
5833 ret = afe_apr_send_pkt(&iir_sidetone, &this_afe.wait[index]);
5834 if (ret)
5835 pr_err("%s: AFE sidetone failed for tx_port(0x%x)\n",
5836 __func__, tx_port_id);
5837
5838done:
5839 return ret;
5840
5841}
5842
5843static int afe_sidetone(u16 tx_port_id, u16 rx_port_id, bool enable)
5844{
5845 struct afe_st_loopback_cfg_v1 cmd_sidetone;
5846 int ret;
5847 int index;
5848 int cal_index = AFE_SIDETONE_CAL;
5849 int sidetone_gain;
5850 int sidetone_enable;
5851 struct cal_block_data *cal_block;
5852 int mid = 0;
5853
5854 memset(&cmd_sidetone, 0, sizeof(cmd_sidetone));
5855 if (this_afe.cal_data[cal_index] == NULL) {
5856 pr_err("%s: cal data is NULL\n", __func__);
5857 ret = -EINVAL;
5858 goto done;
5859 }
5860 mutex_lock(&this_afe.cal_data[cal_index]->lock);
5861 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07005862 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305863 pr_err("%s: cal_block not found\n", __func__);
5864 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5865 ret = -EINVAL;
5866 goto done;
5867 }
5868 sidetone_gain = ((struct audio_cal_info_sidetone *)
5869 cal_block->cal_info)->gain;
5870 sidetone_enable = ((struct audio_cal_info_sidetone *)
5871 cal_block->cal_info)->enable;
5872 mid = ((struct audio_cal_info_sidetone *)
5873 cal_block->cal_info)->mid;
5874 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5875
5876 index = q6audio_get_port_index(tx_port_id);
5877 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5878 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5879 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
5880 cmd_sidetone.hdr.src_port = 0;
5881 cmd_sidetone.hdr.dest_port = 0;
5882 cmd_sidetone.hdr.token = index;
5883 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
5884 cmd_sidetone.param.port_id = tx_port_id;
5885 cmd_sidetone.param.payload_size = (sizeof(cmd_sidetone) -
5886 sizeof(struct apr_hdr) -
5887 sizeof(struct afe_port_cmd_set_param_v2));
5888 cmd_sidetone.param.payload_address_lsw = 0x00;
5889 cmd_sidetone.param.payload_address_msw = 0x00;
5890 cmd_sidetone.param.mem_map_handle = 0x00;
5891 cmd_sidetone.gain_pdata.module_id = AFE_MODULE_LOOPBACK;
5892 cmd_sidetone.gain_pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
5893 /*
5894 * size of actual payload only
5895 */
5896 cmd_sidetone.gain_pdata.param_size = sizeof(
5897 struct afe_loopback_sidetone_gain);
5898 cmd_sidetone.gain_data.rx_port_id = rx_port_id;
5899 cmd_sidetone.gain_data.gain = sidetone_gain;
5900
5901 cmd_sidetone.cfg_pdata.module_id = AFE_MODULE_LOOPBACK;
5902 cmd_sidetone.cfg_pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
5903 /*
5904 * size of actual payload only
5905 */
5906 cmd_sidetone.cfg_pdata.param_size = sizeof(struct loopback_cfg_data);
5907 cmd_sidetone.cfg_data.loopback_cfg_minor_version =
5908 AFE_API_VERSION_LOOPBACK_CONFIG;
5909 cmd_sidetone.cfg_data.dst_port_id = rx_port_id;
5910 cmd_sidetone.cfg_data.routing_mode = LB_MODE_SIDETONE;
5911 cmd_sidetone.cfg_data.enable = enable;
5912
5913 pr_debug("%s rx(0x%x) tx(0x%x) enable(%d) mid(0x%x) gain(%d) sidetone_enable(%d)\n",
5914 __func__, rx_port_id, tx_port_id,
5915 enable, mid, sidetone_gain, sidetone_enable);
5916
5917 ret = afe_apr_send_pkt(&cmd_sidetone, &this_afe.wait[index]);
5918 if (ret)
5919 pr_err("%s: AFE sidetone send failed for tx_port:%d rx_port:%d ret:%d\n",
5920 __func__, tx_port_id, rx_port_id, ret);
5921done:
5922 return ret;
5923}
5924
5925int afe_sidetone_enable(u16 tx_port_id, u16 rx_port_id, bool enable)
5926{
5927 int ret;
5928 int index;
5929
5930 index = q6audio_get_port_index(rx_port_id);
5931 if (index < 0 || index >= AFE_MAX_PORTS) {
5932 pr_err("%s: AFE port index[%d] invalid!\n",
5933 __func__, index);
5934 ret = -EINVAL;
5935 goto done;
5936 }
5937 if (q6audio_validate_port(rx_port_id) < 0) {
5938 pr_err("%s: Invalid port 0x%x\n",
5939 __func__, rx_port_id);
5940 ret = -EINVAL;
5941 goto done;
5942 }
5943 index = q6audio_get_port_index(tx_port_id);
5944 if (index < 0 || index >= AFE_MAX_PORTS) {
5945 pr_err("%s: AFE port index[%d] invalid!\n",
5946 __func__, index);
5947 ret = -EINVAL;
5948 goto done;
5949 }
5950 if (q6audio_validate_port(tx_port_id) < 0) {
5951 pr_err("%s: Invalid port 0x%x\n",
5952 __func__, tx_port_id);
5953 ret = -EINVAL;
5954 goto done;
5955 }
5956 if (enable) {
5957 ret = afe_sidetone_iir(tx_port_id);
5958 if (ret)
5959 goto done;
5960 }
5961
5962 ret = afe_sidetone(tx_port_id, rx_port_id, enable);
5963
5964done:
5965 return ret;
5966}
5967
5968int afe_validate_port(u16 port_id)
5969{
5970 int ret;
5971
5972 switch (port_id) {
5973 case PRIMARY_I2S_RX:
5974 case PRIMARY_I2S_TX:
5975 case AFE_PORT_ID_PRIMARY_PCM_RX:
5976 case AFE_PORT_ID_PRIMARY_PCM_TX:
5977 case AFE_PORT_ID_SECONDARY_PCM_RX:
5978 case AFE_PORT_ID_SECONDARY_PCM_TX:
5979 case AFE_PORT_ID_TERTIARY_PCM_RX:
5980 case AFE_PORT_ID_TERTIARY_PCM_TX:
5981 case AFE_PORT_ID_QUATERNARY_PCM_RX:
5982 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05305983 case AFE_PORT_ID_QUINARY_PCM_RX:
5984 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305985 case SECONDARY_I2S_RX:
5986 case SECONDARY_I2S_TX:
5987 case MI2S_RX:
5988 case MI2S_TX:
5989 case HDMI_RX:
5990 case DISPLAY_PORT_RX:
5991 case AFE_PORT_ID_SPDIF_RX:
5992 case RSVD_2:
5993 case RSVD_3:
5994 case DIGI_MIC_TX:
5995 case VOICE_RECORD_RX:
5996 case VOICE_RECORD_TX:
5997 case VOICE_PLAYBACK_TX:
5998 case VOICE2_PLAYBACK_TX:
5999 case SLIMBUS_0_RX:
6000 case SLIMBUS_0_TX:
6001 case SLIMBUS_1_RX:
6002 case SLIMBUS_1_TX:
6003 case SLIMBUS_2_RX:
6004 case SLIMBUS_2_TX:
6005 case SLIMBUS_3_RX:
6006 case INT_BT_SCO_RX:
6007 case INT_BT_SCO_TX:
6008 case INT_BT_A2DP_RX:
6009 case INT_FM_RX:
6010 case INT_FM_TX:
6011 case RT_PROXY_PORT_001_RX:
6012 case RT_PROXY_PORT_001_TX:
6013 case SLIMBUS_4_RX:
6014 case SLIMBUS_4_TX:
6015 case SLIMBUS_5_RX:
6016 case SLIMBUS_6_RX:
6017 case SLIMBUS_6_TX:
6018 case SLIMBUS_7_RX:
6019 case SLIMBUS_7_TX:
6020 case SLIMBUS_8_RX:
6021 case SLIMBUS_8_TX:
6022 case AFE_PORT_ID_USB_RX:
6023 case AFE_PORT_ID_USB_TX:
6024 case AFE_PORT_ID_PRIMARY_MI2S_RX:
6025 case AFE_PORT_ID_PRIMARY_MI2S_TX:
6026 case AFE_PORT_ID_SECONDARY_MI2S_RX:
6027 case AFE_PORT_ID_SECONDARY_MI2S_TX:
6028 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
6029 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
6030 case AFE_PORT_ID_TERTIARY_MI2S_RX:
6031 case AFE_PORT_ID_TERTIARY_MI2S_TX:
6032 case AFE_PORT_ID_QUINARY_MI2S_RX:
6033 case AFE_PORT_ID_QUINARY_MI2S_TX:
6034 case AFE_PORT_ID_SENARY_MI2S_TX:
6035 case AFE_PORT_ID_PRIMARY_TDM_RX:
6036 case AFE_PORT_ID_PRIMARY_TDM_TX:
6037 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
6038 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
6039 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
6040 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
6041 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
6042 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
6043 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
6044 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
6045 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
6046 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
6047 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
6048 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
6049 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
6050 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
6051 case AFE_PORT_ID_SECONDARY_TDM_RX:
6052 case AFE_PORT_ID_SECONDARY_TDM_TX:
6053 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
6054 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
6055 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
6056 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
6057 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
6058 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
6059 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
6060 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
6061 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
6062 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
6063 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
6064 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
6065 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
6066 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
6067 case AFE_PORT_ID_TERTIARY_TDM_RX:
6068 case AFE_PORT_ID_TERTIARY_TDM_TX:
6069 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
6070 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
6071 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
6072 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
6073 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
6074 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
6075 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
6076 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
6077 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
6078 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
6079 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
6080 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
6081 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
6082 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
6083 case AFE_PORT_ID_QUATERNARY_TDM_RX:
6084 case AFE_PORT_ID_QUATERNARY_TDM_TX:
6085 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
6086 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
6087 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
6088 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
6089 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
6090 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
6091 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
6092 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
6093 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
6094 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
6095 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
6096 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
6097 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
6098 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05306099 case AFE_PORT_ID_QUINARY_TDM_RX:
6100 case AFE_PORT_ID_QUINARY_TDM_TX:
6101 case AFE_PORT_ID_QUINARY_TDM_RX_1:
6102 case AFE_PORT_ID_QUINARY_TDM_TX_1:
6103 case AFE_PORT_ID_QUINARY_TDM_RX_2:
6104 case AFE_PORT_ID_QUINARY_TDM_TX_2:
6105 case AFE_PORT_ID_QUINARY_TDM_RX_3:
6106 case AFE_PORT_ID_QUINARY_TDM_TX_3:
6107 case AFE_PORT_ID_QUINARY_TDM_RX_4:
6108 case AFE_PORT_ID_QUINARY_TDM_TX_4:
6109 case AFE_PORT_ID_QUINARY_TDM_RX_5:
6110 case AFE_PORT_ID_QUINARY_TDM_TX_5:
6111 case AFE_PORT_ID_QUINARY_TDM_RX_6:
6112 case AFE_PORT_ID_QUINARY_TDM_TX_6:
6113 case AFE_PORT_ID_QUINARY_TDM_RX_7:
6114 case AFE_PORT_ID_QUINARY_TDM_TX_7:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306115 case AFE_PORT_ID_INT0_MI2S_RX:
6116 case AFE_PORT_ID_INT1_MI2S_RX:
6117 case AFE_PORT_ID_INT2_MI2S_RX:
6118 case AFE_PORT_ID_INT3_MI2S_RX:
6119 case AFE_PORT_ID_INT4_MI2S_RX:
6120 case AFE_PORT_ID_INT5_MI2S_RX:
6121 case AFE_PORT_ID_INT6_MI2S_RX:
6122 case AFE_PORT_ID_INT0_MI2S_TX:
6123 case AFE_PORT_ID_INT1_MI2S_TX:
6124 case AFE_PORT_ID_INT2_MI2S_TX:
6125 case AFE_PORT_ID_INT3_MI2S_TX:
6126 case AFE_PORT_ID_INT4_MI2S_TX:
6127 case AFE_PORT_ID_INT5_MI2S_TX:
6128 case AFE_PORT_ID_INT6_MI2S_TX:
6129 {
6130 ret = 0;
6131 break;
6132 }
6133
6134 default:
6135 pr_err("%s: default ret 0x%x\n", __func__, port_id);
6136 ret = -EINVAL;
6137 }
6138
6139 return ret;
6140}
6141
6142int afe_convert_virtual_to_portid(u16 port_id)
6143{
6144 int ret;
6145
6146 /*
6147 * if port_id is virtual, convert to physical..
6148 * if port_id is already physical, return physical
6149 */
6150 if (afe_validate_port(port_id) < 0) {
6151 if (port_id == RT_PROXY_DAI_001_RX ||
6152 port_id == RT_PROXY_DAI_001_TX ||
6153 port_id == RT_PROXY_DAI_002_RX ||
6154 port_id == RT_PROXY_DAI_002_TX) {
6155 ret = VIRTUAL_ID_TO_PORTID(port_id);
6156 } else {
6157 pr_err("%s: wrong port 0x%x\n",
6158 __func__, port_id);
6159 ret = -EINVAL;
6160 }
6161 } else
6162 ret = port_id;
6163
6164 return ret;
6165}
6166int afe_port_stop_nowait(int port_id)
6167{
6168 struct afe_port_cmd_device_stop stop;
6169 int ret = 0;
6170
6171 if (this_afe.apr == NULL) {
6172 pr_err("%s: AFE is already closed\n", __func__);
6173 ret = -EINVAL;
6174 goto fail_cmd;
6175 }
6176 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
6177 port_id = q6audio_convert_virtual_to_portid(port_id);
6178
6179 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6180 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6181 stop.hdr.pkt_size = sizeof(stop);
6182 stop.hdr.src_port = 0;
6183 stop.hdr.dest_port = 0;
6184 stop.hdr.token = 0;
6185 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
6186 stop.port_id = port_id;
6187 stop.reserved = 0;
6188
6189 ret = afe_apr_send_pkt(&stop, NULL);
6190 if (ret)
6191 pr_err("%s: AFE close failed %d\n", __func__, ret);
6192
6193fail_cmd:
6194 return ret;
6195
6196}
6197
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306198/**
6199 * afe_close - command to close AFE port
6200 *
6201 * @port_id: AFE port id
6202 *
6203 * Returns 0 on success, appropriate error code otherwise
6204 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306205int afe_close(int port_id)
6206{
6207 struct afe_port_cmd_device_stop stop;
6208 enum afe_mad_type mad_type;
6209 int ret = 0;
6210 int index = 0;
6211 uint16_t port_index;
6212
6213 if (this_afe.apr == NULL) {
6214 pr_err("%s: AFE is already closed\n", __func__);
6215 if ((port_id == RT_PROXY_DAI_001_RX) ||
6216 (port_id == RT_PROXY_DAI_002_TX))
6217 pcm_afe_instance[port_id & 0x1] = 0;
6218 if ((port_id == RT_PROXY_DAI_002_RX) ||
6219 (port_id == RT_PROXY_DAI_001_TX))
6220 proxy_afe_instance[port_id & 0x1] = 0;
6221 afe_close_done[port_id & 0x1] = true;
6222 ret = -EINVAL;
6223 goto fail_cmd;
6224 }
6225 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
6226 if ((port_id == RT_PROXY_DAI_001_RX) ||
6227 (port_id == RT_PROXY_DAI_002_TX)) {
6228 pr_debug("%s: before decrementing pcm_afe_instance %d\n",
6229 __func__, pcm_afe_instance[port_id & 0x1]);
6230 port_id = VIRTUAL_ID_TO_PORTID(port_id);
6231 pcm_afe_instance[port_id & 0x1]--;
6232 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
6233 proxy_afe_instance[port_id & 0x1] == 0)) ||
6234 afe_close_done[port_id & 0x1] == true)
6235 return 0;
6236
6237 afe_close_done[port_id & 0x1] = true;
6238 }
6239
6240 if ((port_id == RT_PROXY_DAI_002_RX) ||
6241 (port_id == RT_PROXY_DAI_001_TX)) {
6242 pr_debug("%s: before decrementing proxy_afe_instance %d\n",
6243 __func__, proxy_afe_instance[port_id & 0x1]);
6244 port_id = VIRTUAL_ID_TO_PORTID(port_id);
6245 proxy_afe_instance[port_id & 0x1]--;
6246 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
6247 proxy_afe_instance[port_id & 0x1] == 0)) ||
6248 afe_close_done[port_id & 0x1] == true)
6249 return 0;
6250
6251 afe_close_done[port_id & 0x1] = true;
6252 }
6253
6254 port_id = q6audio_convert_virtual_to_portid(port_id);
6255 index = q6audio_get_port_index(port_id);
6256 if (index < 0 || index >= AFE_MAX_PORTS) {
6257 pr_err("%s: AFE port index[%d] invalid!\n",
6258 __func__, index);
6259 return -EINVAL;
6260 }
6261 ret = q6audio_validate_port(port_id);
6262 if (ret < 0) {
6263 pr_warn("%s: Not a valid port id 0x%x ret %d\n",
6264 __func__, port_id, ret);
6265 return -EINVAL;
6266 }
6267
6268 mad_type = afe_port_get_mad_type(port_id);
6269 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
6270 mad_type);
6271 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
6272 pr_debug("%s: Turn off MAD\n", __func__);
6273 ret = afe_turn_onoff_hw_mad(mad_type, false);
6274 if (ret) {
6275 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
6276 __func__, ret);
6277 return ret;
6278 }
6279 } else {
6280 pr_debug("%s: Not a MAD port\n", __func__);
6281 }
6282
6283 port_index = afe_get_port_index(port_id);
6284 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
6285 this_afe.afe_sample_rates[port_index] = 0;
6286 this_afe.topology[port_index] = 0;
6287 this_afe.dev_acdb_id[port_index] = 0;
6288 } else {
6289 pr_err("%s: port %d\n", __func__, port_index);
6290 ret = -EINVAL;
6291 goto fail_cmd;
6292 }
6293
6294 if ((port_id == this_afe.aanc_info.aanc_tx_port) &&
6295 (this_afe.aanc_info.aanc_active)) {
6296 memset(&this_afe.aanc_info, 0x00, sizeof(this_afe.aanc_info));
6297 ret = afe_aanc_mod_enable(this_afe.apr, port_id, 0);
6298 if (ret)
6299 pr_err("%s: AFE mod disable failed %d\n",
6300 __func__, ret);
6301 }
6302
6303 /*
6304 * even if ramp down configuration failed it is not serious enough to
6305 * warrant bailaing out.
6306 */
6307 if (afe_spk_ramp_dn_cfg(port_id) < 0)
6308 pr_err("%s: ramp down configuration failed\n", __func__);
6309
6310 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6311 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6312 stop.hdr.pkt_size = sizeof(stop);
6313 stop.hdr.src_port = 0;
6314 stop.hdr.dest_port = 0;
6315 stop.hdr.token = index;
6316 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
6317 stop.port_id = q6audio_get_port_id(port_id);
6318 stop.reserved = 0;
6319
6320 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
6321 if (ret)
6322 pr_err("%s: AFE close failed %d\n", __func__, ret);
6323
6324fail_cmd:
6325 return ret;
6326}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306327EXPORT_SYMBOL(afe_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306328
6329int afe_set_digital_codec_core_clock(u16 port_id,
6330 struct afe_digital_clk_cfg *cfg)
6331{
6332 struct afe_lpass_digital_clk_config_command clk_cfg;
6333 int index = 0;
6334 int ret = 0;
6335
6336 if (!cfg) {
6337 pr_err("%s: clock cfg is NULL\n", __func__);
6338 ret = -EINVAL;
6339 return ret;
6340 }
6341
6342 ret = afe_q6_interface_prepare();
6343 if (ret != 0) {
6344 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6345 return ret;
6346 }
6347
6348 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6349 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6350 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6351 clk_cfg.hdr.src_port = 0;
6352 clk_cfg.hdr.dest_port = 0;
6353 clk_cfg.hdr.token = index;
6354
6355 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6356 /*default rx port is taken to enable the codec digital clock*/
6357 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6358 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6359 - sizeof(clk_cfg.param);
6360 clk_cfg.param.payload_address_lsw = 0x00;
6361 clk_cfg.param.payload_address_msw = 0x00;
6362 clk_cfg.param.mem_map_handle = 0x00;
6363 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6364 clk_cfg.pdata.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
6365 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6366 clk_cfg.clk_cfg = *cfg;
6367
6368 pr_debug("%s: Minor version =0x%x clk val = %d\n"
6369 "clk root = 0x%x resrv = 0x%x\n",
6370 __func__, cfg->i2s_cfg_minor_version,
6371 cfg->clk_val, cfg->clk_root, cfg->reserved);
6372
6373 atomic_set(&this_afe.state, 1);
6374 atomic_set(&this_afe.status, 0);
6375 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6376 if (ret < 0) {
6377 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6378 __func__, port_id, ret);
6379 ret = -EINVAL;
6380 goto fail_cmd;
6381 }
6382
6383 ret = wait_event_timeout(this_afe.wait[index],
6384 (atomic_read(&this_afe.state) == 0),
6385 msecs_to_jiffies(TIMEOUT_MS));
6386 if (!ret) {
6387 pr_err("%s: wait_event timeout\n", __func__);
6388 ret = -EINVAL;
6389 goto fail_cmd;
6390 }
6391 if (atomic_read(&this_afe.status) > 0) {
6392 pr_err("%s: config cmd failed [%s]\n",
6393 __func__, adsp_err_get_err_str(
6394 atomic_read(&this_afe.status)));
6395 ret = adsp_err_get_lnx_err_code(
6396 atomic_read(&this_afe.status));
6397 goto fail_cmd;
6398 }
6399
6400fail_cmd:
6401 return ret;
6402}
6403
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306404/**
6405 * afe_set_lpass_clock - Enable AFE lpass clock
6406 *
6407 * @port_id: AFE port id
6408 * @cfg: pointer to clk set struct
6409 *
6410 * Returns 0 on success, appropriate error code otherwise
6411 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306412int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg)
6413{
6414 struct afe_lpass_clk_config_command clk_cfg;
6415 int index = 0;
6416 int ret = 0;
6417
6418 if (!cfg) {
6419 pr_err("%s: clock cfg is NULL\n", __func__);
6420 ret = -EINVAL;
6421 return ret;
6422 }
6423 index = q6audio_get_port_index(port_id);
6424 if (index < 0 || index >= AFE_MAX_PORTS) {
6425 pr_err("%s: AFE port index[%d] invalid!\n",
6426 __func__, index);
6427 return -EINVAL;
6428 }
6429 ret = q6audio_is_digital_pcm_interface(port_id);
6430 if (ret < 0) {
6431 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6432 __func__, ret);
6433 return -EINVAL;
6434 }
6435
6436 ret = afe_q6_interface_prepare();
6437 if (ret != 0) {
6438 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6439 return ret;
6440 }
6441
6442 mutex_lock(&this_afe.afe_cmd_lock);
6443 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6444 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6445 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6446 clk_cfg.hdr.src_port = 0;
6447 clk_cfg.hdr.dest_port = 0;
6448 clk_cfg.hdr.token = index;
6449
6450 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6451 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6452 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6453 - sizeof(clk_cfg.param);
6454 clk_cfg.param.payload_address_lsw = 0x00;
6455 clk_cfg.param.payload_address_msw = 0x00;
6456 clk_cfg.param.mem_map_handle = 0x00;
6457 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6458 clk_cfg.pdata.param_id = AFE_PARAM_ID_LPAIF_CLK_CONFIG;
6459 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6460 clk_cfg.clk_cfg = *cfg;
6461
6462 pr_debug("%s: Minor version =0x%x clk val1 = %d\n"
6463 "clk val2 = %d, clk src = 0x%x\n"
6464 "clk root = 0x%x clk mode = 0x%x resrv = 0x%x\n"
6465 "port id = 0x%x\n",
6466 __func__, cfg->i2s_cfg_minor_version,
6467 cfg->clk_val1, cfg->clk_val2, cfg->clk_src,
6468 cfg->clk_root, cfg->clk_set_mode,
6469 cfg->reserved, q6audio_get_port_id(port_id));
6470
6471 atomic_set(&this_afe.state, 1);
6472 atomic_set(&this_afe.status, 0);
6473 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6474 if (ret < 0) {
6475 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6476 __func__, port_id, ret);
6477 ret = -EINVAL;
6478 goto fail_cmd;
6479 }
6480
6481 ret = wait_event_timeout(this_afe.wait[index],
6482 (atomic_read(&this_afe.state) == 0),
6483 msecs_to_jiffies(TIMEOUT_MS));
6484 if (!ret) {
6485 pr_err("%s: wait_event timeout\n", __func__);
6486 ret = -EINVAL;
6487 goto fail_cmd;
6488 }
6489 if (atomic_read(&this_afe.status) > 0) {
6490 pr_err("%s: config cmd failed [%s]\n",
6491 __func__, adsp_err_get_err_str(
6492 atomic_read(&this_afe.status)));
6493 ret = adsp_err_get_lnx_err_code(
6494 atomic_read(&this_afe.status));
6495 goto fail_cmd;
6496 }
6497
6498fail_cmd:
6499 mutex_unlock(&this_afe.afe_cmd_lock);
6500 return ret;
6501}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306502EXPORT_SYMBOL(afe_set_lpass_clock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306503
6504/**
6505 * afe_set_lpass_clk_cfg - Set AFE clk config
6506 *
6507 * @index: port index
6508 * @cfg: pointer to clk set struct
6509 *
6510 * Returns 0 on success, appropriate error code otherwise
6511 */
6512int afe_set_lpass_clk_cfg(int index, struct afe_clk_set *cfg)
6513{
6514 struct afe_lpass_clk_config_command_v2 clk_cfg;
6515 int ret = 0;
6516
6517 if (!cfg) {
6518 pr_err("%s: clock cfg is NULL\n", __func__);
6519 ret = -EINVAL;
6520 return ret;
6521 }
6522
6523 if (index < 0 || index >= AFE_MAX_PORTS) {
6524 pr_err("%s: index[%d] invalid!\n", __func__, index);
6525 return -EINVAL;
6526 }
6527
6528 ret = afe_q6_interface_prepare();
6529 if (ret != 0) {
6530 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6531 return ret;
6532 }
6533
6534 mutex_lock(&this_afe.afe_cmd_lock);
6535 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6536 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6537 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6538 clk_cfg.hdr.src_port = 0;
6539 clk_cfg.hdr.dest_port = 0;
6540 clk_cfg.hdr.token = index;
6541
6542 clk_cfg.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
6543 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6544 - sizeof(clk_cfg.param);
6545 clk_cfg.param.payload_address_lsw = 0x00;
6546 clk_cfg.param.payload_address_msw = 0x00;
6547 clk_cfg.param.mem_map_handle = 0x00;
6548 clk_cfg.pdata.module_id = AFE_MODULE_CLOCK_SET;
6549 clk_cfg.pdata.param_id = AFE_PARAM_ID_CLOCK_SET;
6550 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6551 clk_cfg.clk_cfg = *cfg;
6552
6553
6554 pr_debug("%s: Minor version =0x%x clk id = %d\n"
6555 "clk freq (Hz) = %d, clk attri = 0x%x\n"
6556 "clk root = 0x%x clk enable = 0x%x\n",
6557 __func__, cfg->clk_set_minor_version,
6558 cfg->clk_id, cfg->clk_freq_in_hz, cfg->clk_attri,
6559 cfg->clk_root, cfg->enable);
6560
6561 atomic_set(&this_afe.state, 1);
6562 atomic_set(&this_afe.status, 0);
6563 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6564 if (ret < 0) {
6565 pr_err("%s: AFE clk cfg failed with ret %d\n",
6566 __func__, ret);
6567 ret = -EINVAL;
6568 goto fail_cmd;
6569 }
6570
6571 ret = wait_event_timeout(this_afe.wait[index],
6572 (atomic_read(&this_afe.state) == 0),
6573 msecs_to_jiffies(TIMEOUT_MS));
6574 if (!ret) {
6575 pr_err("%s: wait_event timeout\n", __func__);
6576 ret = -EINVAL;
6577 goto fail_cmd;
6578 } else {
6579 /* set ret to 0 as no timeout happened */
6580 ret = 0;
6581 }
6582 if (atomic_read(&this_afe.status) != 0) {
6583 pr_err("%s: config cmd failed\n", __func__);
6584 ret = -EINVAL;
6585 goto fail_cmd;
6586 }
6587
6588fail_cmd:
6589 mutex_unlock(&this_afe.afe_cmd_lock);
6590 return ret;
6591}
6592EXPORT_SYMBOL(afe_set_lpass_clk_cfg);
6593
6594/**
6595 * afe_set_lpass_clock_v2 - Enable AFE lpass clock
6596 *
6597 * @port_id: AFE port id
6598 * @cfg: pointer to clk set struct
6599 *
6600 * Returns 0 on success, appropriate error code otherwise
6601 */
6602int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
6603{
6604 int index = 0;
6605 int ret = 0;
6606
6607 index = q6audio_get_port_index(port_id);
6608 if (index < 0 || index >= AFE_MAX_PORTS) {
6609 pr_err("%s: AFE port index[%d] invalid!\n",
6610 __func__, index);
6611 return -EINVAL;
6612 }
6613 ret = q6audio_is_digital_pcm_interface(port_id);
6614 if (ret < 0) {
6615 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6616 __func__, ret);
6617 return -EINVAL;
6618 }
6619
6620 ret = afe_set_lpass_clk_cfg(index, cfg);
6621 if (ret)
6622 pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
6623 __func__, ret);
6624
6625 return ret;
6626}
6627EXPORT_SYMBOL(afe_set_lpass_clock_v2);
6628
Raja Mallike1b2f792018-06-01 13:17:36 +05306629static int afe_get_service_ver(void)
6630{
6631 int ret = 0;
6632 size_t ver_size;
6633 struct avcs_fwk_ver_info *ver_info = NULL;
6634
6635 ver_size = sizeof(struct avcs_get_fwk_version) +
6636 sizeof(struct avs_svc_api_info);
6637 ver_info = kzalloc(ver_size, GFP_KERNEL);
6638 if (ver_info == NULL)
6639 return -ENOMEM;
6640
6641 ret = q6core_get_service_version(AVCS_SERVICE_ID_AFE, ver_info, ver_size);
6642 if (ret)
6643 pr_err("%s: q6core_get_service_version failed %d\n",
6644 __func__, ret);
6645
6646 return ret;
6647}
6648
6649enum lpass_clk_ver afe_get_lpass_clk_ver(void)
6650{
6651 enum lpass_clk_ver lpass_clk_ver;
6652
6653 /*
6654 * Use different APIs to set the LPASS clock depending on the AFE
6655 * version. On success afe_get_service_ver returns 0 signyfing the
6656 * latest AFE version is supported. Use LPASS clock version 2 if the
6657 * latest AFE version is supported, otherwise use LPASS clock version 1.
6658 */
6659 lpass_clk_ver = (afe_get_service_ver() == 0) ?
6660 LPASS_CLK_VER_2 : LPASS_CLK_VER_1;
6661
6662 pr_debug("%s: returning %s\n", __func__,
6663 (lpass_clk_ver == LPASS_CLK_VER_2) ?
6664 "LPASS_CLK_VER_2" : "LPASS_CLK_VER_1");
6665
6666 return lpass_clk_ver;
6667}
6668EXPORT_SYMBOL(afe_get_lpass_clk_ver);
6669
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306670int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
6671 struct afe_digital_clk_cfg *cfg)
6672{
6673 struct afe_lpass_digital_clk_config_command clk_cfg;
6674 int index = 0;
6675 int ret = 0;
6676
6677 if (!cfg) {
6678 pr_err("%s: clock cfg is NULL\n", __func__);
6679 ret = -EINVAL;
6680 return ret;
6681 }
6682 index = q6audio_get_port_index(port_id);
6683 if (index < 0 || index >= AFE_MAX_PORTS) {
6684 pr_err("%s: AFE port index[%d] invalid!\n",
6685 __func__, index);
6686 return -EINVAL;
6687 }
6688 ret = q6audio_is_digital_pcm_interface(port_id);
6689 if (ret < 0) {
6690 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6691 __func__, ret);
6692 return -EINVAL;
6693 }
6694
6695 ret = afe_q6_interface_prepare();
6696 if (ret != 0) {
6697 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6698 return ret;
6699 }
6700
6701 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6702 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6703 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6704 clk_cfg.hdr.src_port = 0;
6705 clk_cfg.hdr.dest_port = 0;
6706 clk_cfg.hdr.token = index;
6707
6708 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6709 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6710 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6711 - sizeof(clk_cfg.param);
6712 clk_cfg.param.payload_address_lsw = 0x00;
6713 clk_cfg.param.payload_address_msw = 0x00;
6714 clk_cfg.param.mem_map_handle = 0x00;
6715 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6716 clk_cfg.pdata.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
6717 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6718 clk_cfg.clk_cfg = *cfg;
6719
6720 pr_debug("%s: Minor version =0x%x clk val = %d\n"
6721 "clk root = 0x%x resrv = 0x%x port id = 0x%x\n",
6722 __func__, cfg->i2s_cfg_minor_version,
6723 cfg->clk_val, cfg->clk_root, cfg->reserved,
6724 q6audio_get_port_id(port_id));
6725
6726 atomic_set(&this_afe.state, 1);
6727 atomic_set(&this_afe.status, 0);
6728 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6729 if (ret < 0) {
6730 pr_err("%s: AFE enable for port 0x0x%x ret %d\n",
6731 __func__, port_id, ret);
6732 ret = -EINVAL;
6733 goto fail_cmd;
6734 }
6735
6736 ret = wait_event_timeout(this_afe.wait[index],
6737 (atomic_read(&this_afe.state) == 0),
6738 msecs_to_jiffies(TIMEOUT_MS));
6739 if (!ret) {
6740 pr_err("%s: wait_event timeout\n", __func__);
6741 ret = -EINVAL;
6742 goto fail_cmd;
6743 }
6744 if (atomic_read(&this_afe.status) > 0) {
6745 pr_err("%s: config cmd failed [%s]\n",
6746 __func__, adsp_err_get_err_str(
6747 atomic_read(&this_afe.status)));
6748 ret = adsp_err_get_lnx_err_code(
6749 atomic_read(&this_afe.status));
6750 goto fail_cmd;
6751 }
6752
6753fail_cmd:
6754 return ret;
6755}
6756
6757int afe_enable_lpass_core_shared_clock(u16 port_id, u32 enable)
6758{
6759 struct afe_lpass_core_shared_clk_config_command clk_cfg;
6760 int index = 0;
6761 int ret = 0;
6762
6763 index = q6audio_get_port_index(port_id);
6764 if (index < 0 || index >= AFE_MAX_PORTS) {
6765 pr_err("%s: AFE port index[%d] invalid!\n",
6766 __func__, index);
6767 return -EINVAL;
6768 }
6769 ret = q6audio_is_digital_pcm_interface(port_id);
6770 if (ret < 0) {
6771 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6772 __func__, ret);
6773 return -EINVAL;
6774 }
6775
6776 ret = afe_q6_interface_prepare();
6777 if (ret != 0) {
6778 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6779 return ret;
6780 }
6781
6782 mutex_lock(&this_afe.afe_cmd_lock);
6783 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6784 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6785 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6786 clk_cfg.hdr.src_port = 0;
6787 clk_cfg.hdr.dest_port = 0;
6788 clk_cfg.hdr.token = index;
6789
6790 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6791 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6792 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6793 - sizeof(clk_cfg.param);
6794 clk_cfg.param.payload_address_lsw = 0x00;
6795 clk_cfg.param.payload_address_msw = 0x00;
6796 clk_cfg.param.mem_map_handle = 0x00;
6797 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6798 clk_cfg.pdata.param_id = AFE_PARAM_ID_LPASS_CORE_SHARED_CLOCK_CONFIG;
6799 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6800 clk_cfg.clk_cfg.lpass_core_shared_clk_cfg_minor_version =
6801 AFE_API_VERSION_LPASS_CORE_SHARED_CLK_CONFIG;
6802 clk_cfg.clk_cfg.enable = enable;
6803
6804 pr_debug("%s: port id = %d, enable = %d\n",
6805 __func__, q6audio_get_port_id(port_id), enable);
6806
6807 atomic_set(&this_afe.state, 1);
6808 atomic_set(&this_afe.status, 0);
6809 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6810 if (ret < 0) {
6811 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6812 __func__, port_id, ret);
6813 ret = -EINVAL;
6814 goto fail_cmd;
6815 }
6816
6817 ret = wait_event_timeout(this_afe.wait[index],
6818 (atomic_read(&this_afe.state) == 0),
6819 msecs_to_jiffies(TIMEOUT_MS));
6820 if (!ret) {
6821 pr_err("%s: wait_event timeout\n", __func__);
6822 ret = -EINVAL;
6823 goto fail_cmd;
6824 }
6825 if (atomic_read(&this_afe.status) > 0) {
6826 pr_err("%s: config cmd failed [%s]\n",
6827 __func__, adsp_err_get_err_str(
6828 atomic_read(&this_afe.status)));
6829 ret = adsp_err_get_lnx_err_code(
6830 atomic_read(&this_afe.status));
6831 goto fail_cmd;
6832 }
6833
6834fail_cmd:
6835 mutex_unlock(&this_afe.afe_cmd_lock);
6836 return ret;
6837}
6838
6839int q6afe_check_osr_clk_freq(u32 freq)
6840{
6841 int ret = 0;
6842
6843 switch (freq) {
6844 case Q6AFE_LPASS_OSR_CLK_12_P288_MHZ:
Karthikeyan Mani7190b892017-12-10 23:50:37 -08006845 case Q6AFE_LPASS_OSR_CLK_9_P600_MHZ:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306846 case Q6AFE_LPASS_OSR_CLK_8_P192_MHZ:
6847 case Q6AFE_LPASS_OSR_CLK_6_P144_MHZ:
6848 case Q6AFE_LPASS_OSR_CLK_4_P096_MHZ:
6849 case Q6AFE_LPASS_OSR_CLK_3_P072_MHZ:
6850 case Q6AFE_LPASS_OSR_CLK_2_P048_MHZ:
6851 case Q6AFE_LPASS_OSR_CLK_1_P536_MHZ:
6852 case Q6AFE_LPASS_OSR_CLK_1_P024_MHZ:
6853 case Q6AFE_LPASS_OSR_CLK_768_kHZ:
6854 case Q6AFE_LPASS_OSR_CLK_512_kHZ:
6855 break;
6856 default:
6857 pr_err("%s: deafault freq 0x%x\n",
6858 __func__, freq);
6859 ret = -EINVAL;
6860 }
6861 return ret;
6862}
6863
6864int afe_get_sp_th_vi_ftm_data(struct afe_sp_th_vi_get_param *th_vi)
6865{
6866 int ret = -EINVAL;
6867 int index = 0, port = SLIMBUS_4_TX;
6868
6869 if (!th_vi) {
6870 pr_err("%s: Invalid params\n", __func__);
6871 goto done;
6872 }
6873 if (this_afe.vi_tx_port != -1)
6874 port = this_afe.vi_tx_port;
6875
6876 ret = q6audio_validate_port(port);
6877 if (ret < 0) {
6878 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6879 goto done;
6880 }
6881 index = q6audio_get_port_index(port);
6882 if (index < 0) {
6883 pr_err("%s: invalid port 0x%x, index %d\n",
6884 __func__, port, index);
6885 ret = -EINVAL;
6886 goto done;
6887 }
6888 th_vi->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6889 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6890 th_vi->hdr.pkt_size = sizeof(*th_vi);
6891 th_vi->hdr.src_port = 0;
6892 th_vi->hdr.dest_port = 0;
6893 th_vi->hdr.token = index;
6894 th_vi->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6895 th_vi->get_param.mem_map_handle = 0;
6896 th_vi->get_param.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
6897 th_vi->get_param.param_id = AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS;
6898 th_vi->get_param.payload_address_lsw = 0;
6899 th_vi->get_param.payload_address_msw = 0;
6900 th_vi->get_param.payload_size = sizeof(*th_vi)
6901 - sizeof(th_vi->get_param) - sizeof(th_vi->hdr);
6902 th_vi->get_param.port_id = q6audio_get_port_id(port);
6903 th_vi->pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
6904 th_vi->pdata.param_id = AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS;
6905 th_vi->pdata.param_size = sizeof(th_vi->param);
6906 atomic_set(&this_afe.status, 0);
6907 atomic_set(&this_afe.state, 1);
6908 ret = apr_send_pkt(this_afe.apr, (uint32_t *)th_vi);
6909 if (ret < 0) {
6910 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
6911 __func__, port, th_vi->get_param.param_id, ret);
6912 goto done;
6913 }
6914 ret = wait_event_timeout(this_afe.wait[index],
6915 (atomic_read(&this_afe.state) == 0),
6916 msecs_to_jiffies(TIMEOUT_MS));
6917 if (!ret) {
6918 pr_err("%s: wait_event timeout\n", __func__);
6919 ret = -EINVAL;
6920 goto done;
6921 }
6922 if (atomic_read(&this_afe.status) > 0) {
6923 pr_err("%s: config cmd failed [%s]\n",
6924 __func__, adsp_err_get_err_str(
6925 atomic_read(&this_afe.status)));
6926 ret = adsp_err_get_lnx_err_code(atomic_read(&this_afe.status));
6927 goto done;
6928 }
6929 memcpy(&th_vi->param, &this_afe.th_vi_resp.param,
6930 sizeof(this_afe.th_vi_resp.param));
6931 pr_debug("%s: DC resistance %d %d temp %d %d status %d %d\n",
6932 __func__, th_vi->param.dc_res_q24[SP_V2_SPKR_1],
6933 th_vi->param.dc_res_q24[SP_V2_SPKR_2],
6934 th_vi->param.temp_q22[SP_V2_SPKR_1],
6935 th_vi->param.temp_q22[SP_V2_SPKR_2],
6936 th_vi->param.status[SP_V2_SPKR_1],
6937 th_vi->param.status[SP_V2_SPKR_2]);
6938 ret = 0;
6939done:
6940 return ret;
6941}
6942
6943int afe_get_sp_ex_vi_ftm_data(struct afe_sp_ex_vi_get_param *ex_vi)
6944{
6945 int ret = -EINVAL;
6946 int index = 0, port = SLIMBUS_4_TX;
6947
6948 if (!ex_vi) {
6949 pr_err("%s: Invalid params\n", __func__);
6950 goto done;
6951 }
6952 if (this_afe.vi_tx_port != -1)
6953 port = this_afe.vi_tx_port;
6954
6955 ret = q6audio_validate_port(port);
6956 if (ret < 0) {
6957 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6958 goto done;
6959 }
6960
6961 index = q6audio_get_port_index(port);
6962 if (index < 0) {
6963 pr_err("%s: invalid index %d port 0x%x\n", __func__,
6964 index, port);
6965 ret = -EINVAL;
6966 goto done;
6967 }
6968
6969 ex_vi->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6970 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6971 ex_vi->hdr.pkt_size = sizeof(*ex_vi);
6972 ex_vi->hdr.src_port = 0;
6973 ex_vi->hdr.dest_port = 0;
6974 ex_vi->hdr.token = index;
6975 ex_vi->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6976 ex_vi->get_param.mem_map_handle = 0;
6977 ex_vi->get_param.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
6978 ex_vi->get_param.param_id = AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS;
6979 ex_vi->get_param.payload_address_lsw = 0;
6980 ex_vi->get_param.payload_address_msw = 0;
6981 ex_vi->get_param.payload_size = sizeof(*ex_vi)
6982 - sizeof(ex_vi->get_param) - sizeof(ex_vi->hdr);
6983 ex_vi->get_param.port_id = q6audio_get_port_id(port);
6984 ex_vi->pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
6985 ex_vi->pdata.param_id = AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS;
6986 ex_vi->pdata.param_size = sizeof(ex_vi->param);
6987 atomic_set(&this_afe.status, 0);
6988 atomic_set(&this_afe.state, 1);
6989 ret = apr_send_pkt(this_afe.apr, (uint32_t *)ex_vi);
6990 if (ret < 0) {
6991 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
6992 __func__, port, ex_vi->get_param.param_id, ret);
6993 goto done;
6994 }
6995 ret = wait_event_timeout(this_afe.wait[index],
6996 (atomic_read(&this_afe.state) == 0),
6997 msecs_to_jiffies(TIMEOUT_MS));
6998 if (!ret) {
6999 pr_err("%s: wait_event timeout\n", __func__);
7000 ret = -EINVAL;
7001 goto done;
7002 }
7003 if (atomic_read(&this_afe.status) > 0) {
7004 pr_err("%s: config cmd failed [%s]\n",
7005 __func__, adsp_err_get_err_str(
7006 atomic_read(&this_afe.status)));
7007 ret = adsp_err_get_lnx_err_code(atomic_read(&this_afe.status));
7008 goto done;
7009 }
7010 memcpy(&ex_vi->param, &this_afe.ex_vi_resp.param,
7011 sizeof(this_afe.ex_vi_resp.param));
7012 pr_debug("%s: freq %d %d resistance %d %d qfactor %d %d state %d %d\n",
7013 __func__, ex_vi->param.freq_q20[SP_V2_SPKR_1],
7014 ex_vi->param.freq_q20[SP_V2_SPKR_2],
7015 ex_vi->param.resis_q24[SP_V2_SPKR_1],
7016 ex_vi->param.resis_q24[SP_V2_SPKR_2],
7017 ex_vi->param.qmct_q24[SP_V2_SPKR_1],
7018 ex_vi->param.qmct_q24[SP_V2_SPKR_2],
7019 ex_vi->param.status[SP_V2_SPKR_1],
7020 ex_vi->param.status[SP_V2_SPKR_2]);
7021 ret = 0;
7022done:
7023 return ret;
7024}
7025
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307026/**
7027 * afe_get_av_dev_drift -
7028 * command to retrieve AV drift
7029 *
7030 * @timing_stats: timing stats to be updated with AV drift values
7031 * @port: AFE port ID
7032 *
7033 * Returns 0 on success or error on failure
7034 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307035int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
7036 u16 port)
7037{
7038 int ret = -EINVAL;
7039 int index = 0;
7040 struct afe_av_dev_drift_get_param av_dev_drift;
7041
7042 if (!timing_stats) {
7043 pr_err("%s: Invalid params\n", __func__);
7044 goto exit;
7045 }
7046
7047 ret = q6audio_validate_port(port);
7048 if (ret < 0) {
7049 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
7050 ret = -EINVAL;
7051 goto exit;
7052 }
7053
7054 index = q6audio_get_port_index(port);
7055 if (index < 0 || index >= AFE_MAX_PORTS) {
7056 pr_err("%s: Invalid AFE port index[%d]\n",
7057 __func__, index);
7058 ret = -EINVAL;
7059 goto exit;
7060 }
7061
7062 memset(&av_dev_drift, 0, sizeof(struct afe_av_dev_drift_get_param));
7063
7064 av_dev_drift.hdr.hdr_field =
7065 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7066 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
7067 av_dev_drift.hdr.pkt_size = sizeof(av_dev_drift);
7068 av_dev_drift.hdr.src_port = 0;
7069 av_dev_drift.hdr.dest_port = 0;
7070 av_dev_drift.hdr.token = index;
7071 av_dev_drift.hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
7072 av_dev_drift.get_param.mem_map_handle = 0;
7073 av_dev_drift.get_param.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
7074 av_dev_drift.get_param.param_id = AFE_PARAM_ID_DEV_TIMING_STATS;
7075 av_dev_drift.get_param.payload_address_lsw = 0;
7076 av_dev_drift.get_param.payload_address_msw = 0;
7077 av_dev_drift.get_param.payload_size = sizeof(av_dev_drift)
7078 - sizeof(av_dev_drift.get_param) - sizeof(av_dev_drift.hdr);
7079 av_dev_drift.get_param.port_id = q6audio_get_port_id(port);
7080 av_dev_drift.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
7081 av_dev_drift.pdata.param_id = AFE_PARAM_ID_DEV_TIMING_STATS;
7082 av_dev_drift.pdata.param_size = sizeof(av_dev_drift.timing_stats);
7083 atomic_set(&this_afe.status, 0);
7084 atomic_set(&this_afe.state, 1);
7085 ret = apr_send_pkt(this_afe.apr, (uint32_t *)&av_dev_drift);
7086 if (ret < 0) {
7087 pr_err("%s: get param port 0x%x param id[0x%x] failed %d\n",
7088 __func__, port, av_dev_drift.get_param.param_id, ret);
7089 goto exit;
7090 }
7091
7092 ret = wait_event_timeout(this_afe.wait[index],
7093 (atomic_read(&this_afe.state) == 0),
7094 msecs_to_jiffies(TIMEOUT_MS));
7095 if (!ret) {
7096 pr_err("%s: wait_event timeout\n", __func__);
7097 ret = -EINVAL;
7098 goto exit;
7099 }
7100
7101 if (atomic_read(&this_afe.status) > 0) {
7102 pr_err("%s: config cmd failed [%s]\n",
7103 __func__, adsp_err_get_err_str(
7104 atomic_read(&this_afe.status)));
7105 ret = adsp_err_get_lnx_err_code(
7106 atomic_read(&this_afe.status));
7107 goto exit;
7108 }
7109
7110 memcpy(timing_stats, &this_afe.av_dev_drift_resp.timing_stats,
7111 sizeof(this_afe.av_dev_drift_resp.timing_stats));
7112 ret = 0;
7113exit:
7114 return ret;
7115}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307116EXPORT_SYMBOL(afe_get_av_dev_drift);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307117
7118int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp)
7119{
7120 int ret = -EINVAL;
7121 int index = 0, port = SLIMBUS_4_TX;
7122
7123 if (!calib_resp) {
7124 pr_err("%s: Invalid params\n", __func__);
7125 goto fail_cmd;
7126 }
7127 if (this_afe.vi_tx_port != -1)
7128 port = this_afe.vi_tx_port;
7129
7130 ret = q6audio_validate_port(port);
7131 if (ret < 0) {
7132 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
7133 ret = -EINVAL;
7134 goto fail_cmd;
7135 }
7136 index = q6audio_get_port_index(port);
7137 if (index < 0 || index >= AFE_MAX_PORTS) {
7138 pr_err("%s: AFE port index[%d] invalid!\n",
7139 __func__, index);
7140 ret = -EINVAL;
7141 goto fail_cmd;
7142 }
7143 calib_resp->hdr.hdr_field =
7144 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7145 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
7146 calib_resp->hdr.pkt_size = sizeof(*calib_resp);
7147 calib_resp->hdr.src_port = 0;
7148 calib_resp->hdr.dest_port = 0;
7149 calib_resp->hdr.token = index;
7150 calib_resp->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
7151 calib_resp->get_param.mem_map_handle = 0;
7152 calib_resp->get_param.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
7153 calib_resp->get_param.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2;
7154 calib_resp->get_param.payload_address_lsw = 0;
7155 calib_resp->get_param.payload_address_msw = 0;
7156 calib_resp->get_param.payload_size = sizeof(*calib_resp)
7157 - sizeof(calib_resp->get_param) - sizeof(calib_resp->hdr);
7158 calib_resp->get_param.port_id = q6audio_get_port_id(port);
7159 calib_resp->pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
7160 calib_resp->pdata.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2;
7161 calib_resp->pdata.param_size = sizeof(calib_resp->res_cfg);
7162 atomic_set(&this_afe.status, 0);
7163 atomic_set(&this_afe.state, 1);
7164 ret = apr_send_pkt(this_afe.apr, (uint32_t *)calib_resp);
7165 if (ret < 0) {
7166 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
7167 __func__, port, calib_resp->get_param.param_id, ret);
7168 goto fail_cmd;
7169 }
7170 ret = wait_event_timeout(this_afe.wait[index],
7171 (atomic_read(&this_afe.state) == 0),
7172 msecs_to_jiffies(TIMEOUT_MS));
7173 if (!ret) {
7174 pr_err("%s: wait_event timeout\n", __func__);
7175 ret = -EINVAL;
7176 goto fail_cmd;
7177 }
7178 if (atomic_read(&this_afe.status) > 0) {
7179 pr_err("%s: config cmd failed [%s]\n",
7180 __func__, adsp_err_get_err_str(
7181 atomic_read(&this_afe.status)));
7182 ret = adsp_err_get_lnx_err_code(
7183 atomic_read(&this_afe.status));
7184 goto fail_cmd;
7185 }
7186 memcpy(&calib_resp->res_cfg, &this_afe.calib_data.res_cfg,
7187 sizeof(this_afe.calib_data.res_cfg));
7188 pr_info("%s: state %s resistance %d %d\n", __func__,
7189 fbsp_state[calib_resp->res_cfg.th_vi_ca_state],
7190 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1],
7191 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]);
7192 ret = 0;
7193fail_cmd:
7194 return ret;
7195}
7196
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307197/**
7198 * afe_spk_prot_feed_back_cfg -
7199 * command to setup spk protection feedback config
7200 *
7201 * @src_port: source port id
7202 * @dst_port: destination port id
7203 * @l_ch: left speaker active or not
7204 * @r_ch: right speaker active or not
7205 * @enable: flag to enable or disable
7206 *
7207 * Returns 0 on success or error on failure
7208 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307209int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
7210 int l_ch, int r_ch, u32 enable)
7211{
7212 int ret = -EINVAL;
7213 union afe_spkr_prot_config prot_config;
7214 int index = 0;
7215
7216 if (!enable) {
7217 pr_debug("%s: Disable Feedback tx path", __func__);
7218 this_afe.vi_tx_port = -1;
7219 this_afe.vi_rx_port = -1;
7220 return 0;
7221 }
7222
7223 if ((q6audio_validate_port(src_port) < 0) ||
7224 (q6audio_validate_port(dst_port) < 0)) {
7225 pr_err("%s: invalid ports src 0x%x dst 0x%x",
7226 __func__, src_port, dst_port);
7227 goto fail_cmd;
7228 }
7229 if (!l_ch && !r_ch) {
7230 pr_err("%s: error ch values zero\n", __func__);
7231 goto fail_cmd;
7232 }
7233 pr_debug("%s: src_port 0x%x dst_port 0x%x l_ch %d r_ch %d\n",
7234 __func__, src_port, dst_port, l_ch, r_ch);
7235 memset(&prot_config, 0, sizeof(prot_config));
7236 prot_config.feedback_path_cfg.dst_portid =
7237 q6audio_get_port_id(dst_port);
7238 if (l_ch) {
7239 prot_config.feedback_path_cfg.chan_info[index++] = 1;
7240 prot_config.feedback_path_cfg.chan_info[index++] = 2;
7241 }
7242 if (r_ch) {
7243 prot_config.feedback_path_cfg.chan_info[index++] = 3;
7244 prot_config.feedback_path_cfg.chan_info[index++] = 4;
7245 }
7246 prot_config.feedback_path_cfg.num_channels = index;
7247 pr_debug("%s no of channels: %d\n", __func__, index);
7248 prot_config.feedback_path_cfg.minor_version = 1;
7249 ret = afe_spk_prot_prepare(src_port, dst_port,
7250 AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config);
7251fail_cmd:
7252 return ret;
7253}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307254EXPORT_SYMBOL(afe_spk_prot_feed_back_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307255
7256static int get_cal_type_index(int32_t cal_type)
7257{
7258 int ret = -EINVAL;
7259
7260 switch (cal_type) {
7261 case AFE_COMMON_RX_CAL_TYPE:
7262 ret = AFE_COMMON_RX_CAL;
7263 break;
7264 case AFE_COMMON_TX_CAL_TYPE:
7265 ret = AFE_COMMON_TX_CAL;
7266 break;
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307267 case AFE_LSM_TX_CAL_TYPE:
7268 ret = AFE_LSM_TX_CAL;
7269 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307270 case AFE_AANC_CAL_TYPE:
7271 ret = AFE_AANC_CAL;
7272 break;
7273 case AFE_HW_DELAY_CAL_TYPE:
7274 ret = AFE_HW_DELAY_CAL;
7275 break;
7276 case AFE_FB_SPKR_PROT_CAL_TYPE:
7277 ret = AFE_FB_SPKR_PROT_CAL;
7278 break;
7279 case AFE_SIDETONE_CAL_TYPE:
7280 ret = AFE_SIDETONE_CAL;
7281 break;
7282 case AFE_SIDETONE_IIR_CAL_TYPE:
7283 ret = AFE_SIDETONE_IIR_CAL;
7284 break;
7285 case AFE_TOPOLOGY_CAL_TYPE:
7286 ret = AFE_TOPOLOGY_CAL;
7287 break;
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307288 case AFE_LSM_TOPOLOGY_CAL_TYPE:
7289 ret = AFE_LSM_TOPOLOGY_CAL;
7290 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307291 case AFE_CUST_TOPOLOGY_CAL_TYPE:
7292 ret = AFE_CUST_TOPOLOGY_CAL;
7293 break;
7294 default:
7295 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
7296 }
7297 return ret;
7298}
7299
7300int afe_alloc_cal(int32_t cal_type, size_t data_size,
7301 void *data)
7302{
7303 int ret = 0;
7304 int cal_index;
7305
7306 cal_index = get_cal_type_index(cal_type);
7307 pr_debug("%s: cal_type = %d cal_index = %d\n",
7308 __func__, cal_type, cal_index);
7309
7310 if (cal_index < 0) {
7311 pr_err("%s: could not get cal index %d!\n",
7312 __func__, cal_index);
7313 ret = -EINVAL;
7314 goto done;
7315 }
7316
7317 ret = cal_utils_alloc_cal(data_size, data,
7318 this_afe.cal_data[cal_index], 0, NULL);
7319 if (ret < 0) {
7320 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
7321 __func__, ret, cal_type);
7322 ret = -EINVAL;
7323 goto done;
7324 }
7325done:
7326 return ret;
7327}
7328
7329static int afe_dealloc_cal(int32_t cal_type, size_t data_size,
7330 void *data)
7331{
7332 int ret = 0;
7333 int cal_index;
7334
7335 pr_debug("%s:\n", __func__);
7336
7337 cal_index = get_cal_type_index(cal_type);
7338 if (cal_index < 0) {
7339 pr_err("%s: could not get cal index %d!\n",
7340 __func__, cal_index);
7341 ret = -EINVAL;
7342 goto done;
7343 }
7344
7345 ret = cal_utils_dealloc_cal(data_size, data,
7346 this_afe.cal_data[cal_index]);
7347 if (ret < 0) {
7348 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
7349 __func__, ret, cal_type);
7350 ret = -EINVAL;
7351 goto done;
7352 }
7353done:
7354 return ret;
7355}
7356
7357static int afe_set_cal(int32_t cal_type, size_t data_size,
7358 void *data)
7359{
7360 int ret = 0;
7361 int cal_index;
7362
7363 pr_debug("%s:\n", __func__);
7364
7365 cal_index = get_cal_type_index(cal_type);
7366 if (cal_index < 0) {
7367 pr_err("%s: could not get cal index %d!\n",
7368 __func__, cal_index);
7369 ret = -EINVAL;
7370 goto done;
7371 }
7372
7373 ret = cal_utils_set_cal(data_size, data,
7374 this_afe.cal_data[cal_index], 0, NULL);
7375 if (ret < 0) {
7376 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
7377 __func__, ret, cal_type);
7378 ret = -EINVAL;
7379 goto done;
7380 }
7381
7382 if (cal_index == AFE_CUST_TOPOLOGY_CAL) {
7383 mutex_lock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
7384 this_afe.set_custom_topology = 1;
7385 pr_debug("%s:[AFE_CUSTOM_TOPOLOGY] ret = %d, cal type = %d!\n",
7386 __func__, ret, cal_type);
7387 mutex_unlock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
7388 }
7389
7390done:
7391 return ret;
7392}
7393
7394static struct cal_block_data *afe_find_hw_delay_by_path(
7395 struct cal_type_data *cal_type, int path)
7396{
7397 struct list_head *ptr, *next;
7398 struct cal_block_data *cal_block = NULL;
7399
7400 pr_debug("%s:\n", __func__);
7401
7402 list_for_each_safe(ptr, next,
7403 &cal_type->cal_blocks) {
7404
7405 cal_block = list_entry(ptr,
7406 struct cal_block_data, list);
7407
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07007408 if (cal_utils_is_cal_stale(cal_block))
7409 continue;
7410
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307411 if (((struct audio_cal_info_hw_delay *)cal_block->cal_info)
7412 ->path == path) {
7413 return cal_block;
7414 }
7415 }
7416 return NULL;
7417}
7418
7419static int afe_get_cal_hw_delay(int32_t path,
7420 struct audio_cal_hw_delay_entry *entry)
7421{
7422 int ret = 0;
7423 int i;
7424 struct cal_block_data *cal_block = NULL;
7425 struct audio_cal_hw_delay_data *hw_delay_info = NULL;
7426
7427 pr_debug("%s:\n", __func__);
7428
7429 if (this_afe.cal_data[AFE_HW_DELAY_CAL] == NULL) {
7430 pr_err("%s: AFE_HW_DELAY_CAL not initialized\n", __func__);
7431 ret = -EINVAL;
7432 goto done;
7433 }
7434 if (entry == NULL) {
7435 pr_err("%s: entry is NULL\n", __func__);
7436 ret = -EINVAL;
7437 goto done;
7438 }
7439 if ((path >= MAX_PATH_TYPE) || (path < 0)) {
7440 pr_err("%s: bad path: %d\n",
7441 __func__, path);
7442 ret = -EINVAL;
7443 goto done;
7444 }
7445
7446 mutex_lock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
7447 cal_block = afe_find_hw_delay_by_path(
7448 this_afe.cal_data[AFE_HW_DELAY_CAL], path);
7449 if (cal_block == NULL)
7450 goto unlock;
7451
7452 hw_delay_info = &((struct audio_cal_info_hw_delay *)
7453 cal_block->cal_info)->data;
7454 if (hw_delay_info->num_entries > MAX_HW_DELAY_ENTRIES) {
7455 pr_err("%s: invalid num entries: %d\n",
7456 __func__, hw_delay_info->num_entries);
7457 ret = -EINVAL;
7458 goto unlock;
7459 }
7460
7461 for (i = 0; i < hw_delay_info->num_entries; i++) {
7462 if (hw_delay_info->entry[i].sample_rate ==
7463 entry->sample_rate) {
7464 entry->delay_usec = hw_delay_info->entry[i].delay_usec;
7465 break;
7466 }
7467 }
7468 if (i == hw_delay_info->num_entries) {
7469 pr_err("%s: Unable to find delay for sample rate %d\n",
7470 __func__, entry->sample_rate);
7471 ret = -EFAULT;
7472 goto unlock;
7473 }
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07007474
7475 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307476 pr_debug("%s: Path = %d samplerate = %u usec = %u status %d\n",
7477 __func__, path, entry->sample_rate, entry->delay_usec, ret);
7478unlock:
7479 mutex_unlock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
7480done:
7481 return ret;
7482}
7483
7484static int afe_set_cal_sp_th_vi_ftm_cfg(int32_t cal_type, size_t data_size,
7485 void *data)
7486{
7487 int ret = 0;
7488 struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data;
7489
7490 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
7491 cal_data == NULL ||
7492 data_size != sizeof(*cal_data))
7493 goto done;
7494
7495 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7496 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7497 memcpy(&this_afe.th_ftm_cfg, &cal_data->cal_info,
7498 sizeof(this_afe.th_ftm_cfg));
7499 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7500done:
7501 return ret;
7502}
7503
7504static int afe_set_cal_sp_ex_vi_ftm_cfg(int32_t cal_type, size_t data_size,
7505 void *data)
7506{
7507 int ret = 0;
7508 struct audio_cal_type_sp_ex_vi_ftm_cfg *cal_data = data;
7509
7510 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
7511 cal_data == NULL ||
7512 data_size != sizeof(*cal_data))
7513 goto done;
7514
7515 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7516 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7517 memcpy(&this_afe.ex_ftm_cfg, &cal_data->cal_info,
7518 sizeof(this_afe.ex_ftm_cfg));
7519 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7520done:
7521 return ret;
7522}
7523
7524static int afe_set_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
7525 void *data)
7526{
7527 int ret = 0;
7528 struct audio_cal_type_fb_spk_prot_cfg *cal_data = data;
7529
7530 pr_debug("%s:\n", __func__);
7531
7532 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
7533 goto done;
7534 if (cal_data == NULL)
7535 goto done;
7536 if (data_size != sizeof(*cal_data))
7537 goto done;
7538
7539 if (cal_data->cal_info.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
7540 __pm_wakeup_event(&wl.ws, jiffies_to_msecs(WAKELOCK_TIMEOUT));
7541 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7542 memcpy(&this_afe.prot_cfg, &cal_data->cal_info,
7543 sizeof(this_afe.prot_cfg));
7544 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7545done:
7546 return ret;
7547}
7548
7549static int afe_get_cal_sp_th_vi_ftm_param(int32_t cal_type, size_t data_size,
7550 void *data)
7551{
7552 int i, ret = 0;
7553 struct audio_cal_type_sp_th_vi_param *cal_data = data;
7554 struct afe_sp_th_vi_get_param th_vi;
7555
7556 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7557 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
7558 cal_data == NULL ||
7559 data_size != sizeof(*cal_data))
7560 goto done;
7561
7562 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7563 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7564 cal_data->cal_info.status[i] = -EINVAL;
7565 cal_data->cal_info.r_dc_q24[i] = -1;
7566 cal_data->cal_info.temp_q22[i] = -1;
7567 }
7568 if (!afe_get_sp_th_vi_ftm_data(&th_vi)) {
7569 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7570 pr_debug("%s: ftm param status = %d\n",
7571 __func__, th_vi.param.status[i]);
7572 if (th_vi.param.status[i] == FBSP_IN_PROGRESS) {
7573 cal_data->cal_info.status[i] = -EAGAIN;
7574 } else if (th_vi.param.status[i] == FBSP_SUCCESS) {
7575 cal_data->cal_info.status[i] = 0;
7576 cal_data->cal_info.r_dc_q24[i] =
7577 th_vi.param.dc_res_q24[i];
7578 cal_data->cal_info.temp_q22[i] =
7579 th_vi.param.temp_q22[i];
7580 }
7581 }
7582 }
7583 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7584done:
7585 return ret;
7586}
7587
7588static int afe_get_cal_sp_ex_vi_ftm_param(int32_t cal_type, size_t data_size,
7589 void *data)
7590{
7591 int i, ret = 0;
7592 struct audio_cal_type_sp_ex_vi_param *cal_data = data;
7593 struct afe_sp_ex_vi_get_param ex_vi;
7594
7595 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7596 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
7597 cal_data == NULL ||
7598 data_size != sizeof(*cal_data))
7599 goto done;
7600
7601 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7602 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7603 cal_data->cal_info.status[i] = -EINVAL;
7604 cal_data->cal_info.freq_q20[i] = -1;
7605 cal_data->cal_info.resis_q24[i] = -1;
7606 cal_data->cal_info.qmct_q24[i] = -1;
7607 }
7608 if (!afe_get_sp_ex_vi_ftm_data(&ex_vi)) {
7609 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7610 pr_debug("%s: ftm param status = %d\n",
7611 __func__, ex_vi.param.status[i]);
7612 if (ex_vi.param.status[i] == FBSP_IN_PROGRESS) {
7613 cal_data->cal_info.status[i] = -EAGAIN;
7614 } else if (ex_vi.param.status[i] == FBSP_SUCCESS) {
7615 cal_data->cal_info.status[i] = 0;
7616 cal_data->cal_info.freq_q20[i] =
7617 ex_vi.param.freq_q20[i];
7618 cal_data->cal_info.resis_q24[i] =
7619 ex_vi.param.resis_q24[i];
7620 cal_data->cal_info.qmct_q24[i] =
7621 ex_vi.param.qmct_q24[i];
7622 }
7623 }
7624 }
7625 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7626done:
7627 return ret;
7628}
7629
7630static int afe_get_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
7631 void *data)
7632{
7633 int ret = 0;
7634 struct audio_cal_type_fb_spk_prot_status *cal_data = data;
7635 struct afe_spkr_prot_get_vi_calib calib_resp;
7636
7637 pr_debug("%s:\n", __func__);
7638
7639 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
7640 goto done;
7641 if (cal_data == NULL)
7642 goto done;
7643 if (data_size != sizeof(*cal_data))
7644 goto done;
7645
7646 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7647 if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATED) {
7648 cal_data->cal_info.r0[SP_V2_SPKR_1] =
7649 this_afe.prot_cfg.r0[SP_V2_SPKR_1];
7650 cal_data->cal_info.r0[SP_V2_SPKR_2] =
7651 this_afe.prot_cfg.r0[SP_V2_SPKR_2];
7652 cal_data->cal_info.status = 0;
7653 } else if (this_afe.prot_cfg.mode ==
7654 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
7655 /*Call AFE to query the status*/
7656 cal_data->cal_info.status = -EINVAL;
7657 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
7658 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
7659 if (!afe_spk_prot_get_calib_data(&calib_resp)) {
7660 if (calib_resp.res_cfg.th_vi_ca_state ==
7661 FBSP_IN_PROGRESS)
7662 cal_data->cal_info.status = -EAGAIN;
7663 else if (calib_resp.res_cfg.th_vi_ca_state ==
7664 FBSP_SUCCESS) {
7665 cal_data->cal_info.status = 0;
7666 cal_data->cal_info.r0[SP_V2_SPKR_1] =
7667 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_1];
7668 cal_data->cal_info.r0[SP_V2_SPKR_2] =
7669 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_2];
7670 }
7671 }
7672 if (!cal_data->cal_info.status) {
7673 this_afe.prot_cfg.mode =
7674 MSM_SPKR_PROT_CALIBRATED;
7675 this_afe.prot_cfg.r0[SP_V2_SPKR_1] =
7676 cal_data->cal_info.r0[SP_V2_SPKR_1];
7677 this_afe.prot_cfg.r0[SP_V2_SPKR_2] =
7678 cal_data->cal_info.r0[SP_V2_SPKR_2];
7679 }
7680 } else {
7681 /*Indicates calibration data is invalid*/
7682 cal_data->cal_info.status = -EINVAL;
7683 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
7684 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
7685 }
7686 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7687 __pm_relax(&wl.ws);
7688done:
7689 return ret;
7690}
7691
7692static int afe_map_cal_data(int32_t cal_type,
7693 struct cal_block_data *cal_block)
7694{
7695 int ret = 0;
7696 int cal_index;
7697
7698 pr_debug("%s:\n", __func__);
7699
7700 cal_index = get_cal_type_index(cal_type);
7701 if (cal_index < 0) {
7702 pr_err("%s: could not get cal index %d!\n",
7703 __func__, cal_index);
7704 ret = -EINVAL;
7705 goto done;
7706 }
7707
7708
7709 mutex_lock(&this_afe.afe_cmd_lock);
7710 atomic_set(&this_afe.mem_map_cal_index, cal_index);
7711 ret = afe_cmd_memory_map(cal_block->cal_data.paddr,
7712 cal_block->map_data.map_size);
7713 atomic_set(&this_afe.mem_map_cal_index, -1);
7714 if (ret < 0) {
7715 pr_err("%s: mmap did not work! size = %zd ret %d\n",
7716 __func__,
7717 cal_block->map_data.map_size, ret);
7718 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
7719 __func__,
7720 &cal_block->cal_data.paddr,
7721 cal_block->map_data.map_size);
7722 mutex_unlock(&this_afe.afe_cmd_lock);
7723 goto done;
7724 }
7725 cal_block->map_data.q6map_handle = atomic_read(&this_afe.
7726 mem_map_cal_handles[cal_index]);
7727 mutex_unlock(&this_afe.afe_cmd_lock);
7728done:
7729 return ret;
7730}
7731
7732static int afe_unmap_cal_data(int32_t cal_type,
7733 struct cal_block_data *cal_block)
7734{
7735 int ret = 0;
7736 int cal_index;
7737
7738 pr_debug("%s:\n", __func__);
7739
7740 cal_index = get_cal_type_index(cal_type);
7741 if (cal_index < 0) {
7742 pr_err("%s: could not get cal index %d!\n",
7743 __func__, cal_index);
7744 ret = -EINVAL;
7745 goto done;
7746 }
7747
7748 if (cal_block == NULL) {
7749 pr_err("%s: Cal block is NULL!\n",
7750 __func__);
7751 goto done;
7752 }
7753
7754 if (cal_block->map_data.q6map_handle == 0) {
7755 pr_err("%s: Map handle is NULL, nothing to unmap\n",
7756 __func__);
7757 goto done;
7758 }
7759
7760 atomic_set(&this_afe.mem_map_cal_handles[cal_index],
7761 cal_block->map_data.q6map_handle);
7762 atomic_set(&this_afe.mem_map_cal_index, cal_index);
7763 ret = afe_cmd_memory_unmap_nowait(
7764 cal_block->map_data.q6map_handle);
7765 atomic_set(&this_afe.mem_map_cal_index, -1);
7766 if (ret < 0) {
7767 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
7768 __func__, cal_index, ret);
7769 }
7770 cal_block->map_data.q6map_handle = 0;
7771done:
7772 return ret;
7773}
7774
7775static void afe_delete_cal_data(void)
7776{
7777 pr_debug("%s:\n", __func__);
7778
7779 cal_utils_destroy_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data);
7780}
7781
7782static int afe_init_cal_data(void)
7783{
7784 int ret = 0;
7785 struct cal_type_info cal_type_info[] = {
7786 {{AFE_COMMON_RX_CAL_TYPE,
7787 {afe_alloc_cal, afe_dealloc_cal, NULL,
7788 afe_set_cal, NULL, NULL} },
7789 {afe_map_cal_data, afe_unmap_cal_data,
7790 cal_utils_match_buf_num} },
7791
7792 {{AFE_COMMON_TX_CAL_TYPE,
7793 {afe_alloc_cal, afe_dealloc_cal, NULL,
7794 afe_set_cal, NULL, NULL} },
7795 {afe_map_cal_data, afe_unmap_cal_data,
7796 cal_utils_match_buf_num} },
7797
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307798 {{AFE_LSM_TX_CAL_TYPE,
7799 {afe_alloc_cal, afe_dealloc_cal, NULL,
7800 afe_set_cal, NULL, NULL} },
7801 {afe_map_cal_data, afe_unmap_cal_data,
7802 cal_utils_match_buf_num} },
7803
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307804 {{AFE_AANC_CAL_TYPE,
7805 {afe_alloc_cal, afe_dealloc_cal, NULL,
7806 afe_set_cal, NULL, NULL} },
7807 {afe_map_cal_data, afe_unmap_cal_data,
7808 cal_utils_match_buf_num} },
7809
7810 {{AFE_FB_SPKR_PROT_CAL_TYPE,
7811 {NULL, NULL, NULL, afe_set_cal_fb_spkr_prot,
7812 afe_get_cal_fb_spkr_prot, NULL} },
7813 {NULL, NULL, cal_utils_match_buf_num} },
7814
7815 {{AFE_HW_DELAY_CAL_TYPE,
7816 {NULL, NULL, NULL,
7817 afe_set_cal, NULL, NULL} },
7818 {NULL, NULL, cal_utils_match_buf_num} },
7819
7820 {{AFE_SIDETONE_CAL_TYPE,
7821 {NULL, NULL, NULL,
7822 afe_set_cal, NULL, NULL} },
7823 {NULL, NULL, cal_utils_match_buf_num} },
7824
7825 {{AFE_SIDETONE_IIR_CAL_TYPE,
7826 {NULL, NULL, NULL,
7827 afe_set_cal, NULL, NULL} },
7828 {NULL, NULL, cal_utils_match_buf_num} },
7829
7830 {{AFE_TOPOLOGY_CAL_TYPE,
7831 {NULL, NULL, NULL,
7832 afe_set_cal, NULL, NULL} },
7833 {NULL, NULL,
7834 cal_utils_match_buf_num} },
7835
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307836 {{AFE_LSM_TOPOLOGY_CAL_TYPE,
7837 {NULL, NULL, NULL,
7838 afe_set_cal, NULL, NULL} },
7839 {NULL, NULL,
7840 cal_utils_match_buf_num} },
7841
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307842 {{AFE_CUST_TOPOLOGY_CAL_TYPE,
7843 {afe_alloc_cal, afe_dealloc_cal, NULL,
7844 afe_set_cal, NULL, NULL} },
7845 {afe_map_cal_data, afe_unmap_cal_data,
7846 cal_utils_match_buf_num} },
7847
7848 {{AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE,
7849 {NULL, NULL, NULL, afe_set_cal_sp_th_vi_ftm_cfg,
7850 afe_get_cal_sp_th_vi_ftm_param, NULL} },
7851 {NULL, NULL, cal_utils_match_buf_num} },
7852
7853 {{AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE,
7854 {NULL, NULL, NULL, afe_set_cal_sp_ex_vi_ftm_cfg,
7855 afe_get_cal_sp_ex_vi_ftm_param, NULL} },
7856 {NULL, NULL, cal_utils_match_buf_num} },
7857 };
7858 pr_debug("%s:\n", __func__);
7859
7860 ret = cal_utils_create_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data,
7861 cal_type_info);
7862 if (ret < 0) {
7863 pr_err("%s: could not create cal type! %d\n",
7864 __func__, ret);
7865 ret = -EINVAL;
7866 goto err;
7867 }
7868
7869 return ret;
7870err:
7871 afe_delete_cal_data();
7872 return ret;
7873}
7874
7875int afe_map_rtac_block(struct rtac_cal_block_data *cal_block)
7876{
7877 int result = 0;
7878
7879 pr_debug("%s:\n", __func__);
7880
7881 if (cal_block == NULL) {
7882 pr_err("%s: cal_block is NULL!\n",
7883 __func__);
7884 result = -EINVAL;
7885 goto done;
7886 }
7887
7888 if (cal_block->cal_data.paddr == 0) {
7889 pr_debug("%s: No address to map!\n",
7890 __func__);
7891 result = -EINVAL;
7892 goto done;
7893 }
7894
7895 if (cal_block->map_data.map_size == 0) {
7896 pr_debug("%s: map size is 0!\n",
7897 __func__);
7898 result = -EINVAL;
7899 goto done;
7900 }
7901
7902 result = afe_cmd_memory_map(cal_block->cal_data.paddr,
7903 cal_block->map_data.map_size);
7904 if (result < 0) {
7905 pr_err("%s: afe_cmd_memory_map failed for addr = 0x%pK, size = %d, err %d\n",
7906 __func__, &cal_block->cal_data.paddr,
7907 cal_block->map_data.map_size, result);
7908 return result;
7909 }
7910 cal_block->map_data.map_handle = this_afe.mmap_handle;
7911
7912done:
7913 return result;
7914}
7915
7916int afe_unmap_rtac_block(uint32_t *mem_map_handle)
7917{
7918 int result = 0;
7919
7920 pr_debug("%s:\n", __func__);
7921
7922 if (mem_map_handle == NULL) {
7923 pr_err("%s: Map handle is NULL, nothing to unmap\n",
7924 __func__);
7925 goto done;
7926 }
7927
7928 if (*mem_map_handle == 0) {
7929 pr_debug("%s: Map handle is 0, nothing to unmap\n",
7930 __func__);
7931 goto done;
7932 }
7933
7934 result = afe_cmd_memory_unmap(*mem_map_handle);
7935 if (result) {
7936 pr_err("%s: AFE memory unmap failed %d, handle 0x%x\n",
7937 __func__, result, *mem_map_handle);
7938 goto done;
7939 } else {
7940 *mem_map_handle = 0;
7941 }
7942
7943done:
7944 return result;
7945}
7946
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307947int __init afe_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307948{
7949 int i = 0, ret;
7950
7951 atomic_set(&this_afe.state, 0);
7952 atomic_set(&this_afe.status, 0);
7953 atomic_set(&this_afe.mem_map_cal_index, -1);
7954 this_afe.apr = NULL;
7955 this_afe.dtmf_gen_rx_portid = -1;
7956 this_afe.mmap_handle = 0;
7957 this_afe.vi_tx_port = -1;
7958 this_afe.vi_rx_port = -1;
7959 this_afe.prot_cfg.mode = MSM_SPKR_PROT_DISABLED;
7960 this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
7961 this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
7962 mutex_init(&this_afe.afe_cmd_lock);
7963 for (i = 0; i < AFE_MAX_PORTS; i++) {
7964 this_afe.afe_cal_mode[i] = AFE_CAL_MODE_DEFAULT;
7965 this_afe.afe_sample_rates[i] = 0;
7966 this_afe.dev_acdb_id[i] = 0;
7967 init_waitqueue_head(&this_afe.wait[i]);
7968 }
7969 wakeup_source_init(&wl.ws, "spkr-prot");
7970 ret = afe_init_cal_data();
7971 if (ret)
7972 pr_err("%s: could not init cal data! %d\n", __func__, ret);
7973
7974 config_debug_fs_init();
7975 return 0;
7976}
7977
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05307978void afe_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307979{
Laxminath Kasam468ece32017-11-28 12:40:22 +05307980 if (this_afe.apr) {
7981 apr_reset(this_afe.apr);
7982 atomic_set(&this_afe.state, 0);
7983 this_afe.apr = NULL;
7984 rtac_set_afe_handle(this_afe.apr);
7985 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307986 afe_delete_cal_data();
7987
7988 config_debug_fs_exit();
7989 mutex_destroy(&this_afe.afe_cmd_lock);
7990 wakeup_source_trash(&wl.ws);
7991}