blob: 959eb616852bad9468a719bbd423b2a55b143452 [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
Cong Tang76c7e642019-02-26 15:08:55 +08002791int afe_send_slot_mapping_cfg_v2(
2792 struct afe_param_id_slot_mapping_cfg_v2 *slot_mapping_cfg,
2793 u16 port_id)
2794{
2795 struct afe_slot_mapping_config_command_v2 config;
2796 int ret = 0;
2797 int index = 0;
2798
2799 if (!slot_mapping_cfg) {
2800 pr_err("%s: Error, no configuration data\n", __func__);
2801 return -EINVAL;
2802 }
2803
2804 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2805
2806 index = q6audio_get_port_index(port_id);
2807 if (index < 0 || index >= AFE_MAX_PORTS) {
2808 pr_err("%s: AFE port index[%d] invalid!\n",
2809 __func__, index);
2810 return -EINVAL;
2811 }
2812 ret = q6audio_validate_port(port_id);
2813 if (ret < 0) {
2814 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2815 return -EINVAL;
2816 }
2817
2818 memset(&config, 0, sizeof(config));
2819 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2820 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2821 config.hdr.pkt_size = sizeof(config);
2822 config.hdr.src_port = 0;
2823 config.hdr.dest_port = 0;
2824 config.hdr.token = index;
2825
2826 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2827 config.param.port_id = q6audio_get_port_id(port_id);
2828 config.param.payload_size = sizeof(config)
2829 - sizeof(struct apr_hdr) - sizeof(config.param);
2830 config.param.payload_address_lsw = 0x00;
2831 config.param.payload_address_msw = 0x00;
2832 config.param.mem_map_handle = 0x00;
2833 config.pdata.module_id = AFE_MODULE_TDM;
2834 config.pdata.param_id = AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG;
2835 config.pdata.param_size = sizeof(config.slot_mapping);
2836 config.slot_mapping = *slot_mapping_cfg;
2837
2838 atomic_set(&this_afe.state, 1);
2839 atomic_set(&this_afe.status, 0);
2840 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
2841 if (ret < 0) {
2842 pr_err("%s: AFE send slot mapping for port 0x%x failed ret = %d\n",
2843 __func__, port_id, ret);
2844 ret = -EINVAL;
2845 goto fail_cmd;
2846 }
2847
2848 ret = wait_event_timeout(this_afe.wait[index],
2849 (atomic_read(&this_afe.state) == 0),
2850 msecs_to_jiffies(TIMEOUT_MS));
2851 if (!ret) {
2852 pr_err("%s: wait_event timeout\n",
2853 __func__);
2854 ret = -EINVAL;
2855 goto fail_cmd;
2856 }
2857 if (atomic_read(&this_afe.status) > 0) {
2858 pr_err("%s: config cmd failed [%s]\n",
2859 __func__, adsp_err_get_err_str(
2860 atomic_read(&this_afe.status)));
2861 ret = adsp_err_get_lnx_err_code(
2862 atomic_read(&this_afe.status));
2863 goto fail_cmd;
2864 }
2865
2866fail_cmd:
2867 return ret;
2868}
2869
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302870/**
2871 * afe_tdm_port_start - to configure AFE session with
2872 * specified port configuration
2873 *
2874 * @port_id: AFE port id number
2875 * @tdm_port: TDM port configutation
2876 * @rate: sampling rate of port
2877 * @num_groups: number of TDM groups
2878 *
2879 * Returns 0 on success or error value on port start failure.
2880 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302881int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
2882 u32 rate, u16 num_groups)
2883{
2884 struct afe_audioif_config_command config;
2885 int ret = 0;
2886 int index = 0;
2887 uint16_t port_index = 0;
2888 enum afe_mad_type mad_type = MAD_HW_NONE;
2889
2890 if (!tdm_port) {
2891 pr_err("%s: Error, no configuration data\n", __func__);
2892 return -EINVAL;
2893 }
2894
2895 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2896
2897 index = q6audio_get_port_index(port_id);
2898 if (index < 0 || index >= AFE_MAX_PORTS) {
2899 pr_err("%s: AFE port index[%d] invalid!\n",
2900 __func__, index);
2901 return -EINVAL;
2902 }
2903 ret = q6audio_validate_port(port_id);
2904 if (ret < 0) {
2905 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2906 return -EINVAL;
2907 }
2908
2909 ret = afe_q6_interface_prepare();
2910 if (ret != 0) {
2911 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2912 return ret;
2913 }
2914
2915 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
2916 this_afe.afe_sample_rates[index] = rate;
2917
2918 if (this_afe.rt_cb)
2919 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
2920 }
2921
Xiaoyu Ye13da4822017-09-18 17:46:30 -07002922 /* Also send the topology id here: */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302923 port_index = afe_get_port_index(port_id);
Xiaoyu Ye13da4822017-09-18 17:46:30 -07002924 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302925 /* One time call: only for first time */
2926 afe_send_custom_topology();
2927 afe_send_port_topology_id(port_id);
2928 afe_send_cal(port_id);
2929 afe_send_hw_delay(port_id, rate);
2930 }
2931
2932 /* Start SW MAD module */
2933 mad_type = afe_port_get_mad_type(port_id);
2934 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
2935 mad_type);
2936 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
2937 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
2938 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
2939 pr_err("%s: AFE isn't configured yet for\n"
2940 "HW MAD try Again\n", __func__);
2941 ret = -EAGAIN;
2942 goto fail_cmd;
2943 }
2944 ret = afe_turn_onoff_hw_mad(mad_type, true);
2945 if (ret) {
2946 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
2947 __func__, ret);
2948 goto fail_cmd;
2949 }
2950 }
2951
2952 memset(&config, 0, sizeof(config));
2953 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2954 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2955 config.hdr.pkt_size = sizeof(config);
2956 config.hdr.src_port = 0;
2957 config.hdr.dest_port = 0;
2958 config.hdr.token = index;
2959 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
2960 config.param.port_id = q6audio_get_port_id(port_id);
2961 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
2962 sizeof(config.param);
2963 config.param.payload_address_lsw = 0x00;
2964 config.param.payload_address_msw = 0x00;
2965 config.param.mem_map_handle = 0x00;
2966 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2967 config.pdata.param_id = AFE_PARAM_ID_TDM_CONFIG;
2968 config.pdata.param_size = sizeof(config.port);
2969 config.port.tdm = tdm_port->tdm;
2970
2971 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
2972 if (ret) {
2973 pr_err("%s: AFE enable for port 0x%x failed ret = %d\n",
2974 __func__, port_id, ret);
2975 goto fail_cmd;
2976 }
2977
2978 port_index = afe_get_port_index(port_id);
2979 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
2980 this_afe.afe_sample_rates[port_index] = rate;
2981 } else {
2982 pr_err("%s: Invalid port index %d\n", __func__, port_index);
2983 ret = -EINVAL;
2984 goto fail_cmd;
2985 }
Xiaoyu Ye13da4822017-09-18 17:46:30 -07002986
Cong Tang76c7e642019-02-26 15:08:55 +08002987 if (q6core_get_avcs_api_version_per_service(
2988 APRV2_IDS_SERVICE_ID_ADSP_AFE_V) >= AFE_API_VERSION_V3)
2989 ret = afe_send_slot_mapping_cfg_v2(
2990 &tdm_port->slot_mapping_v2, port_id);
2991 else
2992 ret = afe_send_slot_mapping_cfg(
2993 &tdm_port->slot_mapping,
2994 port_id);
2995
Xiaoyu Ye13da4822017-09-18 17:46:30 -07002996 if (ret < 0) {
2997 pr_err("%s: afe send failed %d\n", __func__, ret);
2998 goto fail_cmd;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302999 }
3000
3001 if (tdm_port->custom_tdm_header.header_type) {
3002 ret = afe_send_custom_tdm_header_cfg(
3003 &tdm_port->custom_tdm_header, port_id);
3004 if (ret < 0) {
3005 pr_err("%s: afe send failed %d\n", __func__, ret);
3006 goto fail_cmd;
3007 }
3008 }
3009
3010 ret = afe_send_cmd_port_start(port_id);
3011
3012fail_cmd:
3013 return ret;
3014}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303015EXPORT_SYMBOL(afe_tdm_port_start);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303016
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303017/**
3018 * afe_set_cal_mode -
3019 * set cal mode for AFE calibration
3020 *
3021 * @port_id: AFE port id number
3022 * @afe_cal_mode: AFE calib mode
3023 *
3024 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303025void afe_set_cal_mode(u16 port_id, enum afe_cal_mode afe_cal_mode)
3026{
3027 uint16_t port_index;
3028
3029 port_index = afe_get_port_index(port_id);
3030 this_afe.afe_cal_mode[port_index] = afe_cal_mode;
3031}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303032EXPORT_SYMBOL(afe_set_cal_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303033
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303034/**
3035 * afe_set_routing_callback -
3036 * Update callback function for routing
3037 *
3038 * @cb: callback function to update with
3039 *
3040 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303041void afe_set_routing_callback(routing_cb cb)
3042{
3043 this_afe.rt_cb = cb;
3044}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303045EXPORT_SYMBOL(afe_set_routing_callback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303046
3047int afe_port_send_usb_dev_param(u16 port_id, union afe_port_config *afe_config)
3048{
3049 struct afe_usb_audio_dev_param_command config;
3050 int ret = 0, index = 0;
3051
3052 if (!afe_config) {
3053 pr_err("%s: Error, no configuration data\n", __func__);
3054 ret = -EINVAL;
3055 goto exit;
3056 }
3057 index = q6audio_get_port_index(port_id);
3058 if (index < 0 || index >= AFE_MAX_PORTS) {
3059 pr_err("%s: AFE port index[%d] invalid! for port ID 0x%x\n",
3060 __func__, index, port_id);
3061 ret = -EINVAL;
3062 goto exit;
3063 }
3064 memset(&config, 0, sizeof(config));
3065 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3066 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3067 config.hdr.pkt_size = sizeof(config);
3068 config.hdr.src_port = 0;
3069 config.hdr.dest_port = 0;
3070 config.hdr.token = index;
3071 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3072 config.param.port_id = q6audio_get_port_id(port_id);
3073 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
3074 sizeof(config.param);
3075 config.param.payload_address_lsw = 0x00;
3076 config.param.payload_address_msw = 0x00;
3077 config.param.mem_map_handle = 0x00;
3078 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3079 config.pdata.param_id = AFE_PARAM_ID_USB_AUDIO_DEV_PARAMS;
3080 config.pdata.param_size = sizeof(config.usb_dev);
3081 config.usb_dev.cfg_minor_version =
3082 AFE_API_MINIOR_VERSION_USB_AUDIO_CONFIG;
3083 config.usb_dev.dev_token = afe_config->usb_audio.dev_token;
3084
3085 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3086 if (ret) {
3087 pr_err("%s: AFE device param cmd failed %d\n",
3088 __func__, ret);
3089 ret = -EINVAL;
3090 goto exit;
3091 }
3092
3093 config.pdata.param_id = AFE_PARAM_ID_USB_AUDIO_DEV_LPCM_FMT;
3094 config.pdata.param_size = sizeof(config.lpcm_fmt);
3095 config.lpcm_fmt.cfg_minor_version =
3096 AFE_API_MINIOR_VERSION_USB_AUDIO_CONFIG;
3097 config.lpcm_fmt.endian = afe_config->usb_audio.endian;
3098
3099 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3100 if (ret) {
3101 pr_err("%s: AFE device param cmd LPCM_FMT failed %d\n",
3102 __func__, ret);
3103 ret = -EINVAL;
3104 goto exit;
3105 }
3106
Haynes Mathew George7ed9b512018-02-28 18:18:09 -08003107 config.pdata.param_id = AFE_PARAM_ID_PORT_LATENCY_MODE_CONFIG;
3108 config.pdata.param_size = sizeof(config.latency_config);
3109 config.latency_config.minor_version =
3110 AFE_API_MINOR_VERSION_USB_AUDIO_LATENCY_MODE;
3111 if (afe_config->usb_audio.service_interval > 0 &&
3112 afe_config->usb_audio.service_interval <= HS_USB_INTERVAL_US)
3113 config.latency_config.mode = AFE_PORT_LOW_LATENCY_MODE;
3114 else
3115 config.latency_config.mode = AFE_PORT_DEFAULT_LATENCY_MODE;
3116
3117 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3118 if (ret) {
3119 pr_debug("%s: AFE device param cmd latency mode failed %d\n",
3120 __func__, ret);
3121 /* latency mode is an optimization, not a requirement */
3122 ret = 0;
3123 goto exit;
3124 }
3125
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303126exit:
3127 return ret;
3128}
3129
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003130static int q6afe_send_dec_config(u16 port_id,
3131 union afe_port_config afe_config,
3132 struct afe_dec_config *cfg)
3133{
3134 struct afe_audioif_config_command config;
3135 int index = 0;
3136 int ret = 0;
3137 size_t payload_size = sizeof(config) - sizeof(struct apr_hdr) -
3138 sizeof(config.param) - sizeof(config.port);
3139
3140 index = q6audio_get_port_index(port_id);
3141 if (index < 0) {
3142 pr_err("%s: Invalid index number: %d\n", __func__, index);
3143 return -EINVAL;
3144 }
3145 memset(&config, 0, sizeof(config));
3146
3147 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3148 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3149 config.hdr.pkt_size = sizeof(config);
3150 config.hdr.src_port = 0;
3151 config.hdr.dest_port = 0;
3152 config.hdr.token = index;
3153
3154 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3155 config.param.port_id = q6audio_get_port_id(port_id);
3156 config.param.payload_address_lsw = 0x00;
3157 config.param.payload_address_msw = 0x00;
3158 config.param.mem_map_handle = 0x00;
3159 config.pdata.module_id = AFE_MODULE_ID_DECODER;
3160 config.param.payload_size =
3161 payload_size + sizeof(config.port.dec_depkt_id_param);
3162 pr_debug("%s:sending AFE_DECODER_PARAM_ID_DEPACKETIZER to DSP payload = %d\n",
3163 __func__, config.param.payload_size);
3164 config.pdata.param_id = AFE_DECODER_PARAM_ID_DEPACKETIZER_ID;
3165 config.pdata.param_size = sizeof(config.port.dec_depkt_id_param);
3166 config.port.dec_depkt_id_param.dec_depacketizer_id =
3167 AFE_MODULE_ID_DEPACKETIZER_COP;
3168 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3169 if (ret) {
3170 pr_err("%s: AFE_DECODER_PARAM_ID_DEPACKETIZER for port 0x%x failed %d\n",
3171 __func__, port_id, ret);
3172 goto exit;
3173 }
3174
3175 config.param.payload_size =
3176 payload_size + sizeof(config.port.imc_info_param);
3177 pr_debug("%s:sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload = %d\n",
3178 __func__, config.param.payload_size);
3179 config.pdata.param_id = AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION;
3180 config.pdata.param_size = sizeof(config.port.imc_info_param);
3181 config.port.imc_info_param.imc_info = cfg->abr_dec_cfg.imc_info;
3182 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3183 if (ret) {
3184 pr_err("%s: AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION for port 0x%x failed %d\n",
3185 __func__, port_id, ret);
3186 goto exit;
3187 }
3188
3189 config.param.payload_size =
3190 payload_size + sizeof(config.port.media_type);
3191 config.pdata.param_size = sizeof(config.port.media_type);
3192
3193 pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP\n",
3194 __func__);
3195 config.pdata.module_id = AFE_MODULE_PORT;
3196 config.pdata.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
3197 config.port.media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
3198 config.port.media_type.sample_rate = afe_config.slim_sch.sample_rate;
3199 config.port.media_type.bit_width =
3200 afe_config.slim_sch.bit_width;
3201 config.port.media_type.num_channels =
3202 afe_config.slim_sch.num_channels;
3203 config.port.media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
3204 config.port.media_type.reserved = 0;
3205
3206 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3207 if (ret) {
3208 pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
3209 __func__, port_id, ret);
3210 goto exit;
3211 }
3212
3213exit:
3214 return ret;
3215}
3216
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303217static int q6afe_send_enc_config(u16 port_id,
3218 union afe_enc_config_data *cfg, u32 format,
3219 union afe_port_config afe_config,
Preetam Singh Ranawatf746a872017-10-20 18:13:14 +05303220 u16 afe_in_channels, u16 afe_in_bit_width,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303221 u32 scrambler_mode, u32 mono_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303222{
3223 struct afe_audioif_config_command config;
3224 int index;
3225 int ret;
3226 int payload_size = sizeof(config) - sizeof(struct apr_hdr) -
3227 sizeof(config.param) - sizeof(config.port);
3228
3229 pr_debug("%s:update DSP for enc format = %d\n", __func__, format);
3230 if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 &&
Preetam Singh Ranawat54028492017-09-04 11:42:26 +05303231 format != ASM_MEDIA_FMT_APTX && format != ASM_MEDIA_FMT_APTX_HD &&
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05303232 format != ASM_MEDIA_FMT_CELT && format != ASM_MEDIA_FMT_LDAC) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303233 pr_err("%s:Unsuppported format Ignore AFE config\n", __func__);
3234 return 0;
3235 }
3236 memset(&config, 0, sizeof(config));
3237 index = q6audio_get_port_index(port_id);
3238 if (index < 0) {
3239 pr_err("%s: Invalid index number: %d\n", __func__, index);
3240 return -EINVAL;
3241 }
3242
3243 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3244 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3245 config.hdr.pkt_size = sizeof(config);
3246 config.hdr.src_port = 0;
3247 config.hdr.dest_port = 0;
3248 config.hdr.token = index;
3249
3250 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3251 config.param.port_id = q6audio_get_port_id(port_id);
3252 config.param.payload_size = payload_size + sizeof(config.port.enc_fmt);
3253 config.param.payload_address_lsw = 0x00;
3254 config.param.payload_address_msw = 0x00;
3255 config.param.mem_map_handle = 0x00;
3256 config.pdata.module_id = AFE_MODULE_ID_ENCODER;
3257 config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_FMT_ID;
3258 config.pdata.param_size = sizeof(config.port.enc_fmt);
3259 config.port.enc_fmt.fmt_id = format;
3260 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENC_FMT_ID payload: %d\n",
3261 __func__, config.param.payload_size);
3262 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3263 if (ret) {
3264 pr_err("%s:unable to send AFE_ENCODER_PARAM_ID_ENC_FMT_ID",
3265 __func__);
3266 goto exit;
3267 }
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003268 if (format == ASM_MEDIA_FMT_LDAC) {
3269 config.param.payload_size = payload_size
3270 + sizeof(config.port.enc_blk_param)
3271 - sizeof(struct afe_abr_enc_cfg_t);
3272 config.pdata.param_size = sizeof(config.port.enc_blk_param)
3273 - sizeof(struct afe_abr_enc_cfg_t);
3274 config.port.enc_blk_param.enc_cfg_blk_size =
3275 sizeof(config.port.enc_blk_param.enc_blk_config)
3276 - sizeof(struct afe_abr_enc_cfg_t);
3277 } else {
3278 config.param.payload_size = payload_size
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303279 + sizeof(config.port.enc_blk_param);
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003280 config.pdata.param_size = sizeof(config.port.enc_blk_param);
3281 config.port.enc_blk_param.enc_cfg_blk_size =
3282 sizeof(config.port.enc_blk_param.enc_blk_config);
3283 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303284 pr_debug("%s:send AFE_ENCODER_PARAM_ID_ENC_CFG_BLK to DSP payload:%d\n",
3285 __func__, config.param.payload_size);
3286 config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_CFG_BLK;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303287 config.port.enc_blk_param.enc_blk_config = *cfg;
3288 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3289 if (ret) {
3290 pr_err("%s: AFE_ENCODER_PARAM_ID_ENC_CFG_BLK for port 0x%x failed %d\n",
3291 __func__, port_id, ret);
3292 goto exit;
3293 }
3294
Preetam Singh Ranawat899b78b2017-09-07 12:36:06 -07003295 if (format == ASM_MEDIA_FMT_APTX) {
3296 config.param.payload_size =
3297 payload_size + sizeof(config.port.sync_mode_param);
3298 pr_debug("%s: sending AFE_PARAM_ID_APTX_SYNC_MODE to DSP",
3299 __func__);
3300 config.pdata.param_id = AFE_PARAM_ID_APTX_SYNC_MODE;
3301 config.pdata.param_size = sizeof(config.port.sync_mode_param);
3302 config.port.sync_mode_param.sync_mode =
3303 config.port.enc_blk_param.enc_blk_config.aptx_config.
3304 aptx_v2_cfg.sync_mode;
3305 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3306 if (ret) {
3307 pr_err("%s: AFE_PARAM_ID_APTX_SYNC_MODE for port 0x%x failed %d\n",
3308 __func__, port_id, ret);
3309 goto exit;
3310 }
3311 }
3312
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303313 config.param.payload_size =
3314 payload_size + sizeof(config.port.enc_pkt_id_param);
3315 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_PACKETIZER to DSP payload = %d",
3316 __func__, config.param.payload_size);
3317 config.pdata.param_id = AFE_ENCODER_PARAM_ID_PACKETIZER_ID;
3318 config.pdata.param_size = sizeof(config.port.enc_pkt_id_param);
3319 config.port.enc_pkt_id_param.enc_packetizer_id =
3320 AFE_MODULE_ID_PACKETIZER_COP;
3321 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3322 if (ret) {
3323 pr_err("%s: AFE_ENCODER_PARAM_ID_PACKETIZER for port 0x%x failed %d\n",
3324 __func__, port_id, ret);
3325 goto exit;
3326 }
3327
3328 config.param.payload_size =
Preetam Singh Ranawatf746a872017-10-20 18:13:14 +05303329 payload_size + sizeof(config.port.enc_set_scrambler_param);
3330 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING mode= %d to DSP payload = %d\n",
3331 __func__, scrambler_mode, config.param.payload_size);
3332 config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING;
3333 config.pdata.param_size = sizeof(config.port.enc_set_scrambler_param);
3334 config.port.enc_set_scrambler_param.enable_scrambler = scrambler_mode;
3335 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3336 if (ret) {
3337 pr_err("%s: AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING for port 0x%x failed %d\n",
3338 __func__, port_id, ret);
3339 goto exit;
3340 }
3341
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303342 if (format == ASM_MEDIA_FMT_APTX) {
3343 config.param.payload_size =
3344 payload_size + sizeof(config.port.channel_mode_param);
3345 pr_debug("%s:sending CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO mode= %d to DSP payload\n",
3346 __func__, mono_mode);
3347 config.pdata.param_id = CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO;
3348 config.pdata.param_size = sizeof(config.port.channel_mode_param);
3349 config.port.channel_mode_param.channel_mode = mono_mode;
3350 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3351 if (ret) {
3352 pr_err("%s: CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO for port 0x%x failed %d\n",
3353 __func__, port_id, ret);
3354 }
3355 }
3356
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003357 if (format == ASM_MEDIA_FMT_LDAC) {
3358 config.param.payload_size =
3359 payload_size + sizeof(config.port.map_param);
3360 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP to DSP payload = %d\n",
3361 __func__, config.param.payload_size);
3362 config.pdata.param_id = AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP;
3363 config.pdata.param_size = sizeof(config.port.map_param);
3364 config.port.map_param.mapping_table =
3365 cfg->ldac_config.abr_config.mapping_info;
3366 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3367 if (ret) {
3368 pr_err("%s: AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP for port 0x%x failed %d\n",
3369 __func__, port_id, ret);
3370 goto exit;
3371 }
3372
3373 config.param.payload_size =
3374 payload_size + sizeof(config.port.imc_info_param);
3375 pr_debug("%s:sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload = %d\n",
3376 __func__, config.param.payload_size);
3377 config.pdata.param_id =
3378 AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION;
3379 config.pdata.param_size = sizeof(config.port.imc_info_param);
3380 config.port.imc_info_param.imc_info =
3381 cfg->ldac_config.abr_config.imc_info;
3382 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3383 if (ret) {
3384 pr_err("%s: AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION for port 0x%x failed %d\n",
3385 __func__, port_id, ret);
3386 goto exit;
3387 }
3388 }
3389
Preetam Singh Ranawatf746a872017-10-20 18:13:14 +05303390 config.param.payload_size =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303391 payload_size + sizeof(config.port.media_type);
3392 config.pdata.param_size = sizeof(config.port.media_type);
3393
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003394 pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP\n",
3395 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303396 config.pdata.module_id = AFE_MODULE_PORT;
3397 config.pdata.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
3398 config.port.media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003399 if (format == ASM_MEDIA_FMT_LDAC)
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05303400 config.port.media_type.sample_rate =
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003401 cfg->ldac_config.custom_config.sample_rate;
3402 else
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05303403 config.port.media_type.sample_rate =
3404 afe_config.slim_sch.sample_rate;
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05303405
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303406 if (afe_in_bit_width)
3407 config.port.media_type.bit_width = afe_in_bit_width;
3408 else
3409 config.port.media_type.bit_width =
3410 afe_config.slim_sch.bit_width;
3411
3412 if (afe_in_channels)
3413 config.port.media_type.num_channels = afe_in_channels;
3414 else
3415 config.port.media_type.num_channels =
3416 afe_config.slim_sch.num_channels;
3417 config.port.media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
3418 config.port.media_type.reserved = 0;
3419
3420 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3421 if (ret) {
3422 pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
3423 __func__, port_id, ret);
3424 goto exit;
3425 }
3426
3427exit:
3428 return ret;
3429}
3430
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303431int afe_set_tws_channel_mode(u16 port_id, u32 channel_mode)
3432{
3433 struct aptx_channel_mode_param_t channel_mode_param;
3434 int ret = 0;
3435 int index = 0;
3436
3437 pr_debug("%s: enter\n", __func__);
3438 index = q6audio_get_port_index(port_id);
3439 if (index < 0 || index >= AFE_MAX_PORTS) {
3440 pr_err("%s: AFE port index[%d] invalid!\n",
3441 __func__, index);
3442 return -EINVAL;
3443 }
3444
3445 ret = q6audio_validate_port(port_id);
3446 if (ret < 0) {
3447 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
3448 return -EINVAL;
3449 }
3450
3451 channel_mode_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3452 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3453 channel_mode_param.hdr.pkt_size = sizeof(channel_mode_param);
3454 channel_mode_param.hdr.src_port = 0;
3455 channel_mode_param.hdr.dest_port = 0;
3456 channel_mode_param.hdr.token = index;
3457
3458 channel_mode_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3459 channel_mode_param.param.payload_size = sizeof(channel_mode_param) - sizeof(struct apr_hdr)
3460 - sizeof(channel_mode_param.param);
3461
3462 channel_mode_param.param.payload_address_lsw = 0x00;
3463 channel_mode_param.param.payload_address_msw = 0x00;
3464 channel_mode_param.param.mem_map_handle = 0x00;
3465 channel_mode_param.param.port_id = q6audio_get_port_id(port_id);
3466 channel_mode_param.pdata.module_id = AFE_MODULE_ID_ENCODER;
3467 channel_mode_param.pdata.param_id = CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO;
3468 channel_mode_param.pdata.param_size = sizeof(channel_mode_param.channel_mode);
3469
3470 channel_mode_param.channel_mode = channel_mode;
3471
3472 ret = afe_apr_send_pkt(&channel_mode_param, &this_afe.wait[index]);
3473
3474 if (ret)
3475 pr_err("%s: AFE set channel mode cfg for port 0x%x failed %d\n",
3476 __func__, port_id, ret);
3477
3478 return ret;
3479}
3480EXPORT_SYMBOL(afe_set_tws_channel_mode);
3481
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303482static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
3483 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003484 union afe_enc_config_data *enc_cfg,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303485 u32 codec_format, u32 scrambler_mode, u32 mono_mode,
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003486 struct afe_dec_config *dec_cfg)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303487{
3488 struct afe_audioif_config_command config;
3489 int ret = 0;
3490 int cfg_type;
3491 int index = 0;
3492 enum afe_mad_type mad_type;
3493 uint16_t port_index;
3494
3495 if (!afe_config) {
3496 pr_err("%s: Error, no configuration data\n", __func__);
3497 ret = -EINVAL;
3498 return ret;
3499 }
3500
3501 if ((port_id == RT_PROXY_DAI_001_RX) ||
3502 (port_id == RT_PROXY_DAI_002_TX)) {
3503 pr_debug("%s: before incrementing pcm_afe_instance %d port_id 0x%x\n",
3504 __func__,
3505 pcm_afe_instance[port_id & 0x1], port_id);
3506 port_id = VIRTUAL_ID_TO_PORTID(port_id);
3507 pcm_afe_instance[port_id & 0x1]++;
3508 return 0;
3509 }
3510 if ((port_id == RT_PROXY_DAI_002_RX) ||
3511 (port_id == RT_PROXY_DAI_001_TX)) {
3512 pr_debug("%s: before incrementing proxy_afe_instance %d port_id 0x%x\n",
3513 __func__,
3514 proxy_afe_instance[port_id & 0x1], port_id);
3515
3516 if (!afe_close_done[port_id & 0x1]) {
3517 /*close pcm dai corresponding to the proxy dai*/
3518 afe_close(port_id - 0x10);
3519 pcm_afe_instance[port_id & 0x1]++;
3520 pr_debug("%s: reconfigure afe port again\n", __func__);
3521 }
3522 proxy_afe_instance[port_id & 0x1]++;
3523 afe_close_done[port_id & 0x1] = false;
3524 port_id = VIRTUAL_ID_TO_PORTID(port_id);
3525 }
3526
3527 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
3528
3529 index = q6audio_get_port_index(port_id);
3530 if (index < 0 || index >= AFE_MAX_PORTS) {
3531 pr_err("%s: AFE port index[%d] invalid!\n",
3532 __func__, index);
3533 return -EINVAL;
3534 }
3535 ret = q6audio_validate_port(port_id);
3536 if (ret < 0) {
3537 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
3538 return -EINVAL;
3539 }
3540
3541 ret = afe_q6_interface_prepare();
3542 if (ret != 0) {
3543 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3544 return ret;
3545 }
3546
3547 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
3548 this_afe.afe_sample_rates[index] = rate;
3549
3550 if (this_afe.rt_cb)
3551 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
3552 }
3553
3554 mutex_lock(&this_afe.afe_cmd_lock);
3555 /* Also send the topology id here: */
3556 port_index = afe_get_port_index(port_id);
3557 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
3558 /* One time call: only for first time */
3559 afe_send_custom_topology();
3560 afe_send_port_topology_id(port_id);
3561 afe_send_cal(port_id);
3562 afe_send_hw_delay(port_id, rate);
3563 }
3564
3565 /* Start SW MAD module */
3566 mad_type = afe_port_get_mad_type(port_id);
3567 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
3568 mad_type);
3569 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
3570 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
3571 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
3572 pr_err("%s: AFE isn't configured yet for\n"
3573 "HW MAD try Again\n", __func__);
3574 ret = -EAGAIN;
3575 goto fail_cmd;
3576 }
3577 ret = afe_turn_onoff_hw_mad(mad_type, true);
3578 if (ret) {
3579 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
3580 __func__, ret);
3581 goto fail_cmd;
3582 }
3583 }
3584
3585 if ((this_afe.aanc_info.aanc_active) &&
3586 (this_afe.aanc_info.aanc_tx_port == port_id)) {
3587 this_afe.aanc_info.aanc_tx_port_sample_rate = rate;
3588 port_index =
3589 afe_get_port_index(this_afe.aanc_info.aanc_rx_port);
3590 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3591 this_afe.aanc_info.aanc_rx_port_sample_rate =
3592 this_afe.afe_sample_rates[port_index];
3593 } else {
3594 pr_err("%s: Invalid port index %d\n",
3595 __func__, port_index);
3596 ret = -EINVAL;
3597 goto fail_cmd;
3598 }
3599 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
3600 this_afe.aanc_info.aanc_rx_port);
3601 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
3602 }
3603
3604 if ((port_id == AFE_PORT_ID_USB_RX) ||
3605 (port_id == AFE_PORT_ID_USB_TX)) {
3606 ret = afe_port_send_usb_dev_param(port_id, afe_config);
3607 if (ret) {
3608 pr_err("%s: AFE device param for port 0x%x failed %d\n",
3609 __func__, port_id, ret);
3610 ret = -EINVAL;
3611 goto fail_cmd;
3612 }
3613 }
3614
3615 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3616 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3617 config.hdr.pkt_size = sizeof(config);
3618 config.hdr.src_port = 0;
3619 config.hdr.dest_port = 0;
3620 config.hdr.token = index;
3621
3622 switch (port_id) {
3623 case AFE_PORT_ID_PRIMARY_PCM_RX:
3624 case AFE_PORT_ID_PRIMARY_PCM_TX:
3625 case AFE_PORT_ID_SECONDARY_PCM_RX:
3626 case AFE_PORT_ID_SECONDARY_PCM_TX:
3627 case AFE_PORT_ID_TERTIARY_PCM_RX:
3628 case AFE_PORT_ID_TERTIARY_PCM_TX:
3629 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3630 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303631 case AFE_PORT_ID_QUINARY_PCM_RX:
3632 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303633 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
3634 break;
3635 case PRIMARY_I2S_RX:
3636 case PRIMARY_I2S_TX:
3637 case SECONDARY_I2S_RX:
3638 case SECONDARY_I2S_TX:
3639 case MI2S_RX:
3640 case MI2S_TX:
3641 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3642 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3643 case AFE_PORT_ID_SECONDARY_MI2S_RX:
3644 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
3645 case AFE_PORT_ID_SECONDARY_MI2S_TX:
3646 case AFE_PORT_ID_TERTIARY_MI2S_RX:
3647 case AFE_PORT_ID_TERTIARY_MI2S_TX:
3648 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3649 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3650 case AFE_PORT_ID_QUINARY_MI2S_RX:
3651 case AFE_PORT_ID_QUINARY_MI2S_TX:
3652 case AFE_PORT_ID_SENARY_MI2S_TX:
3653 case AFE_PORT_ID_INT0_MI2S_RX:
3654 case AFE_PORT_ID_INT0_MI2S_TX:
3655 case AFE_PORT_ID_INT1_MI2S_RX:
3656 case AFE_PORT_ID_INT1_MI2S_TX:
3657 case AFE_PORT_ID_INT2_MI2S_RX:
3658 case AFE_PORT_ID_INT2_MI2S_TX:
3659 case AFE_PORT_ID_INT3_MI2S_RX:
3660 case AFE_PORT_ID_INT3_MI2S_TX:
3661 case AFE_PORT_ID_INT4_MI2S_RX:
3662 case AFE_PORT_ID_INT4_MI2S_TX:
3663 case AFE_PORT_ID_INT5_MI2S_RX:
3664 case AFE_PORT_ID_INT5_MI2S_TX:
3665 case AFE_PORT_ID_INT6_MI2S_RX:
3666 case AFE_PORT_ID_INT6_MI2S_TX:
3667 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
3668 break;
3669 case HDMI_RX:
3670 case DISPLAY_PORT_RX:
3671 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
3672 break;
3673 case VOICE_PLAYBACK_TX:
3674 case VOICE2_PLAYBACK_TX:
3675 case VOICE_RECORD_RX:
3676 case VOICE_RECORD_TX:
3677 cfg_type = AFE_PARAM_ID_PSEUDO_PORT_CONFIG;
3678 break;
3679 case SLIMBUS_0_RX:
3680 case SLIMBUS_0_TX:
3681 case SLIMBUS_1_RX:
3682 case SLIMBUS_1_TX:
3683 case SLIMBUS_2_RX:
3684 case SLIMBUS_2_TX:
3685 case SLIMBUS_3_RX:
3686 case SLIMBUS_3_TX:
3687 case SLIMBUS_4_RX:
3688 case SLIMBUS_4_TX:
3689 case SLIMBUS_5_RX:
3690 case SLIMBUS_5_TX:
3691 case SLIMBUS_6_RX:
3692 case SLIMBUS_6_TX:
3693 case SLIMBUS_7_RX:
3694 case SLIMBUS_7_TX:
3695 case SLIMBUS_8_RX:
3696 case SLIMBUS_8_TX:
3697 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
3698 break;
3699 case AFE_PORT_ID_USB_RX:
3700 case AFE_PORT_ID_USB_TX:
3701 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
3702 break;
3703 case RT_PROXY_PORT_001_RX:
3704 case RT_PROXY_PORT_001_TX:
3705 cfg_type = AFE_PARAM_ID_RT_PROXY_CONFIG;
3706 break;
3707 case INT_BT_SCO_RX:
3708 case INT_BT_A2DP_RX:
3709 case INT_BT_SCO_TX:
3710 case INT_FM_RX:
3711 case INT_FM_TX:
3712 cfg_type = AFE_PARAM_ID_INTERNAL_BT_FM_CONFIG;
3713 break;
3714 default:
3715 pr_err("%s: Invalid port id 0x%x\n", __func__, port_id);
3716 ret = -EINVAL;
3717 goto fail_cmd;
3718 }
3719 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3720 config.param.port_id = q6audio_get_port_id(port_id);
3721 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
3722 sizeof(config.param);
3723 config.param.payload_address_lsw = 0x00;
3724 config.param.payload_address_msw = 0x00;
3725 config.param.mem_map_handle = 0x00;
3726 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3727 config.pdata.param_id = cfg_type;
3728 config.pdata.param_size = sizeof(config.port);
3729
3730 config.port = *afe_config;
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003731 if (((enc_cfg != NULL) || (dec_cfg != NULL)) &&
3732 (codec_format != ASM_MEDIA_FMT_NONE) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303733 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
3734 config.port.slim_sch.data_format =
3735 AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED;
3736 }
3737 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3738 if (ret) {
3739 pr_err("%s: AFE enable for port 0x%x failed %d\n",
3740 __func__, port_id, ret);
3741 goto fail_cmd;
3742 }
3743
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003744 if ((codec_format != ASM_MEDIA_FMT_NONE) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303745 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003746 if (enc_cfg != NULL) {
3747 pr_debug("%s: Found AFE encoder support for SLIMBUS enc_format = %d\n",
3748 __func__, codec_format);
3749 ret = q6afe_send_enc_config(port_id, enc_cfg,
3750 codec_format, *afe_config,
3751 afe_in_channels,
3752 afe_in_bit_width,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303753 scrambler_mode, mono_mode);
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003754 if (ret) {
3755 pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
3756 __func__, port_id, ret);
3757 goto fail_cmd;
3758 }
3759 }
3760 if (dec_cfg != NULL) {
3761 pr_debug("%s: Found AFE decoder support for SLIMBUS dec_format = %d\n",
3762 __func__, codec_format);
3763 ret = q6afe_send_dec_config(port_id, *afe_config,
3764 dec_cfg);
3765 if (ret) {
3766 pr_err("%s: AFE decoder config for port 0x%x failed %d\n",
3767 __func__, port_id, ret);
3768 goto fail_cmd;
3769 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303770 }
3771 }
3772
3773 port_index = afe_get_port_index(port_id);
3774 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3775 /*
3776 * If afe_port_start() for tx port called before
3777 * rx port, then aanc rx sample rate is zero. So,
3778 * AANC state machine in AFE will not get triggered.
3779 * Make sure to check whether aanc is active during
3780 * afe_port_start() for rx port and if aanc rx
3781 * sample rate is zero, call afe_aanc_start to configure
3782 * aanc with valid sample rates.
3783 */
3784 if (this_afe.aanc_info.aanc_active &&
3785 !this_afe.aanc_info.aanc_rx_port_sample_rate) {
3786 this_afe.aanc_info.aanc_rx_port_sample_rate =
3787 this_afe.afe_sample_rates[port_index];
3788 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
3789 this_afe.aanc_info.aanc_rx_port);
3790 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
3791 }
3792 } else {
3793 pr_err("%s: Invalid port index %d\n", __func__, port_index);
3794 ret = -EINVAL;
3795 goto fail_cmd;
3796 }
3797 ret = afe_send_cmd_port_start(port_id);
3798
3799fail_cmd:
3800 mutex_unlock(&this_afe.afe_cmd_lock);
3801 return ret;
3802}
3803
3804/**
3805 * afe_port_start - to configure AFE session with
3806 * specified port configuration
3807 *
3808 * @port_id: AFE port id number
3809 * @afe_config: port configutation
3810 * @rate: sampling rate of port
3811 *
3812 * Returns 0 on success or error value on port start failure.
3813 */
3814int afe_port_start(u16 port_id, union afe_port_config *afe_config,
3815 u32 rate)
3816{
3817 return __afe_port_start(port_id, afe_config, rate,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303818 0, 0, NULL, ASM_MEDIA_FMT_NONE, 0, 0, NULL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303819}
3820EXPORT_SYMBOL(afe_port_start);
3821
3822/**
3823 * afe_port_start_v2 - to configure AFE session with
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003824 * specified port configuration and encoder/decoder params
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303825 *
3826 * @port_id: AFE port id number
3827 * @afe_config: port configutation
3828 * @rate: sampling rate of port
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003829 * @enc_cfg: AFE enc configuration information to setup encoder
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303830 * @afe_in_channels: AFE input channel configuration, this needs
3831 * update only if input channel is differ from AFE output
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003832 * @dec_cfg: AFE dec configuration information to set up decoder
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303833 *
3834 * Returns 0 on success or error value on port start failure.
3835 */
3836int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
3837 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003838 struct afe_enc_config *enc_cfg,
3839 struct afe_dec_config *dec_cfg)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303840{
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003841 int ret = 0;
3842
3843 if (enc_cfg != NULL)
3844 ret = __afe_port_start(port_id, afe_config, rate,
3845 afe_in_channels, afe_in_bit_width,
3846 &enc_cfg->data, enc_cfg->format,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303847 enc_cfg->scrambler_mode,
3848 enc_cfg->mono_mode, NULL);
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003849 else if (dec_cfg != NULL)
3850 ret = __afe_port_start(port_id, afe_config, rate,
3851 afe_in_channels, afe_in_bit_width,
Manisha Agarwal472fc1e2018-11-04 15:46:02 +05303852 NULL, dec_cfg->format, 0, 0, dec_cfg);
Aniket Kumar Lataf8664712018-02-22 14:46:09 -08003853
3854 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303855}
3856EXPORT_SYMBOL(afe_port_start_v2);
3857
3858int afe_get_port_index(u16 port_id)
3859{
3860 switch (port_id) {
3861 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
3862 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
3863 case AFE_PORT_ID_PRIMARY_PCM_RX:
3864 return IDX_AFE_PORT_ID_PRIMARY_PCM_RX;
3865 case AFE_PORT_ID_PRIMARY_PCM_TX:
3866 return IDX_AFE_PORT_ID_PRIMARY_PCM_TX;
3867 case AFE_PORT_ID_SECONDARY_PCM_RX:
3868 return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
3869 case AFE_PORT_ID_SECONDARY_PCM_TX:
3870 return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
3871 case AFE_PORT_ID_TERTIARY_PCM_RX:
3872 return IDX_AFE_PORT_ID_TERTIARY_PCM_RX;
3873 case AFE_PORT_ID_TERTIARY_PCM_TX:
3874 return IDX_AFE_PORT_ID_TERTIARY_PCM_TX;
3875 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3876 return IDX_AFE_PORT_ID_QUATERNARY_PCM_RX;
3877 case AFE_PORT_ID_QUATERNARY_PCM_TX:
3878 return IDX_AFE_PORT_ID_QUATERNARY_PCM_TX;
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303879 case AFE_PORT_ID_QUINARY_PCM_RX:
3880 return IDX_AFE_PORT_ID_QUINARY_PCM_RX;
3881 case AFE_PORT_ID_QUINARY_PCM_TX:
3882 return IDX_AFE_PORT_ID_QUINARY_PCM_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303883 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
3884 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
3885 case MI2S_RX: return IDX_MI2S_RX;
3886 case MI2S_TX: return IDX_MI2S_TX;
3887 case HDMI_RX: return IDX_HDMI_RX;
3888 case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX;
3889 case AFE_PORT_ID_SPDIF_RX: return IDX_SPDIF_RX;
3890 case RSVD_2: return IDX_RSVD_2;
3891 case RSVD_3: return IDX_RSVD_3;
3892 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
3893 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
3894 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
3895 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
3896 case VOICE2_PLAYBACK_TX: return IDX_VOICE2_PLAYBACK_TX;
3897 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
3898 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
3899 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
3900 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
3901 case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
3902 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
3903 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
3904 case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
3905 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
3906 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
3907 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
3908 case INT_FM_RX: return IDX_INT_FM_RX;
3909 case INT_FM_TX: return IDX_INT_FM_TX;
3910 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
3911 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
3912 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
3913 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
3914 case SLIMBUS_5_RX: return IDX_SLIMBUS_5_RX;
3915 case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX;
3916 case SLIMBUS_6_RX: return IDX_SLIMBUS_6_RX;
3917 case SLIMBUS_6_TX: return IDX_SLIMBUS_6_TX;
3918 case SLIMBUS_7_RX: return IDX_SLIMBUS_7_RX;
3919 case SLIMBUS_7_TX: return IDX_SLIMBUS_7_TX;
3920 case SLIMBUS_8_RX: return IDX_SLIMBUS_8_RX;
3921 case SLIMBUS_8_TX: return IDX_SLIMBUS_8_TX;
3922 case AFE_PORT_ID_USB_RX: return IDX_AFE_PORT_ID_USB_RX;
3923 case AFE_PORT_ID_USB_TX: return IDX_AFE_PORT_ID_USB_TX;
3924 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3925 return IDX_AFE_PORT_ID_PRIMARY_MI2S_RX;
3926 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3927 return IDX_AFE_PORT_ID_PRIMARY_MI2S_TX;
3928 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3929 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
3930 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3931 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX;
3932 case AFE_PORT_ID_SECONDARY_MI2S_RX:
3933 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX;
3934 case AFE_PORT_ID_SECONDARY_MI2S_TX:
3935 return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX;
3936 case AFE_PORT_ID_TERTIARY_MI2S_RX:
3937 return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX;
3938 case AFE_PORT_ID_TERTIARY_MI2S_TX:
3939 return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX;
3940 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
3941 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_SD1;
3942 case AFE_PORT_ID_QUINARY_MI2S_RX:
3943 return IDX_AFE_PORT_ID_QUINARY_MI2S_RX;
3944 case AFE_PORT_ID_QUINARY_MI2S_TX:
3945 return IDX_AFE_PORT_ID_QUINARY_MI2S_TX;
3946 case AFE_PORT_ID_SENARY_MI2S_TX:
3947 return IDX_AFE_PORT_ID_SENARY_MI2S_TX;
3948 case AFE_PORT_ID_PRIMARY_TDM_RX:
3949 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_0;
3950 case AFE_PORT_ID_PRIMARY_TDM_TX:
3951 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_0;
3952 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
3953 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_1;
3954 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
3955 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_1;
3956 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
3957 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_2;
3958 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
3959 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_2;
3960 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
3961 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_3;
3962 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
3963 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_3;
3964 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
3965 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_4;
3966 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
3967 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_4;
3968 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
3969 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_5;
3970 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
3971 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_5;
3972 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
3973 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_6;
3974 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
3975 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_6;
3976 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
3977 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_7;
3978 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
3979 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_7;
3980 case AFE_PORT_ID_SECONDARY_TDM_RX:
3981 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_0;
3982 case AFE_PORT_ID_SECONDARY_TDM_TX:
3983 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_0;
3984 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
3985 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_1;
3986 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
3987 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_1;
3988 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
3989 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_2;
3990 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
3991 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_2;
3992 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
3993 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_3;
3994 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
3995 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_3;
3996 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
3997 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_4;
3998 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
3999 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_4;
4000 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
4001 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_5;
4002 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
4003 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_5;
4004 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
4005 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_6;
4006 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
4007 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_6;
4008 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
4009 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_7;
4010 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
4011 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_7;
4012 case AFE_PORT_ID_TERTIARY_TDM_RX:
4013 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_0;
4014 case AFE_PORT_ID_TERTIARY_TDM_TX:
4015 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_0;
4016 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
4017 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_1;
4018 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
4019 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_1;
4020 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
4021 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_2;
4022 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
4023 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_2;
4024 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
4025 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_3;
4026 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
4027 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_3;
4028 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
4029 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_4;
4030 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
4031 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_4;
4032 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
4033 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_5;
4034 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
4035 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_5;
4036 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
4037 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_6;
4038 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
4039 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_6;
4040 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
4041 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_7;
4042 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
4043 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_7;
4044 case AFE_PORT_ID_QUATERNARY_TDM_RX:
4045 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_0;
4046 case AFE_PORT_ID_QUATERNARY_TDM_TX:
4047 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_0;
4048 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
4049 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_1;
4050 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
4051 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_1;
4052 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
4053 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_2;
4054 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
4055 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_2;
4056 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
4057 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_3;
4058 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
4059 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_3;
4060 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
4061 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_4;
4062 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
4063 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_4;
4064 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
4065 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_5;
4066 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
4067 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_5;
4068 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
4069 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_6;
4070 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
4071 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_6;
4072 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
4073 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_7;
4074 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
4075 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_7;
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304076 case AFE_PORT_ID_QUINARY_TDM_RX:
4077 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_0;
4078 case AFE_PORT_ID_QUINARY_TDM_TX:
4079 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_0;
4080 case AFE_PORT_ID_QUINARY_TDM_RX_1:
4081 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_1;
4082 case AFE_PORT_ID_QUINARY_TDM_TX_1:
4083 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_1;
4084 case AFE_PORT_ID_QUINARY_TDM_RX_2:
4085 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_2;
4086 case AFE_PORT_ID_QUINARY_TDM_TX_2:
4087 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_2;
4088 case AFE_PORT_ID_QUINARY_TDM_RX_3:
4089 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_3;
4090 case AFE_PORT_ID_QUINARY_TDM_TX_3:
4091 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_3;
4092 case AFE_PORT_ID_QUINARY_TDM_RX_4:
4093 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_4;
4094 case AFE_PORT_ID_QUINARY_TDM_TX_4:
4095 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_4;
4096 case AFE_PORT_ID_QUINARY_TDM_RX_5:
4097 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_5;
4098 case AFE_PORT_ID_QUINARY_TDM_TX_5:
4099 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_5;
4100 case AFE_PORT_ID_QUINARY_TDM_RX_6:
4101 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_6;
4102 case AFE_PORT_ID_QUINARY_TDM_TX_6:
4103 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_6;
4104 case AFE_PORT_ID_QUINARY_TDM_RX_7:
4105 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_7;
4106 case AFE_PORT_ID_QUINARY_TDM_TX_7:
4107 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_7;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304108 case AFE_PORT_ID_INT0_MI2S_RX:
4109 return IDX_AFE_PORT_ID_INT0_MI2S_RX;
4110 case AFE_PORT_ID_INT0_MI2S_TX:
4111 return IDX_AFE_PORT_ID_INT0_MI2S_TX;
4112 case AFE_PORT_ID_INT1_MI2S_RX:
4113 return IDX_AFE_PORT_ID_INT1_MI2S_RX;
4114 case AFE_PORT_ID_INT1_MI2S_TX:
4115 return IDX_AFE_PORT_ID_INT1_MI2S_TX;
4116 case AFE_PORT_ID_INT2_MI2S_RX:
4117 return IDX_AFE_PORT_ID_INT2_MI2S_RX;
4118 case AFE_PORT_ID_INT2_MI2S_TX:
4119 return IDX_AFE_PORT_ID_INT2_MI2S_TX;
4120 case AFE_PORT_ID_INT3_MI2S_RX:
4121 return IDX_AFE_PORT_ID_INT3_MI2S_RX;
4122 case AFE_PORT_ID_INT3_MI2S_TX:
4123 return IDX_AFE_PORT_ID_INT3_MI2S_TX;
4124 case AFE_PORT_ID_INT4_MI2S_RX:
4125 return IDX_AFE_PORT_ID_INT4_MI2S_RX;
4126 case AFE_PORT_ID_INT4_MI2S_TX:
4127 return IDX_AFE_PORT_ID_INT4_MI2S_TX;
4128 case AFE_PORT_ID_INT5_MI2S_RX:
4129 return IDX_AFE_PORT_ID_INT5_MI2S_RX;
4130 case AFE_PORT_ID_INT5_MI2S_TX:
4131 return IDX_AFE_PORT_ID_INT5_MI2S_TX;
4132 case AFE_PORT_ID_INT6_MI2S_RX:
4133 return IDX_AFE_PORT_ID_INT6_MI2S_RX;
4134 case AFE_PORT_ID_INT6_MI2S_TX:
4135 return IDX_AFE_PORT_ID_INT6_MI2S_TX;
Raja Mallik425e1d32018-05-20 19:21:10 +05304136 case AFE_LOOPBACK_TX:
4137 return IDX_AFE_LOOPBACK_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304138 default:
4139 pr_err("%s: port 0x%x\n", __func__, port_id);
4140 return -EINVAL;
4141 }
4142}
4143
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304144/**
4145 * afe_open -
4146 * command to open AFE port
4147 *
4148 * @port_id: AFE port id
4149 * @afe_config: AFE port config to pass
4150 * @rate: sample rate
4151 *
4152 * Returns 0 on success or error on failure
4153 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304154int afe_open(u16 port_id,
4155 union afe_port_config *afe_config, int rate)
4156{
4157 struct afe_port_cmd_device_start start;
4158 struct afe_audioif_config_command config;
4159 int ret = 0;
4160 int cfg_type;
4161 int index = 0;
4162
4163 if (!afe_config) {
4164 pr_err("%s: Error, no configuration data\n", __func__);
4165 ret = -EINVAL;
4166 return ret;
4167 }
4168
4169 pr_err("%s: port_id 0x%x rate %d\n", __func__, port_id, rate);
4170
4171 index = q6audio_get_port_index(port_id);
4172 if (index < 0 || index >= AFE_MAX_PORTS) {
4173 pr_err("%s: AFE port index[%d] invalid!\n",
4174 __func__, index);
4175 return -EINVAL;
4176 }
4177 ret = q6audio_validate_port(port_id);
4178 if (ret < 0) {
4179 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
4180 return -EINVAL;
4181 }
4182
4183 if ((port_id == RT_PROXY_DAI_001_RX) ||
4184 (port_id == RT_PROXY_DAI_002_TX)) {
4185 pr_err("%s: wrong port 0x%x\n", __func__, port_id);
4186 return -EINVAL;
4187 }
4188 if ((port_id == RT_PROXY_DAI_002_RX) ||
4189 (port_id == RT_PROXY_DAI_001_TX))
4190 port_id = VIRTUAL_ID_TO_PORTID(port_id);
4191
4192 ret = afe_q6_interface_prepare();
4193 if (ret != 0) {
4194 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4195 return -EINVAL;
4196 }
4197
4198 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
4199 this_afe.afe_sample_rates[index] = rate;
4200
4201 if (this_afe.rt_cb)
4202 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
4203 }
4204
4205 /* Also send the topology id here: */
4206 afe_send_custom_topology(); /* One time call: only for first time */
4207 afe_send_port_topology_id(port_id);
4208
4209 ret = q6audio_validate_port(port_id);
4210 if (ret < 0) {
4211 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
4212 __func__, port_id, ret);
4213 return -EINVAL;
4214 }
4215 mutex_lock(&this_afe.afe_cmd_lock);
4216
4217 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4218 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4219 config.hdr.pkt_size = sizeof(config);
4220 config.hdr.src_port = 0;
4221 config.hdr.dest_port = 0;
4222 config.hdr.token = index;
4223 switch (port_id) {
4224 case PRIMARY_I2S_RX:
4225 case PRIMARY_I2S_TX:
4226 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
4227 break;
4228 case AFE_PORT_ID_PRIMARY_PCM_RX:
4229 case AFE_PORT_ID_PRIMARY_PCM_TX:
4230 case AFE_PORT_ID_SECONDARY_PCM_RX:
4231 case AFE_PORT_ID_SECONDARY_PCM_TX:
4232 case AFE_PORT_ID_TERTIARY_PCM_RX:
4233 case AFE_PORT_ID_TERTIARY_PCM_TX:
4234 case AFE_PORT_ID_QUATERNARY_PCM_RX:
4235 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304236 case AFE_PORT_ID_QUINARY_PCM_RX:
4237 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304238 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
4239 break;
4240 case SECONDARY_I2S_RX:
4241 case SECONDARY_I2S_TX:
4242 case AFE_PORT_ID_PRIMARY_MI2S_RX:
4243 case AFE_PORT_ID_PRIMARY_MI2S_TX:
4244 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
4245 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
4246 case MI2S_RX:
4247 case MI2S_TX:
4248 case AFE_PORT_ID_QUINARY_MI2S_RX:
4249 case AFE_PORT_ID_QUINARY_MI2S_TX:
4250 case AFE_PORT_ID_SENARY_MI2S_TX:
4251 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
4252 break;
4253 case HDMI_RX:
4254 case DISPLAY_PORT_RX:
4255 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
4256 break;
4257 case SLIMBUS_0_RX:
4258 case SLIMBUS_0_TX:
4259 case SLIMBUS_1_RX:
4260 case SLIMBUS_1_TX:
4261 case SLIMBUS_2_RX:
4262 case SLIMBUS_2_TX:
4263 case SLIMBUS_3_RX:
4264 case SLIMBUS_3_TX:
4265 case SLIMBUS_4_RX:
4266 case SLIMBUS_4_TX:
4267 case SLIMBUS_5_RX:
4268 case SLIMBUS_6_RX:
4269 case SLIMBUS_6_TX:
4270 case SLIMBUS_7_RX:
4271 case SLIMBUS_7_TX:
4272 case SLIMBUS_8_RX:
4273 case SLIMBUS_8_TX:
4274 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
4275 break;
4276 case AFE_PORT_ID_USB_RX:
4277 case AFE_PORT_ID_USB_TX:
4278 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
4279 break;
4280 default:
4281 pr_err("%s: Invalid port id 0x%x\n",
4282 __func__, port_id);
4283 ret = -EINVAL;
4284 goto fail_cmd;
4285 }
4286 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
4287 config.param.port_id = q6audio_get_port_id(port_id);
4288 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr)
4289 - sizeof(config.param);
4290 config.param.payload_address_lsw = 0x00;
4291 config.param.payload_address_msw = 0x00;
4292 config.param.mem_map_handle = 0x00;
4293 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
4294 config.pdata.param_id = cfg_type;
4295 config.pdata.param_size = sizeof(config.port);
4296
4297 config.port = *afe_config;
4298 pr_debug("%s: param PL size=%d iparam_size[%d][%zd %zd %zd %zd] param_id[0x%x]\n",
4299 __func__, config.param.payload_size, config.pdata.param_size,
4300 sizeof(config), sizeof(config.param), sizeof(config.port),
4301 sizeof(struct apr_hdr), config.pdata.param_id);
4302
4303 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
4304 if (ret) {
4305 pr_err("%s: AFE enable for port 0x%x opcode[0x%x]failed %d\n",
4306 __func__, port_id, cfg_type, ret);
4307 goto fail_cmd;
4308 }
4309 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4310 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4311 start.hdr.pkt_size = sizeof(start);
4312 start.hdr.src_port = 0;
4313 start.hdr.dest_port = 0;
4314 start.hdr.token = index;
4315 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
4316 start.port_id = q6audio_get_port_id(port_id);
4317 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
4318 __func__, start.hdr.opcode, start.port_id);
4319
4320 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
4321 if (ret) {
4322 pr_err("%s: AFE enable for port 0x%x failed %d\n", __func__,
4323 port_id, ret);
4324 goto fail_cmd;
4325 }
4326
4327fail_cmd:
4328 mutex_unlock(&this_afe.afe_cmd_lock);
4329 return ret;
4330}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304331EXPORT_SYMBOL(afe_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304332
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304333/**
4334 * afe_loopback -
4335 * command to set loopback between AFE ports
4336 *
4337 * @enable: enable or disable loopback
4338 * @rx_port: AFE RX port ID
4339 * @tx_port: AFE TX port ID
4340 *
4341 * Returns 0 on success or error on failure
4342 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304343int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
4344{
4345 struct afe_loopback_cfg_v1 lb_cmd;
4346 int ret = 0;
4347 int index = 0;
4348
4349 if (rx_port == MI2S_RX)
4350 rx_port = AFE_PORT_ID_PRIMARY_MI2S_RX;
4351 if (tx_port == MI2S_TX)
4352 tx_port = AFE_PORT_ID_PRIMARY_MI2S_TX;
4353
4354 ret = afe_q6_interface_prepare();
4355 if (ret != 0) {
4356 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4357 return ret;
4358 }
4359
4360 index = q6audio_get_port_index(rx_port);
4361 if (index < 0 || index >= AFE_MAX_PORTS) {
4362 pr_err("%s: AFE port index[%d] invalid!\n",
4363 __func__, index);
4364 return -EINVAL;
4365 }
4366 ret = q6audio_validate_port(rx_port);
4367 if (ret < 0) {
4368 pr_err("%s: Invalid port 0x%x ret %d", __func__, rx_port, ret);
4369 return -EINVAL;
4370 }
4371
4372 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4373 APR_HDR_LEN(20), APR_PKT_VER);
4374 lb_cmd.hdr.pkt_size = sizeof(lb_cmd);
4375 lb_cmd.hdr.src_port = 0;
4376 lb_cmd.hdr.dest_port = 0;
4377 lb_cmd.hdr.token = index;
4378 lb_cmd.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
4379 lb_cmd.param.port_id = tx_port;
4380 lb_cmd.param.payload_size = (sizeof(lb_cmd) - sizeof(struct apr_hdr) -
4381 sizeof(struct afe_port_cmd_set_param_v2));
4382 lb_cmd.param.payload_address_lsw = 0x00;
4383 lb_cmd.param.payload_address_msw = 0x00;
4384 lb_cmd.param.mem_map_handle = 0x00;
4385 lb_cmd.pdata.module_id = AFE_MODULE_LOOPBACK;
4386 lb_cmd.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
4387 lb_cmd.pdata.param_size = lb_cmd.param.payload_size -
4388 sizeof(struct afe_port_param_data_v2);
4389
4390 lb_cmd.dst_port_id = rx_port;
4391 lb_cmd.routing_mode = LB_MODE_DEFAULT;
4392 lb_cmd.enable = (enable ? 1 : 0);
4393 lb_cmd.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
4394
4395 ret = afe_apr_send_pkt(&lb_cmd, &this_afe.wait[index]);
4396 if (ret)
4397 pr_err("%s: AFE loopback failed %d\n", __func__, ret);
4398 return ret;
4399}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304400EXPORT_SYMBOL(afe_loopback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304401
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304402/**
4403 * afe_loopback_gain -
4404 * command to set gain for AFE loopback
4405 *
4406 * @port_id: AFE port id
4407 * @volume: gain value to set
4408 *
4409 * Returns 0 on success or error on failure
4410 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304411int afe_loopback_gain(u16 port_id, u16 volume)
4412{
4413 struct afe_loopback_gain_per_path_param set_param;
4414 int ret = 0;
4415 int index = 0;
4416
4417 if (this_afe.apr == NULL) {
4418 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4419 0xFFFFFFFF, &this_afe);
4420 pr_debug("%s: Register AFE\n", __func__);
4421 if (this_afe.apr == NULL) {
4422 pr_err("%s: Unable to register AFE\n", __func__);
4423 ret = -ENODEV;
4424 return ret;
4425 }
4426 rtac_set_afe_handle(this_afe.apr);
4427 }
4428
4429 ret = q6audio_validate_port(port_id);
4430 if (ret < 0) {
4431 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
4432 __func__, port_id, ret);
4433 ret = -EINVAL;
4434 goto fail_cmd;
4435 }
4436 index = q6audio_get_port_index(port_id);
4437 if (index < 0 || index >= AFE_MAX_PORTS) {
4438 pr_err("%s: AFE port index[%d] invalid!\n",
4439 __func__, index);
4440 return -EINVAL;
4441 }
4442 ret = q6audio_validate_port(port_id);
4443 if (ret < 0) {
4444 pr_err("%s: Invalid port 0x%x ret %d",
4445 __func__, port_id, ret);
4446 return -EINVAL;
4447 }
4448
4449 /* RX ports numbers are even .TX ports numbers are odd. */
4450 if (port_id % 2 == 0) {
4451 pr_err("%s: Failed : afe loopback gain only for TX ports. port_id %d\n",
4452 __func__, port_id);
4453 ret = -EINVAL;
4454 goto fail_cmd;
4455 }
4456
4457 pr_debug("%s: port 0x%x volume %d\n", __func__, port_id, volume);
4458
4459 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4460 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4461 set_param.hdr.pkt_size = sizeof(set_param);
4462 set_param.hdr.src_port = 0;
4463 set_param.hdr.dest_port = 0;
4464 set_param.hdr.token = index;
4465 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
4466
4467 set_param.param.port_id = port_id;
4468 set_param.param.payload_size =
4469 (sizeof(struct afe_loopback_gain_per_path_param) -
4470 sizeof(struct apr_hdr) - sizeof(struct afe_port_cmd_set_param_v2));
4471 set_param.param.payload_address_lsw = 0;
4472 set_param.param.payload_address_msw = 0;
4473 set_param.param.mem_map_handle = 0;
4474
4475 set_param.pdata.module_id = AFE_MODULE_LOOPBACK;
4476 set_param.pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
4477 set_param.pdata.param_size =
4478 (set_param.param.payload_size -
4479 sizeof(struct afe_port_param_data_v2));
4480 set_param.rx_port_id = port_id;
4481 set_param.gain = volume;
4482
4483 ret = afe_apr_send_pkt(&set_param, &this_afe.wait[index]);
4484 if (ret) {
4485 pr_err("%s: AFE param set failed for port 0x%x ret %d\n",
4486 __func__, port_id, ret);
4487 goto fail_cmd;
4488 }
4489
4490fail_cmd:
4491 return ret;
4492}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304493EXPORT_SYMBOL(afe_loopback_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304494
4495int afe_pseudo_port_start_nowait(u16 port_id)
4496{
4497 struct afe_pseudoport_start_command start;
4498 int ret = 0;
4499
4500 pr_debug("%s: port_id=0x%x\n", __func__, port_id);
4501 if (this_afe.apr == NULL) {
4502 pr_err("%s: AFE APR is not registered\n", __func__);
4503 return -ENODEV;
4504 }
4505
4506
4507 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4508 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4509 start.hdr.pkt_size = sizeof(start);
4510 start.hdr.src_port = 0;
4511 start.hdr.dest_port = 0;
4512 start.hdr.token = 0;
4513 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
4514 start.port_id = port_id;
4515 start.timing = 1;
4516
4517 ret = afe_apr_send_pkt(&start, NULL);
4518 if (ret) {
4519 pr_err("%s: AFE enable for port 0x%x failed %d\n",
4520 __func__, port_id, ret);
4521 return ret;
4522 }
4523 return 0;
4524}
4525
4526int afe_start_pseudo_port(u16 port_id)
4527{
4528 int ret = 0;
4529 struct afe_pseudoport_start_command start;
4530 int index = 0;
4531
4532 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4533
4534 ret = afe_q6_interface_prepare();
4535 if (ret != 0) {
4536 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4537 return ret;
4538 }
4539
4540 index = q6audio_get_port_index(port_id);
4541 if (index < 0 || index >= AFE_MAX_PORTS) {
4542 pr_err("%s: AFE port index[%d] invalid!\n",
4543 __func__, index);
4544 return -EINVAL;
4545 }
4546 ret = q6audio_validate_port(port_id);
4547 if (ret < 0) {
4548 pr_err("%s: Invalid port 0x%x ret %d",
4549 __func__, port_id, ret);
4550 return -EINVAL;
4551 }
4552
4553 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4554 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4555 start.hdr.pkt_size = sizeof(start);
4556 start.hdr.src_port = 0;
4557 start.hdr.dest_port = 0;
4558 start.hdr.token = 0;
4559 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
4560 start.port_id = port_id;
4561 start.timing = 1;
4562 start.hdr.token = index;
4563
4564 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
4565 if (ret)
4566 pr_err("%s: AFE enable for port 0x%x failed %d\n",
4567 __func__, port_id, ret);
4568 return ret;
4569}
4570
4571int afe_pseudo_port_stop_nowait(u16 port_id)
4572{
4573 int ret = 0;
4574 struct afe_pseudoport_stop_command stop;
4575 int index = 0;
4576
4577 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4578
4579 if (this_afe.apr == NULL) {
4580 pr_err("%s: AFE is already closed\n", __func__);
4581 return -EINVAL;
4582 }
4583 index = q6audio_get_port_index(port_id);
4584 if (index < 0 || index >= AFE_MAX_PORTS) {
4585 pr_err("%s: AFE port index[%d] invalid!\n",
4586 __func__, index);
4587 return -EINVAL;
4588 }
4589 ret = q6audio_validate_port(port_id);
4590 if (ret < 0) {
4591 pr_err("%s: Invalid port 0x%x ret %d",
4592 __func__, port_id, ret);
4593 return -EINVAL;
4594 }
4595
4596 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4597 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4598 stop.hdr.pkt_size = sizeof(stop);
4599 stop.hdr.src_port = 0;
4600 stop.hdr.dest_port = 0;
4601 stop.hdr.token = 0;
4602 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
4603 stop.port_id = port_id;
4604 stop.reserved = 0;
4605 stop.hdr.token = index;
4606
4607 ret = afe_apr_send_pkt(&stop, NULL);
4608 if (ret)
4609 pr_err("%s: AFE close failed %d\n", __func__, ret);
4610
4611 return ret;
4612}
4613
4614int afe_port_group_set_param(u16 group_id,
4615 union afe_port_group_config *afe_group_config)
4616{
4617 int ret;
4618 struct afe_port_group_create config;
4619 int cfg_type;
4620
4621 if (!afe_group_config) {
4622 pr_err("%s: Error, no configuration data\n", __func__);
4623 return -EINVAL;
4624 }
4625
4626 pr_debug("%s: group id: 0x%x\n", __func__, group_id);
4627
4628 ret = afe_q6_interface_prepare();
4629 if (ret != 0) {
4630 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4631 return ret;
4632 }
4633
4634 switch (group_id) {
4635 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX:
4636 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX:
4637 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_RX:
4638 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_TX:
4639 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_RX:
4640 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_TX:
4641 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_RX:
4642 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304643 case AFE_GROUP_DEVICE_ID_QUINARY_TDM_RX:
4644 case AFE_GROUP_DEVICE_ID_QUINARY_TDM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304645 cfg_type = AFE_PARAM_ID_GROUP_DEVICE_TDM_CONFIG;
4646 break;
4647 default:
4648 pr_err("%s: Invalid group id 0x%x\n", __func__, group_id);
4649 return -EINVAL;
4650 }
4651
4652 memset(&config, 0, sizeof(config));
4653 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4654 APR_HDR_LEN(APR_HDR_SIZE),
4655 APR_PKT_VER);
4656 config.hdr.pkt_size = sizeof(config);
4657 config.hdr.src_port = 0;
4658 config.hdr.dest_port = 0;
4659 config.hdr.token = IDX_GLOBAL_CFG;
4660 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
4661
4662 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
4663 sizeof(config.param);
4664 config.param.payload_address_lsw = 0x00;
4665 config.param.payload_address_msw = 0x00;
4666 config.param.mem_map_handle = 0x00;
4667 config.pdata.module_id = AFE_MODULE_GROUP_DEVICE;
4668 config.pdata.param_id = cfg_type;
4669 config.pdata.param_size = sizeof(config.data);
4670 config.data = *afe_group_config;
4671
4672 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
4673 if (ret)
4674 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_CFG failed %d\n",
4675 __func__, ret);
4676
4677 return ret;
4678}
4679
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304680/**
4681 * afe_port_group_enable -
4682 * command to enable AFE port group
4683 *
4684 * @group_id: group ID for AFE port group
4685 * @afe_group_config: config for AFE group
4686 * @enable: flag to indicate enable or disable
4687 *
4688 * Returns 0 on success or error on failure
4689 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304690int afe_port_group_enable(u16 group_id,
4691 union afe_port_group_config *afe_group_config,
4692 u16 enable)
4693{
4694 int ret;
4695 struct afe_port_group_create config;
4696
4697 pr_debug("%s: group id: 0x%x enable: %d\n", __func__,
4698 group_id, enable);
4699
4700 ret = afe_q6_interface_prepare();
4701 if (ret != 0) {
4702 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4703 return ret;
4704 }
4705
4706 if (enable) {
4707 ret = afe_port_group_set_param(group_id, afe_group_config);
4708 if (ret < 0) {
4709 pr_err("%s: afe send failed %d\n", __func__, ret);
4710 return ret;
4711 }
4712 }
4713
4714 memset(&config, 0, sizeof(config));
4715 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4716 APR_HDR_LEN(APR_HDR_SIZE),
4717 APR_PKT_VER);
4718 config.hdr.pkt_size = sizeof(config);
4719 config.hdr.src_port = 0;
4720 config.hdr.dest_port = 0;
4721 config.hdr.token = IDX_GLOBAL_CFG;
4722 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
4723
4724 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
4725 sizeof(config.param);
4726 config.param.payload_address_lsw = 0x00;
4727 config.param.payload_address_msw = 0x00;
4728 config.param.mem_map_handle = 0x00;
4729 config.pdata.module_id = AFE_MODULE_GROUP_DEVICE;
4730 config.pdata.param_id = AFE_PARAM_ID_GROUP_DEVICE_ENABLE;
4731 config.pdata.param_size = sizeof(config.data);
4732 config.data.group_enable.group_id = group_id;
4733 config.data.group_enable.enable = enable;
4734
4735 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
4736 if (ret)
4737 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_ENABLE failed %d\n",
4738 __func__, ret);
4739
4740 return ret;
4741}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304742EXPORT_SYMBOL(afe_port_group_enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304743
4744int afe_stop_pseudo_port(u16 port_id)
4745{
4746 int ret = 0;
4747 struct afe_pseudoport_stop_command stop;
4748 int index = 0;
4749
4750 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4751
4752 if (this_afe.apr == NULL) {
4753 pr_err("%s: AFE is already closed\n", __func__);
4754 return -EINVAL;
4755 }
4756
4757 index = q6audio_get_port_index(port_id);
4758 if (index < 0 || index >= AFE_MAX_PORTS) {
4759 pr_err("%s: AFE port index[%d] invalid!\n",
4760 __func__, index);
4761 return -EINVAL;
4762 }
4763 ret = q6audio_validate_port(port_id);
4764 if (ret < 0) {
4765 pr_err("%s: Invalid port 0x%x ret %d\n",
4766 __func__, port_id, ret);
4767 return -EINVAL;
4768 }
4769
4770 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4771 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4772 stop.hdr.pkt_size = sizeof(stop);
4773 stop.hdr.src_port = 0;
4774 stop.hdr.dest_port = 0;
4775 stop.hdr.token = 0;
4776 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
4777 stop.port_id = port_id;
4778 stop.reserved = 0;
4779 stop.hdr.token = index;
4780
4781 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
4782 if (ret)
4783 pr_err("%s: AFE close failed %d\n", __func__, ret);
4784
4785 return ret;
4786}
4787
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304788/**
4789 * afe_req_mmap_handle -
4790 * Retrieve AFE memory map handle
4791 *
4792 * @ac: AFE audio client
4793 *
4794 * Returns memory map handle
4795 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304796uint32_t afe_req_mmap_handle(struct afe_audio_client *ac)
4797{
4798 return ac->mem_map_handle;
4799}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304800EXPORT_SYMBOL(afe_req_mmap_handle);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304801
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304802/**
4803 * q6afe_audio_client_alloc -
4804 * Assign new AFE audio client
4805 *
4806 * @priv: privata data to hold for audio client
4807 *
4808 * Returns ac pointer on success or NULL on failure
4809 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304810struct afe_audio_client *q6afe_audio_client_alloc(void *priv)
4811{
4812 struct afe_audio_client *ac;
4813 int lcnt = 0;
4814
4815 ac = kzalloc(sizeof(struct afe_audio_client), GFP_KERNEL);
4816 if (!ac)
4817 return NULL;
4818
4819 ac->priv = priv;
4820
4821 init_waitqueue_head(&ac->cmd_wait);
4822 INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
4823 INIT_LIST_HEAD(&ac->port[1].mem_map_handle);
4824 pr_debug("%s: mem_map_handle list init'ed\n", __func__);
4825 mutex_init(&ac->cmd_lock);
4826 for (lcnt = 0; lcnt <= OUT; lcnt++) {
4827 mutex_init(&ac->port[lcnt].lock);
4828 spin_lock_init(&ac->port[lcnt].dsp_lock);
4829 }
4830 atomic_set(&ac->cmd_state, 0);
4831
4832 return ac;
4833}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304834EXPORT_SYMBOL(q6afe_audio_client_alloc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304835
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304836/**
4837 * q6afe_audio_client_buf_alloc_contiguous -
4838 * Allocate contiguous shared buffers
4839 *
4840 * @dir: RX or TX direction of AFE port
4841 * @ac: AFE audio client handle
4842 * @bufsz: size of each shared buffer
4843 * @bufcnt: number of buffers
4844 *
4845 * Returns 0 on success or error on failure
4846 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304847int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir,
4848 struct afe_audio_client *ac,
4849 unsigned int bufsz,
4850 unsigned int bufcnt)
4851{
4852 int cnt = 0;
4853 int rc = 0;
4854 struct afe_audio_buffer *buf;
4855 size_t len;
4856
4857 if (!(ac) || ((dir != IN) && (dir != OUT))) {
4858 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
4859 return -EINVAL;
4860 }
4861
4862 pr_debug("%s: bufsz[%d]bufcnt[%d]\n",
4863 __func__,
4864 bufsz, bufcnt);
4865
4866 if (ac->port[dir].buf) {
4867 pr_debug("%s: buffer already allocated\n", __func__);
4868 return 0;
4869 }
4870 mutex_lock(&ac->cmd_lock);
4871 buf = kzalloc(((sizeof(struct afe_audio_buffer))*bufcnt),
4872 GFP_KERNEL);
4873
4874 if (!buf) {
4875 pr_err("%s: null buf\n", __func__);
4876 mutex_unlock(&ac->cmd_lock);
4877 goto fail;
4878 }
4879
4880 ac->port[dir].buf = buf;
4881
4882 rc = msm_audio_ion_alloc("afe_client", &buf[0].client,
4883 &buf[0].handle, bufsz*bufcnt,
4884 &buf[0].phys, &len,
4885 &buf[0].data);
4886 if (rc) {
4887 pr_err("%s: audio ION alloc failed, rc = %d\n",
4888 __func__, rc);
4889 mutex_unlock(&ac->cmd_lock);
4890 goto fail;
4891 }
4892
4893 buf[0].used = dir ^ 1;
4894 buf[0].size = bufsz;
4895 buf[0].actual_size = bufsz;
4896 cnt = 1;
4897 while (cnt < bufcnt) {
4898 if (bufsz > 0) {
4899 buf[cnt].data = buf[0].data + (cnt * bufsz);
4900 buf[cnt].phys = buf[0].phys + (cnt * bufsz);
4901 if (!buf[cnt].data) {
4902 pr_err("%s: Buf alloc failed\n",
4903 __func__);
4904 mutex_unlock(&ac->cmd_lock);
4905 goto fail;
4906 }
4907 buf[cnt].used = dir ^ 1;
4908 buf[cnt].size = bufsz;
4909 buf[cnt].actual_size = bufsz;
4910 pr_debug("%s: data[%pK]phys[%pK][%pK]\n", __func__,
4911 buf[cnt].data,
4912 &buf[cnt].phys,
4913 &buf[cnt].phys);
4914 }
4915 cnt++;
4916 }
4917 ac->port[dir].max_buf_cnt = cnt;
4918 mutex_unlock(&ac->cmd_lock);
4919 return 0;
4920fail:
4921 pr_err("%s: jump fail\n", __func__);
4922 q6afe_audio_client_buf_free_contiguous(dir, ac);
4923 return -EINVAL;
4924}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304925EXPORT_SYMBOL(q6afe_audio_client_buf_alloc_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304926
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304927/**
4928 * afe_memory_map -
4929 * command to map shared buffers to AFE
4930 *
4931 * @dma_addr_p: DMA physical address
4932 * @dma_buf_sz: shared DMA buffer size
4933 * @ac: AFE audio client handle
4934 *
4935 * Returns 0 on success or error on failure
4936 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304937int afe_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz,
4938 struct afe_audio_client *ac)
4939{
4940 int ret = 0;
4941
4942 mutex_lock(&this_afe.afe_cmd_lock);
4943 ac->mem_map_handle = 0;
4944 ret = afe_cmd_memory_map(dma_addr_p, dma_buf_sz);
4945 if (ret < 0) {
4946 pr_err("%s: afe_cmd_memory_map failed %d\n",
4947 __func__, ret);
4948
4949 mutex_unlock(&this_afe.afe_cmd_lock);
4950 return ret;
4951 }
4952 ac->mem_map_handle = this_afe.mmap_handle;
4953 mutex_unlock(&this_afe.afe_cmd_lock);
4954
4955 return ret;
4956}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304957EXPORT_SYMBOL(afe_memory_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304958
4959int afe_cmd_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz)
4960{
4961 int ret = 0;
4962 int cmd_size = 0;
4963 void *payload = NULL;
4964 void *mmap_region_cmd = NULL;
4965 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
4966 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
4967 int index = 0;
4968
4969 pr_debug("%s:\n", __func__);
4970
4971 if (this_afe.apr == NULL) {
4972 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4973 0xFFFFFFFF, &this_afe);
4974 pr_debug("%s: Register AFE\n", __func__);
4975 if (this_afe.apr == NULL) {
4976 pr_err("%s: Unable to register AFE\n", __func__);
4977 ret = -ENODEV;
4978 return ret;
4979 }
4980 rtac_set_afe_handle(this_afe.apr);
4981 }
4982 if (dma_buf_sz % SZ_4K != 0) {
4983 /*
4984 * The memory allocated by msm_audio_ion_alloc is always 4kB
4985 * aligned, ADSP expects the size to be 4kB aligned as well
4986 * so re-adjusts the buffer size before passing to ADSP.
4987 */
4988 dma_buf_sz = PAGE_ALIGN(dma_buf_sz);
4989 }
4990
4991 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
4992 + sizeof(struct afe_service_shared_map_region_payload);
4993
4994 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
4995 if (!mmap_region_cmd)
4996 return -ENOMEM;
4997
4998 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
4999 mmap_region_cmd;
5000 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5001 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5002 mregion->hdr.pkt_size = cmd_size;
5003 mregion->hdr.src_port = 0;
5004 mregion->hdr.dest_port = 0;
5005 mregion->hdr.token = 0;
5006 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
5007 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
5008 mregion->num_regions = 1;
5009 mregion->property_flag = 0x00;
5010 /* Todo */
5011 index = mregion->hdr.token = IDX_RSVD_2;
5012
5013 payload = ((u8 *) mmap_region_cmd +
5014 sizeof(struct afe_service_cmd_shared_mem_map_regions));
5015
5016 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
5017
5018 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
5019 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
5020 mregion_pl->mem_size_bytes = dma_buf_sz;
5021
5022 pr_debug("%s: dma_addr_p 0x%pK , size %d\n", __func__,
5023 &dma_addr_p, dma_buf_sz);
5024 atomic_set(&this_afe.state, 1);
5025 atomic_set(&this_afe.status, 0);
5026 this_afe.mmap_handle = 0;
5027 ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
5028 if (ret < 0) {
5029 pr_err("%s: AFE memory map cmd failed %d\n",
5030 __func__, ret);
5031 ret = -EINVAL;
5032 goto fail_cmd;
5033 }
5034
5035 ret = wait_event_timeout(this_afe.wait[index],
5036 (atomic_read(&this_afe.state) == 0),
5037 msecs_to_jiffies(TIMEOUT_MS));
5038 if (!ret) {
5039 pr_err("%s: wait_event timeout\n", __func__);
5040 ret = -EINVAL;
5041 goto fail_cmd;
5042 }
5043 if (atomic_read(&this_afe.status) > 0) {
5044 pr_err("%s: config cmd failed [%s]\n",
5045 __func__, adsp_err_get_err_str(
5046 atomic_read(&this_afe.status)));
5047 ret = adsp_err_get_lnx_err_code(
5048 atomic_read(&this_afe.status));
5049 goto fail_cmd;
5050 }
5051
5052 kfree(mmap_region_cmd);
5053 return 0;
5054fail_cmd:
5055 kfree(mmap_region_cmd);
5056 pr_err("%s: fail_cmd\n", __func__);
5057 return ret;
5058}
5059
5060int afe_cmd_memory_map_nowait(int port_id, phys_addr_t dma_addr_p,
5061 u32 dma_buf_sz)
5062{
5063 int ret = 0;
5064 int cmd_size = 0;
5065 void *payload = NULL;
5066 void *mmap_region_cmd = NULL;
5067 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
5068 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
5069 int index = 0;
5070
5071 pr_debug("%s:\n", __func__);
5072
5073 if (this_afe.apr == NULL) {
5074 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5075 0xFFFFFFFF, &this_afe);
5076 pr_debug("%s: Register AFE\n", __func__);
5077 if (this_afe.apr == NULL) {
5078 pr_err("%s: Unable to register AFE\n", __func__);
5079 ret = -ENODEV;
5080 return ret;
5081 }
5082 rtac_set_afe_handle(this_afe.apr);
5083 }
5084 index = q6audio_get_port_index(port_id);
5085 if (index < 0 || index >= AFE_MAX_PORTS) {
5086 pr_err("%s: AFE port index[%d] invalid!\n",
5087 __func__, index);
5088 return -EINVAL;
5089 }
5090 ret = q6audio_validate_port(port_id);
5091 if (ret < 0) {
5092 pr_err("%s: Invalid port 0x%x ret %d",
5093 __func__, port_id, ret);
5094 return -EINVAL;
5095 }
5096
5097 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
5098 + sizeof(struct afe_service_shared_map_region_payload);
5099
5100 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
5101 if (!mmap_region_cmd)
5102 return -ENOMEM;
5103
5104 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
5105 mmap_region_cmd;
5106 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5107 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5108 mregion->hdr.pkt_size = sizeof(mregion);
5109 mregion->hdr.src_port = 0;
5110 mregion->hdr.dest_port = 0;
5111 mregion->hdr.token = 0;
5112 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
5113 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
5114 mregion->num_regions = 1;
5115 mregion->property_flag = 0x00;
5116
5117 payload = ((u8 *) mmap_region_cmd +
5118 sizeof(struct afe_service_cmd_shared_mem_map_regions));
5119 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
5120
5121 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
5122 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
5123 mregion_pl->mem_size_bytes = dma_buf_sz;
5124
5125 ret = afe_apr_send_pkt(mmap_region_cmd, NULL);
5126 if (ret)
5127 pr_err("%s: AFE memory map cmd failed %d\n",
5128 __func__, ret);
5129 kfree(mmap_region_cmd);
5130 return ret;
5131}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305132
5133/**
5134 * q6afe_audio_client_buf_free_contiguous -
5135 * frees the shared contiguous memory
5136 *
5137 * @dir: RX or TX direction of port
5138 * @ac: AFE audio client handle
5139 *
5140 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305141int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
5142 struct afe_audio_client *ac)
5143{
5144 struct afe_audio_port_data *port;
5145 int cnt = 0;
5146
5147 mutex_lock(&ac->cmd_lock);
5148 port = &ac->port[dir];
5149 if (!port->buf) {
5150 pr_err("%s: buf is null\n", __func__);
5151 mutex_unlock(&ac->cmd_lock);
5152 return 0;
5153 }
5154 cnt = port->max_buf_cnt - 1;
5155
5156 if (port->buf[0].data) {
5157 pr_debug("%s: data[%pK]phys[%pK][%pK] , client[%pK] handle[%pK]\n",
5158 __func__,
5159 port->buf[0].data,
5160 &port->buf[0].phys,
5161 &port->buf[0].phys,
5162 port->buf[0].client,
5163 port->buf[0].handle);
5164 msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
5165 port->buf[0].client = NULL;
5166 port->buf[0].handle = NULL;
5167 }
5168
5169 while (cnt >= 0) {
5170 port->buf[cnt].data = NULL;
5171 port->buf[cnt].phys = 0;
5172 cnt--;
5173 }
5174 port->max_buf_cnt = 0;
5175 kfree(port->buf);
5176 port->buf = NULL;
5177 mutex_unlock(&ac->cmd_lock);
5178 return 0;
5179}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305180EXPORT_SYMBOL(q6afe_audio_client_buf_free_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305181
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305182/**
5183 * q6afe_audio_client_free -
5184 * frees the audio client from AFE
5185 *
5186 * @ac: AFE audio client handle
5187 *
5188 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305189void q6afe_audio_client_free(struct afe_audio_client *ac)
5190{
5191 int loopcnt;
5192 struct afe_audio_port_data *port;
5193
5194 if (!ac) {
5195 pr_err("%s: audio client is NULL\n", __func__);
5196 return;
5197 }
5198 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
5199 port = &ac->port[loopcnt];
5200 if (!port->buf)
5201 continue;
5202 pr_debug("%s: loopcnt = %d\n", __func__, loopcnt);
5203 q6afe_audio_client_buf_free_contiguous(loopcnt, ac);
5204 }
5205 kfree(ac);
5206}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305207EXPORT_SYMBOL(q6afe_audio_client_free);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305208
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305209/**
5210 * afe_cmd_memory_unmap -
5211 * command to unmap memory for AFE shared buffer
5212 *
5213 * @mem_map_handle: memory map handle to be unmapped
5214 *
5215 * Returns 0 on success or error on failure
5216 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305217int afe_cmd_memory_unmap(u32 mem_map_handle)
5218{
5219 int ret = 0;
5220 struct afe_service_cmd_shared_mem_unmap_regions mregion;
5221 int index = 0;
5222
5223 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
5224
5225 if (this_afe.apr == NULL) {
5226 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5227 0xFFFFFFFF, &this_afe);
5228 pr_debug("%s: Register AFE\n", __func__);
5229 if (this_afe.apr == NULL) {
5230 pr_err("%s: Unable to register AFE\n", __func__);
5231 ret = -ENODEV;
5232 return ret;
5233 }
5234 rtac_set_afe_handle(this_afe.apr);
5235 }
5236
5237 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5238 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5239 mregion.hdr.pkt_size = sizeof(mregion);
5240 mregion.hdr.src_port = 0;
5241 mregion.hdr.dest_port = 0;
5242 mregion.hdr.token = 0;
5243 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
5244 mregion.mem_map_handle = mem_map_handle;
5245
5246 /* Todo */
5247 index = mregion.hdr.token = IDX_RSVD_2;
5248
5249 atomic_set(&this_afe.status, 0);
5250 ret = afe_apr_send_pkt(&mregion, &this_afe.wait[index]);
5251 if (ret)
5252 pr_err("%s: AFE memory unmap cmd failed %d\n",
5253 __func__, ret);
5254
5255 return ret;
5256}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305257EXPORT_SYMBOL(afe_cmd_memory_unmap);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305258
5259int afe_cmd_memory_unmap_nowait(u32 mem_map_handle)
5260{
5261 int ret = 0;
5262 struct afe_service_cmd_shared_mem_unmap_regions mregion;
5263
5264 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
5265
5266 if (this_afe.apr == NULL) {
5267 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5268 0xFFFFFFFF, &this_afe);
5269 pr_debug("%s: Register AFE\n", __func__);
5270 if (this_afe.apr == NULL) {
5271 pr_err("%s: Unable to register AFE\n", __func__);
5272 ret = -ENODEV;
5273 return ret;
5274 }
5275 rtac_set_afe_handle(this_afe.apr);
5276 }
5277
5278 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5279 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5280 mregion.hdr.pkt_size = sizeof(mregion);
5281 mregion.hdr.src_port = 0;
5282 mregion.hdr.dest_port = 0;
5283 mregion.hdr.token = 0;
5284 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
5285 mregion.mem_map_handle = mem_map_handle;
5286
5287 ret = afe_apr_send_pkt(&mregion, NULL);
5288 if (ret)
5289 pr_err("%s: AFE memory unmap cmd failed %d\n",
5290 __func__, ret);
5291 return ret;
5292}
5293
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305294/**
5295 * afe_register_get_events -
5296 * register for events from proxy port
5297 *
5298 * @port_id: Port ID to register events
5299 * @cb: callback function to invoke for events from proxy port
5300 * @private_data: private data to sent back in callback fn
5301 *
5302 * Returns 0 on success or error on failure
5303 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305304int afe_register_get_events(u16 port_id,
5305 void (*cb)(uint32_t opcode,
5306 uint32_t token, uint32_t *payload, void *priv),
5307 void *private_data)
5308{
5309 int ret = 0;
5310 struct afe_service_cmd_register_rt_port_driver rtproxy;
5311
5312 pr_debug("%s: port_id: 0x%x\n", __func__, port_id);
5313
5314 if (this_afe.apr == NULL) {
5315 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5316 0xFFFFFFFF, &this_afe);
5317 pr_debug("%s: Register AFE\n", __func__);
5318 if (this_afe.apr == NULL) {
5319 pr_err("%s: Unable to register AFE\n", __func__);
5320 ret = -ENODEV;
5321 return ret;
5322 }
5323 rtac_set_afe_handle(this_afe.apr);
5324 }
5325 if ((port_id == RT_PROXY_DAI_002_RX) ||
5326 (port_id == RT_PROXY_DAI_001_TX)) {
5327 port_id = VIRTUAL_ID_TO_PORTID(port_id);
5328 } else {
5329 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
5330 return -EINVAL;
5331 }
5332
5333 if (port_id == RT_PROXY_PORT_001_TX) {
5334 this_afe.tx_cb = cb;
5335 this_afe.tx_private_data = private_data;
5336 } else if (port_id == RT_PROXY_PORT_001_RX) {
5337 this_afe.rx_cb = cb;
5338 this_afe.rx_private_data = private_data;
5339 }
5340
5341 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5342 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5343 rtproxy.hdr.pkt_size = sizeof(rtproxy);
5344 rtproxy.hdr.src_port = 1;
5345 rtproxy.hdr.dest_port = 1;
5346 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER;
5347 rtproxy.port_id = port_id;
5348 rtproxy.reserved = 0;
5349
5350 ret = afe_apr_send_pkt(&rtproxy, NULL);
5351 if (ret)
5352 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
5353 __func__, ret);
5354 return ret;
5355}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305356EXPORT_SYMBOL(afe_register_get_events);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305357
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305358/**
5359 * afe_unregister_get_events -
5360 * unregister for events from proxy port
5361 *
5362 * @port_id: Port ID to unregister events
5363 *
5364 * Returns 0 on success or error on failure
5365 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305366int afe_unregister_get_events(u16 port_id)
5367{
5368 int ret = 0;
5369 struct afe_service_cmd_unregister_rt_port_driver rtproxy;
5370 int index = 0;
5371
5372 pr_debug("%s:\n", __func__);
5373
5374 if (this_afe.apr == NULL) {
5375 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5376 0xFFFFFFFF, &this_afe);
5377 pr_debug("%s: Register AFE\n", __func__);
5378 if (this_afe.apr == NULL) {
5379 pr_err("%s: Unable to register AFE\n", __func__);
5380 ret = -ENODEV;
5381 return ret;
5382 }
5383 rtac_set_afe_handle(this_afe.apr);
5384 }
5385
5386 if ((port_id == RT_PROXY_DAI_002_RX) ||
5387 (port_id == RT_PROXY_DAI_001_TX)) {
5388 port_id = VIRTUAL_ID_TO_PORTID(port_id);
5389 } else {
5390 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
5391 return -EINVAL;
5392 }
5393
5394 index = q6audio_get_port_index(port_id);
5395 if (index < 0 || index >= AFE_MAX_PORTS) {
5396 pr_err("%s: AFE port index[%d] invalid!\n",
5397 __func__, index);
5398 return -EINVAL;
5399 }
5400 ret = q6audio_validate_port(port_id);
5401 if (ret < 0) {
5402 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
5403 return -EINVAL;
5404 }
5405
5406 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5407 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5408 rtproxy.hdr.pkt_size = sizeof(rtproxy);
5409 rtproxy.hdr.src_port = 0;
5410 rtproxy.hdr.dest_port = 0;
5411 rtproxy.hdr.token = 0;
5412 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER;
5413 rtproxy.port_id = port_id;
5414 rtproxy.reserved = 0;
5415
5416 rtproxy.hdr.token = index;
5417
5418 if (port_id == RT_PROXY_PORT_001_TX) {
5419 this_afe.tx_cb = NULL;
5420 this_afe.tx_private_data = NULL;
5421 } else if (port_id == RT_PROXY_PORT_001_RX) {
5422 this_afe.rx_cb = NULL;
5423 this_afe.rx_private_data = NULL;
5424 }
5425
5426 ret = afe_apr_send_pkt(&rtproxy, &this_afe.wait[index]);
5427 if (ret)
5428 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
5429 __func__, ret);
5430 return ret;
5431}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305432EXPORT_SYMBOL(afe_unregister_get_events);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305433
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305434/**
5435 * afe_rt_proxy_port_write -
5436 * command for AFE RT proxy port write
5437 *
5438 * @buf_addr_p: Physical buffer address with
5439 * playback data to proxy port
5440 * @mem_map_handle: memory map handle of write buffer
5441 * @bytes: number of bytes to write
5442 *
5443 * Returns 0 on success or error on failure
5444 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305445int afe_rt_proxy_port_write(phys_addr_t buf_addr_p,
5446 u32 mem_map_handle, int bytes)
5447{
5448 int ret = 0;
5449 struct afe_port_data_cmd_rt_proxy_port_write_v2 afecmd_wr;
5450
5451 if (this_afe.apr == NULL) {
5452 pr_err("%s: register to AFE is not done\n", __func__);
5453 ret = -ENODEV;
5454 return ret;
5455 }
5456 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
5457 &buf_addr_p, bytes);
5458
5459 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5460 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5461 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
5462 afecmd_wr.hdr.src_port = 0;
5463 afecmd_wr.hdr.dest_port = 0;
5464 afecmd_wr.hdr.token = 0;
5465 afecmd_wr.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2;
5466 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
5467 afecmd_wr.buffer_address_lsw = lower_32_bits(buf_addr_p);
5468 afecmd_wr.buffer_address_msw =
5469 msm_audio_populate_upper_32_bits(buf_addr_p);
5470 afecmd_wr.mem_map_handle = mem_map_handle;
5471 afecmd_wr.available_bytes = bytes;
5472 afecmd_wr.reserved = 0;
5473
5474 ret = afe_apr_send_pkt(&afecmd_wr, NULL);
5475 if (ret)
5476 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
5477 __func__, afecmd_wr.port_id, ret);
5478 return ret;
5479
5480}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305481EXPORT_SYMBOL(afe_rt_proxy_port_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305482
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305483/**
5484 * afe_rt_proxy_port_read -
5485 * command for AFE RT proxy port read
5486 *
5487 * @buf_addr_p: Physical buffer address to fill read data
5488 * @mem_map_handle: memory map handle for buffer read
5489 * @bytes: number of bytes to read
5490 *
5491 * Returns 0 on success or error on failure
5492 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305493int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
5494 u32 mem_map_handle, int bytes)
5495{
5496 int ret = 0;
5497 struct afe_port_data_cmd_rt_proxy_port_read_v2 afecmd_rd;
5498
5499 if (this_afe.apr == NULL) {
5500 pr_err("%s: register to AFE is not done\n", __func__);
5501 ret = -ENODEV;
5502 return ret;
5503 }
5504 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
5505 &buf_addr_p, bytes);
5506
5507 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5508 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5509 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
5510 afecmd_rd.hdr.src_port = 0;
5511 afecmd_rd.hdr.dest_port = 0;
5512 afecmd_rd.hdr.token = 0;
5513 afecmd_rd.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2;
5514 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
5515 afecmd_rd.buffer_address_lsw = lower_32_bits(buf_addr_p);
5516 afecmd_rd.buffer_address_msw =
5517 msm_audio_populate_upper_32_bits(buf_addr_p);
5518 afecmd_rd.available_bytes = bytes;
5519 afecmd_rd.mem_map_handle = mem_map_handle;
5520
5521 ret = afe_apr_send_pkt(&afecmd_rd, NULL);
5522 if (ret)
5523 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
5524 __func__, afecmd_rd.port_id, ret);
5525 return ret;
5526}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305527EXPORT_SYMBOL(afe_rt_proxy_port_read);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305528
5529#ifdef CONFIG_DEBUG_FS
5530static struct dentry *debugfs_afelb;
5531static struct dentry *debugfs_afelb_gain;
5532
5533static int afe_debug_open(struct inode *inode, struct file *file)
5534{
5535 file->private_data = inode->i_private;
5536 pr_info("%s: debug intf %s\n", __func__, (char *) file->private_data);
5537 return 0;
5538}
5539
5540static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
5541{
5542 char *token;
5543 int base, cnt;
5544
5545 token = strsep(&buf, " ");
5546
5547 for (cnt = 0; cnt < num_of_par; cnt++) {
5548 if (token != NULL) {
5549 if ((token[1] == 'x') || (token[1] == 'X'))
5550 base = 16;
5551 else
5552 base = 10;
5553
5554 if (kstrtoul(token, base, &param1[cnt]) != 0) {
5555 pr_err("%s: kstrtoul failed\n",
5556 __func__);
5557 return -EINVAL;
5558 }
5559
5560 token = strsep(&buf, " ");
5561 } else {
5562 pr_err("%s: token NULL\n", __func__);
5563 return -EINVAL;
5564 }
5565 }
5566 return 0;
5567}
5568#define AFE_LOOPBACK_ON (1)
5569#define AFE_LOOPBACK_OFF (0)
5570static ssize_t afe_debug_write(struct file *filp,
5571 const char __user *ubuf, size_t cnt, loff_t *ppos)
5572{
5573 char *lb_str = filp->private_data;
5574 char lbuf[32];
5575 int rc;
5576 unsigned long param[5];
5577
5578 if (cnt > sizeof(lbuf) - 1) {
5579 pr_err("%s: cnt %zd size %zd\n", __func__, cnt, sizeof(lbuf)-1);
5580 return -EINVAL;
5581 }
5582
5583 rc = copy_from_user(lbuf, ubuf, cnt);
5584 if (rc) {
5585 pr_err("%s: copy from user failed %d\n", __func__, rc);
5586 return -EFAULT;
5587 }
5588
5589 lbuf[cnt] = '\0';
5590
5591 if (!strcmp(lb_str, "afe_loopback")) {
5592 rc = afe_get_parameters(lbuf, param, 3);
5593 if (!rc) {
5594 pr_info("%s: %lu %lu %lu\n", lb_str, param[0], param[1],
5595 param[2]);
5596
5597 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
5598 AFE_LOOPBACK_OFF)) {
5599 pr_err("%s: Error, parameter 0 incorrect\n",
5600 __func__);
5601 rc = -EINVAL;
5602 goto afe_error;
5603 }
5604 if ((q6audio_validate_port(param[1]) < 0) ||
5605 (q6audio_validate_port(param[2])) < 0) {
5606 pr_err("%s: Error, invalid afe port\n",
5607 __func__);
5608 }
5609 if (this_afe.apr == NULL) {
5610 pr_err("%s: Error, AFE not opened\n", __func__);
5611 rc = -EINVAL;
5612 } else {
5613 rc = afe_loopback(param[0], param[1], param[2]);
5614 }
5615 } else {
5616 pr_err("%s: Error, invalid parameters\n", __func__);
5617 rc = -EINVAL;
5618 }
5619
5620 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
5621 rc = afe_get_parameters(lbuf, param, 2);
5622 if (!rc) {
5623 pr_info("%s: %s %lu %lu\n",
5624 __func__, lb_str, param[0], param[1]);
5625
5626 rc = q6audio_validate_port(param[0]);
5627 if (rc < 0) {
5628 pr_err("%s: Error, invalid afe port %d %lu\n",
5629 __func__, rc, param[0]);
5630 rc = -EINVAL;
5631 goto afe_error;
5632 }
5633
5634 if (param[1] > 100) {
5635 pr_err("%s: Error, volume should be 0 to 100 percentage param = %lu\n",
5636 __func__, param[1]);
5637 rc = -EINVAL;
5638 goto afe_error;
5639 }
5640
5641 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
5642
5643 if (this_afe.apr == NULL) {
5644 pr_err("%s: Error, AFE not opened\n", __func__);
5645 rc = -EINVAL;
5646 } else {
5647 rc = afe_loopback_gain(param[0], param[1]);
5648 }
5649 } else {
5650 pr_err("%s: Error, invalid parameters\n", __func__);
5651 rc = -EINVAL;
5652 }
5653 }
5654
5655afe_error:
5656 if (rc == 0)
5657 rc = cnt;
5658 else
5659 pr_err("%s: rc = %d\n", __func__, rc);
5660
5661 return rc;
5662}
5663
5664static const struct file_operations afe_debug_fops = {
5665 .open = afe_debug_open,
5666 .write = afe_debug_write
5667};
5668
5669static void config_debug_fs_init(void)
5670{
5671 debugfs_afelb = debugfs_create_file("afe_loopback",
5672 0664, NULL, (void *) "afe_loopback",
5673 &afe_debug_fops);
5674
5675 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
5676 0664, NULL, (void *) "afe_loopback_gain",
5677 &afe_debug_fops);
5678}
5679static void config_debug_fs_exit(void)
5680{
5681 debugfs_remove(debugfs_afelb);
5682 debugfs_remove(debugfs_afelb_gain);
5683}
5684#else
5685static void config_debug_fs_init(void)
5686{
5687}
5688static void config_debug_fs_exit(void)
5689{
5690}
5691#endif
5692
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305693/**
5694 * afe_set_dtmf_gen_rx_portid -
5695 * Set port_id for DTMF tone generation
5696 *
5697 * @port_id: AFE port id
5698 * @set: set or reset port id value for dtmf gen
5699 *
5700 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305701void afe_set_dtmf_gen_rx_portid(u16 port_id, int set)
5702{
5703 if (set)
5704 this_afe.dtmf_gen_rx_portid = port_id;
5705 else if (this_afe.dtmf_gen_rx_portid == port_id)
5706 this_afe.dtmf_gen_rx_portid = -1;
5707}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305708EXPORT_SYMBOL(afe_set_dtmf_gen_rx_portid);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305709
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305710/**
5711 * afe_dtmf_generate_rx - command to generate AFE DTMF RX
5712 *
5713 * @duration_in_ms: Duration in ms for dtmf tone
5714 * @high_freq: Higher frequency for dtmf
5715 * @low_freq: lower frequency for dtmf
5716 * @gain: Gain value for DTMF tone
5717 *
5718 * Returns 0 on success, appropriate error code otherwise
5719 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305720int afe_dtmf_generate_rx(int64_t duration_in_ms,
5721 uint16_t high_freq,
5722 uint16_t low_freq, uint16_t gain)
5723{
5724 int ret = 0;
5725 int index = 0;
5726 struct afe_dtmf_generation_command cmd_dtmf;
5727
5728 pr_debug("%s: DTMF AFE Gen\n", __func__);
5729
5730 if (afe_validate_port(this_afe.dtmf_gen_rx_portid) < 0) {
5731 pr_err("%s: Failed : Invalid Port id = 0x%x\n",
5732 __func__, this_afe.dtmf_gen_rx_portid);
5733 ret = -EINVAL;
5734 goto fail_cmd;
5735 }
5736
5737 if (this_afe.apr == NULL) {
5738 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5739 0xFFFFFFFF, &this_afe);
5740 pr_debug("%s: Register AFE\n", __func__);
5741 if (this_afe.apr == NULL) {
5742 pr_err("%s: Unable to register AFE\n", __func__);
5743 ret = -ENODEV;
5744 return ret;
5745 }
5746 rtac_set_afe_handle(this_afe.apr);
5747 }
5748
5749 pr_debug("%s: dur=%lld: hfreq=%d lfreq=%d gain=%d portid=0x%x\n",
5750 __func__,
5751 duration_in_ms, high_freq, low_freq, gain,
5752 this_afe.dtmf_gen_rx_portid);
5753
5754 cmd_dtmf.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5755 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5756 cmd_dtmf.hdr.pkt_size = sizeof(cmd_dtmf);
5757 cmd_dtmf.hdr.src_port = 0;
5758 cmd_dtmf.hdr.dest_port = 0;
5759 cmd_dtmf.hdr.token = 0;
5760 cmd_dtmf.hdr.opcode = AFE_PORTS_CMD_DTMF_CTL;
5761 cmd_dtmf.duration_in_ms = duration_in_ms;
5762 cmd_dtmf.high_freq = high_freq;
5763 cmd_dtmf.low_freq = low_freq;
5764 cmd_dtmf.gain = gain;
5765 cmd_dtmf.num_ports = 1;
5766 cmd_dtmf.port_ids = q6audio_get_port_id(this_afe.dtmf_gen_rx_portid);
5767
5768 atomic_set(&this_afe.state, 1);
5769 atomic_set(&this_afe.status, 0);
5770 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_dtmf);
5771 if (ret < 0) {
5772 pr_err("%s: AFE DTMF failed for num_ports:%d ids:0x%x\n",
5773 __func__, cmd_dtmf.num_ports, cmd_dtmf.port_ids);
5774 ret = -EINVAL;
5775 goto fail_cmd;
5776 }
5777 index = q6audio_get_port_index(this_afe.dtmf_gen_rx_portid);
5778 if (index < 0 || index >= AFE_MAX_PORTS) {
5779 pr_err("%s: AFE port index[%d] invalid!\n",
5780 __func__, index);
5781 ret = -EINVAL;
5782 goto fail_cmd;
5783 }
5784 ret = wait_event_timeout(this_afe.wait[index],
5785 (atomic_read(&this_afe.state) == 0),
5786 msecs_to_jiffies(TIMEOUT_MS));
5787 if (!ret) {
5788 pr_err("%s: wait_event timeout\n", __func__);
5789 ret = -EINVAL;
5790 goto fail_cmd;
5791 }
5792 if (atomic_read(&this_afe.status) > 0) {
5793 pr_err("%s: config cmd failed [%s]\n",
5794 __func__, adsp_err_get_err_str(
5795 atomic_read(&this_afe.status)));
5796 ret = adsp_err_get_lnx_err_code(
5797 atomic_read(&this_afe.status));
5798 goto fail_cmd;
5799 }
5800 return 0;
5801
5802fail_cmd:
5803 pr_err("%s: failed %d\n", __func__, ret);
5804 return ret;
5805}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305806EXPORT_SYMBOL(afe_dtmf_generate_rx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305807
5808static int afe_sidetone_iir(u16 tx_port_id)
5809{
5810 struct afe_loopback_iir_cfg_v2 iir_sidetone;
5811 int ret;
5812 int index = 0;
5813 uint16_t size = 0;
5814 int cal_index = AFE_SIDETONE_IIR_CAL;
5815 int iir_pregain = 0;
5816 int iir_num_biquad_stages = 0;
5817 int iir_enable;
5818 struct cal_block_data *cal_block;
5819 int mid;
5820
5821 memset(&iir_sidetone, 0, sizeof(iir_sidetone));
5822 index = q6audio_get_port_index(tx_port_id);
5823 iir_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5824 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5825 iir_sidetone.hdr.pkt_size = sizeof(iir_sidetone);
5826 iir_sidetone.hdr.src_port = 0;
5827 iir_sidetone.hdr.dest_port = 0;
5828 iir_sidetone.hdr.token = index;
5829 iir_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
5830 iir_sidetone.param.port_id = tx_port_id;
5831 iir_sidetone.param.payload_address_lsw = 0x00;
5832 iir_sidetone.param.payload_address_msw = 0x00;
5833 iir_sidetone.param.mem_map_handle = 0x00;
5834
5835 if (this_afe.cal_data[cal_index] == NULL) {
5836 pr_err("%s: cal data is NULL\n", __func__);
5837 ret = -EINVAL;
5838 goto done;
5839 }
5840 mutex_lock(&this_afe.cal_data[cal_index]->lock);
5841 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07005842 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305843 pr_err("%s: cal_block not found\n ", __func__);
5844 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5845 ret = -EINVAL;
5846 goto done;
5847 }
5848
5849 iir_pregain = ((struct audio_cal_info_sidetone_iir *)
5850 cal_block->cal_info)->pregain;
5851 iir_enable = ((struct audio_cal_info_sidetone_iir *)
5852 cal_block->cal_info)->iir_enable;
5853 iir_num_biquad_stages = ((struct audio_cal_info_sidetone_iir *)
5854 cal_block->cal_info)->num_biquad_stages;
5855 mid = ((struct audio_cal_info_sidetone_iir *)
5856 cal_block->cal_info)->mid;
5857
5858 /*
5859 * calculate the actual size of payload based on no of stages
5860 * enabled in calibration
5861 */
5862 size = (MAX_SIDETONE_IIR_DATA_SIZE / MAX_NO_IIR_FILTER_STAGE) *
5863 iir_num_biquad_stages;
5864 /*
5865 * For an odd number of stages, 2 bytes of padding are
5866 * required at the end of the payload.
5867 */
5868 if (iir_num_biquad_stages % 2) {
5869 pr_debug("%s: adding 2 to size:%d\n", __func__, size);
5870 size = size + 2;
5871 }
5872 memcpy(&iir_sidetone.st_iir_filter_config_data.iir_config,
5873 &((struct audio_cal_info_sidetone_iir *)
5874 cal_block->cal_info)->iir_config,
5875 sizeof(iir_sidetone.st_iir_filter_config_data.iir_config));
5876 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5877
5878 /*
5879 * Calculate the payload size for setparams command
5880 */
5881 iir_sidetone.param.payload_size = (sizeof(iir_sidetone) -
5882 sizeof(struct apr_hdr) -
5883 sizeof(struct afe_port_cmd_set_param_v2) -
5884 (MAX_SIDETONE_IIR_DATA_SIZE - size));
5885
5886 pr_debug("%s: payload size :%d\n", __func__,
5887 iir_sidetone.param.payload_size);
5888
5889 /*
5890 * Set IIR enable params
5891 */
5892 iir_sidetone.st_iir_enable_pdata.module_id = mid;
5893 iir_sidetone.st_iir_enable_pdata.param_id =
5894 AFE_PARAM_ID_ENABLE;
5895 iir_sidetone.st_iir_enable_pdata.param_size =
5896 sizeof(iir_sidetone.st_iir_mode_enable_data);
5897 iir_sidetone.st_iir_mode_enable_data.enable = iir_enable;
5898
5899 /*
5900 * Set IIR filter config params
5901 */
5902 iir_sidetone.st_iir_filter_config_pdata.module_id = mid;
5903 iir_sidetone.st_iir_filter_config_pdata.param_id =
5904 AFE_PARAM_ID_SIDETONE_IIR_FILTER_CONFIG;
5905 iir_sidetone.st_iir_filter_config_pdata.param_size =
5906 sizeof(iir_sidetone.st_iir_filter_config_data.num_biquad_stages)
5907 +
5908 sizeof(iir_sidetone.st_iir_filter_config_data.pregain) + size;
5909 iir_sidetone.st_iir_filter_config_pdata.reserved = 0;
5910 iir_sidetone.st_iir_filter_config_data.num_biquad_stages =
5911 iir_num_biquad_stages;
5912 iir_sidetone.st_iir_filter_config_data.pregain = iir_pregain;
5913 pr_debug("%s: tx(0x%x)mid(0x%x)iir_en(%d)stg(%d)gain(0x%x)size(%d)\n",
5914 __func__, tx_port_id, mid,
5915 iir_sidetone.st_iir_mode_enable_data.enable,
5916 iir_sidetone.st_iir_filter_config_data.num_biquad_stages,
5917 iir_sidetone.st_iir_filter_config_data.pregain,
5918 iir_sidetone.st_iir_filter_config_pdata.param_size);
5919 ret = afe_apr_send_pkt(&iir_sidetone, &this_afe.wait[index]);
5920 if (ret)
5921 pr_err("%s: AFE sidetone failed for tx_port(0x%x)\n",
5922 __func__, tx_port_id);
5923
5924done:
5925 return ret;
5926
5927}
5928
5929static int afe_sidetone(u16 tx_port_id, u16 rx_port_id, bool enable)
5930{
5931 struct afe_st_loopback_cfg_v1 cmd_sidetone;
5932 int ret;
5933 int index;
5934 int cal_index = AFE_SIDETONE_CAL;
5935 int sidetone_gain;
5936 int sidetone_enable;
5937 struct cal_block_data *cal_block;
5938 int mid = 0;
5939
5940 memset(&cmd_sidetone, 0, sizeof(cmd_sidetone));
5941 if (this_afe.cal_data[cal_index] == NULL) {
5942 pr_err("%s: cal data is NULL\n", __func__);
5943 ret = -EINVAL;
5944 goto done;
5945 }
5946 mutex_lock(&this_afe.cal_data[cal_index]->lock);
5947 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07005948 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305949 pr_err("%s: cal_block not found\n", __func__);
5950 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5951 ret = -EINVAL;
5952 goto done;
5953 }
5954 sidetone_gain = ((struct audio_cal_info_sidetone *)
5955 cal_block->cal_info)->gain;
5956 sidetone_enable = ((struct audio_cal_info_sidetone *)
5957 cal_block->cal_info)->enable;
5958 mid = ((struct audio_cal_info_sidetone *)
5959 cal_block->cal_info)->mid;
5960 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5961
5962 index = q6audio_get_port_index(tx_port_id);
5963 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5964 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5965 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
5966 cmd_sidetone.hdr.src_port = 0;
5967 cmd_sidetone.hdr.dest_port = 0;
5968 cmd_sidetone.hdr.token = index;
5969 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
5970 cmd_sidetone.param.port_id = tx_port_id;
5971 cmd_sidetone.param.payload_size = (sizeof(cmd_sidetone) -
5972 sizeof(struct apr_hdr) -
5973 sizeof(struct afe_port_cmd_set_param_v2));
5974 cmd_sidetone.param.payload_address_lsw = 0x00;
5975 cmd_sidetone.param.payload_address_msw = 0x00;
5976 cmd_sidetone.param.mem_map_handle = 0x00;
5977 cmd_sidetone.gain_pdata.module_id = AFE_MODULE_LOOPBACK;
5978 cmd_sidetone.gain_pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
5979 /*
5980 * size of actual payload only
5981 */
5982 cmd_sidetone.gain_pdata.param_size = sizeof(
5983 struct afe_loopback_sidetone_gain);
5984 cmd_sidetone.gain_data.rx_port_id = rx_port_id;
5985 cmd_sidetone.gain_data.gain = sidetone_gain;
5986
5987 cmd_sidetone.cfg_pdata.module_id = AFE_MODULE_LOOPBACK;
5988 cmd_sidetone.cfg_pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
5989 /*
5990 * size of actual payload only
5991 */
5992 cmd_sidetone.cfg_pdata.param_size = sizeof(struct loopback_cfg_data);
5993 cmd_sidetone.cfg_data.loopback_cfg_minor_version =
5994 AFE_API_VERSION_LOOPBACK_CONFIG;
5995 cmd_sidetone.cfg_data.dst_port_id = rx_port_id;
5996 cmd_sidetone.cfg_data.routing_mode = LB_MODE_SIDETONE;
5997 cmd_sidetone.cfg_data.enable = enable;
5998
5999 pr_debug("%s rx(0x%x) tx(0x%x) enable(%d) mid(0x%x) gain(%d) sidetone_enable(%d)\n",
6000 __func__, rx_port_id, tx_port_id,
6001 enable, mid, sidetone_gain, sidetone_enable);
6002
6003 ret = afe_apr_send_pkt(&cmd_sidetone, &this_afe.wait[index]);
6004 if (ret)
6005 pr_err("%s: AFE sidetone send failed for tx_port:%d rx_port:%d ret:%d\n",
6006 __func__, tx_port_id, rx_port_id, ret);
6007done:
6008 return ret;
6009}
6010
6011int afe_sidetone_enable(u16 tx_port_id, u16 rx_port_id, bool enable)
6012{
6013 int ret;
6014 int index;
6015
6016 index = q6audio_get_port_index(rx_port_id);
6017 if (index < 0 || index >= AFE_MAX_PORTS) {
6018 pr_err("%s: AFE port index[%d] invalid!\n",
6019 __func__, index);
6020 ret = -EINVAL;
6021 goto done;
6022 }
6023 if (q6audio_validate_port(rx_port_id) < 0) {
6024 pr_err("%s: Invalid port 0x%x\n",
6025 __func__, rx_port_id);
6026 ret = -EINVAL;
6027 goto done;
6028 }
6029 index = q6audio_get_port_index(tx_port_id);
6030 if (index < 0 || index >= AFE_MAX_PORTS) {
6031 pr_err("%s: AFE port index[%d] invalid!\n",
6032 __func__, index);
6033 ret = -EINVAL;
6034 goto done;
6035 }
6036 if (q6audio_validate_port(tx_port_id) < 0) {
6037 pr_err("%s: Invalid port 0x%x\n",
6038 __func__, tx_port_id);
6039 ret = -EINVAL;
6040 goto done;
6041 }
6042 if (enable) {
6043 ret = afe_sidetone_iir(tx_port_id);
6044 if (ret)
6045 goto done;
6046 }
6047
6048 ret = afe_sidetone(tx_port_id, rx_port_id, enable);
6049
6050done:
6051 return ret;
6052}
6053
6054int afe_validate_port(u16 port_id)
6055{
6056 int ret;
6057
6058 switch (port_id) {
6059 case PRIMARY_I2S_RX:
6060 case PRIMARY_I2S_TX:
6061 case AFE_PORT_ID_PRIMARY_PCM_RX:
6062 case AFE_PORT_ID_PRIMARY_PCM_TX:
6063 case AFE_PORT_ID_SECONDARY_PCM_RX:
6064 case AFE_PORT_ID_SECONDARY_PCM_TX:
6065 case AFE_PORT_ID_TERTIARY_PCM_RX:
6066 case AFE_PORT_ID_TERTIARY_PCM_TX:
6067 case AFE_PORT_ID_QUATERNARY_PCM_RX:
6068 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05306069 case AFE_PORT_ID_QUINARY_PCM_RX:
6070 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306071 case SECONDARY_I2S_RX:
6072 case SECONDARY_I2S_TX:
6073 case MI2S_RX:
6074 case MI2S_TX:
6075 case HDMI_RX:
6076 case DISPLAY_PORT_RX:
6077 case AFE_PORT_ID_SPDIF_RX:
6078 case RSVD_2:
6079 case RSVD_3:
6080 case DIGI_MIC_TX:
6081 case VOICE_RECORD_RX:
6082 case VOICE_RECORD_TX:
6083 case VOICE_PLAYBACK_TX:
6084 case VOICE2_PLAYBACK_TX:
6085 case SLIMBUS_0_RX:
6086 case SLIMBUS_0_TX:
6087 case SLIMBUS_1_RX:
6088 case SLIMBUS_1_TX:
6089 case SLIMBUS_2_RX:
6090 case SLIMBUS_2_TX:
6091 case SLIMBUS_3_RX:
6092 case INT_BT_SCO_RX:
6093 case INT_BT_SCO_TX:
6094 case INT_BT_A2DP_RX:
6095 case INT_FM_RX:
6096 case INT_FM_TX:
6097 case RT_PROXY_PORT_001_RX:
6098 case RT_PROXY_PORT_001_TX:
6099 case SLIMBUS_4_RX:
6100 case SLIMBUS_4_TX:
6101 case SLIMBUS_5_RX:
6102 case SLIMBUS_6_RX:
6103 case SLIMBUS_6_TX:
6104 case SLIMBUS_7_RX:
6105 case SLIMBUS_7_TX:
6106 case SLIMBUS_8_RX:
6107 case SLIMBUS_8_TX:
6108 case AFE_PORT_ID_USB_RX:
6109 case AFE_PORT_ID_USB_TX:
6110 case AFE_PORT_ID_PRIMARY_MI2S_RX:
6111 case AFE_PORT_ID_PRIMARY_MI2S_TX:
6112 case AFE_PORT_ID_SECONDARY_MI2S_RX:
6113 case AFE_PORT_ID_SECONDARY_MI2S_TX:
6114 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
6115 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
6116 case AFE_PORT_ID_TERTIARY_MI2S_RX:
6117 case AFE_PORT_ID_TERTIARY_MI2S_TX:
6118 case AFE_PORT_ID_QUINARY_MI2S_RX:
6119 case AFE_PORT_ID_QUINARY_MI2S_TX:
6120 case AFE_PORT_ID_SENARY_MI2S_TX:
6121 case AFE_PORT_ID_PRIMARY_TDM_RX:
6122 case AFE_PORT_ID_PRIMARY_TDM_TX:
6123 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
6124 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
6125 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
6126 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
6127 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
6128 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
6129 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
6130 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
6131 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
6132 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
6133 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
6134 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
6135 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
6136 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
6137 case AFE_PORT_ID_SECONDARY_TDM_RX:
6138 case AFE_PORT_ID_SECONDARY_TDM_TX:
6139 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
6140 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
6141 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
6142 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
6143 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
6144 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
6145 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
6146 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
6147 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
6148 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
6149 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
6150 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
6151 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
6152 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
6153 case AFE_PORT_ID_TERTIARY_TDM_RX:
6154 case AFE_PORT_ID_TERTIARY_TDM_TX:
6155 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
6156 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
6157 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
6158 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
6159 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
6160 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
6161 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
6162 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
6163 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
6164 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
6165 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
6166 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
6167 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
6168 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
6169 case AFE_PORT_ID_QUATERNARY_TDM_RX:
6170 case AFE_PORT_ID_QUATERNARY_TDM_TX:
6171 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
6172 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
6173 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
6174 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
6175 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
6176 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
6177 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
6178 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
6179 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
6180 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
6181 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
6182 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
6183 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
6184 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05306185 case AFE_PORT_ID_QUINARY_TDM_RX:
6186 case AFE_PORT_ID_QUINARY_TDM_TX:
6187 case AFE_PORT_ID_QUINARY_TDM_RX_1:
6188 case AFE_PORT_ID_QUINARY_TDM_TX_1:
6189 case AFE_PORT_ID_QUINARY_TDM_RX_2:
6190 case AFE_PORT_ID_QUINARY_TDM_TX_2:
6191 case AFE_PORT_ID_QUINARY_TDM_RX_3:
6192 case AFE_PORT_ID_QUINARY_TDM_TX_3:
6193 case AFE_PORT_ID_QUINARY_TDM_RX_4:
6194 case AFE_PORT_ID_QUINARY_TDM_TX_4:
6195 case AFE_PORT_ID_QUINARY_TDM_RX_5:
6196 case AFE_PORT_ID_QUINARY_TDM_TX_5:
6197 case AFE_PORT_ID_QUINARY_TDM_RX_6:
6198 case AFE_PORT_ID_QUINARY_TDM_TX_6:
6199 case AFE_PORT_ID_QUINARY_TDM_RX_7:
6200 case AFE_PORT_ID_QUINARY_TDM_TX_7:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306201 case AFE_PORT_ID_INT0_MI2S_RX:
6202 case AFE_PORT_ID_INT1_MI2S_RX:
6203 case AFE_PORT_ID_INT2_MI2S_RX:
6204 case AFE_PORT_ID_INT3_MI2S_RX:
6205 case AFE_PORT_ID_INT4_MI2S_RX:
6206 case AFE_PORT_ID_INT5_MI2S_RX:
6207 case AFE_PORT_ID_INT6_MI2S_RX:
6208 case AFE_PORT_ID_INT0_MI2S_TX:
6209 case AFE_PORT_ID_INT1_MI2S_TX:
6210 case AFE_PORT_ID_INT2_MI2S_TX:
6211 case AFE_PORT_ID_INT3_MI2S_TX:
6212 case AFE_PORT_ID_INT4_MI2S_TX:
6213 case AFE_PORT_ID_INT5_MI2S_TX:
6214 case AFE_PORT_ID_INT6_MI2S_TX:
6215 {
6216 ret = 0;
6217 break;
6218 }
6219
6220 default:
6221 pr_err("%s: default ret 0x%x\n", __func__, port_id);
6222 ret = -EINVAL;
6223 }
6224
6225 return ret;
6226}
6227
6228int afe_convert_virtual_to_portid(u16 port_id)
6229{
6230 int ret;
6231
6232 /*
6233 * if port_id is virtual, convert to physical..
6234 * if port_id is already physical, return physical
6235 */
6236 if (afe_validate_port(port_id) < 0) {
6237 if (port_id == RT_PROXY_DAI_001_RX ||
6238 port_id == RT_PROXY_DAI_001_TX ||
6239 port_id == RT_PROXY_DAI_002_RX ||
6240 port_id == RT_PROXY_DAI_002_TX) {
6241 ret = VIRTUAL_ID_TO_PORTID(port_id);
6242 } else {
6243 pr_err("%s: wrong port 0x%x\n",
6244 __func__, port_id);
6245 ret = -EINVAL;
6246 }
6247 } else
6248 ret = port_id;
6249
6250 return ret;
6251}
6252int afe_port_stop_nowait(int port_id)
6253{
6254 struct afe_port_cmd_device_stop stop;
6255 int ret = 0;
6256
6257 if (this_afe.apr == NULL) {
6258 pr_err("%s: AFE is already closed\n", __func__);
6259 ret = -EINVAL;
6260 goto fail_cmd;
6261 }
6262 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
6263 port_id = q6audio_convert_virtual_to_portid(port_id);
6264
6265 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6266 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6267 stop.hdr.pkt_size = sizeof(stop);
6268 stop.hdr.src_port = 0;
6269 stop.hdr.dest_port = 0;
6270 stop.hdr.token = 0;
6271 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
6272 stop.port_id = port_id;
6273 stop.reserved = 0;
6274
6275 ret = afe_apr_send_pkt(&stop, NULL);
6276 if (ret)
6277 pr_err("%s: AFE close failed %d\n", __func__, ret);
6278
6279fail_cmd:
6280 return ret;
6281
6282}
6283
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306284/**
6285 * afe_close - command to close AFE port
6286 *
6287 * @port_id: AFE port id
6288 *
6289 * Returns 0 on success, appropriate error code otherwise
6290 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306291int afe_close(int port_id)
6292{
6293 struct afe_port_cmd_device_stop stop;
6294 enum afe_mad_type mad_type;
6295 int ret = 0;
6296 int index = 0;
6297 uint16_t port_index;
6298
6299 if (this_afe.apr == NULL) {
6300 pr_err("%s: AFE is already closed\n", __func__);
6301 if ((port_id == RT_PROXY_DAI_001_RX) ||
6302 (port_id == RT_PROXY_DAI_002_TX))
6303 pcm_afe_instance[port_id & 0x1] = 0;
6304 if ((port_id == RT_PROXY_DAI_002_RX) ||
6305 (port_id == RT_PROXY_DAI_001_TX))
6306 proxy_afe_instance[port_id & 0x1] = 0;
6307 afe_close_done[port_id & 0x1] = true;
6308 ret = -EINVAL;
6309 goto fail_cmd;
6310 }
6311 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
6312 if ((port_id == RT_PROXY_DAI_001_RX) ||
6313 (port_id == RT_PROXY_DAI_002_TX)) {
6314 pr_debug("%s: before decrementing pcm_afe_instance %d\n",
6315 __func__, pcm_afe_instance[port_id & 0x1]);
6316 port_id = VIRTUAL_ID_TO_PORTID(port_id);
6317 pcm_afe_instance[port_id & 0x1]--;
6318 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
6319 proxy_afe_instance[port_id & 0x1] == 0)) ||
6320 afe_close_done[port_id & 0x1] == true)
6321 return 0;
6322
6323 afe_close_done[port_id & 0x1] = true;
6324 }
6325
6326 if ((port_id == RT_PROXY_DAI_002_RX) ||
6327 (port_id == RT_PROXY_DAI_001_TX)) {
6328 pr_debug("%s: before decrementing proxy_afe_instance %d\n",
6329 __func__, proxy_afe_instance[port_id & 0x1]);
6330 port_id = VIRTUAL_ID_TO_PORTID(port_id);
6331 proxy_afe_instance[port_id & 0x1]--;
6332 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
6333 proxy_afe_instance[port_id & 0x1] == 0)) ||
6334 afe_close_done[port_id & 0x1] == true)
6335 return 0;
6336
6337 afe_close_done[port_id & 0x1] = true;
6338 }
6339
6340 port_id = q6audio_convert_virtual_to_portid(port_id);
6341 index = q6audio_get_port_index(port_id);
6342 if (index < 0 || index >= AFE_MAX_PORTS) {
6343 pr_err("%s: AFE port index[%d] invalid!\n",
6344 __func__, index);
6345 return -EINVAL;
6346 }
6347 ret = q6audio_validate_port(port_id);
6348 if (ret < 0) {
6349 pr_warn("%s: Not a valid port id 0x%x ret %d\n",
6350 __func__, port_id, ret);
6351 return -EINVAL;
6352 }
6353
6354 mad_type = afe_port_get_mad_type(port_id);
6355 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
6356 mad_type);
6357 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
6358 pr_debug("%s: Turn off MAD\n", __func__);
6359 ret = afe_turn_onoff_hw_mad(mad_type, false);
6360 if (ret) {
6361 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
6362 __func__, ret);
6363 return ret;
6364 }
6365 } else {
6366 pr_debug("%s: Not a MAD port\n", __func__);
6367 }
6368
6369 port_index = afe_get_port_index(port_id);
6370 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
6371 this_afe.afe_sample_rates[port_index] = 0;
6372 this_afe.topology[port_index] = 0;
6373 this_afe.dev_acdb_id[port_index] = 0;
6374 } else {
6375 pr_err("%s: port %d\n", __func__, port_index);
6376 ret = -EINVAL;
6377 goto fail_cmd;
6378 }
6379
6380 if ((port_id == this_afe.aanc_info.aanc_tx_port) &&
6381 (this_afe.aanc_info.aanc_active)) {
6382 memset(&this_afe.aanc_info, 0x00, sizeof(this_afe.aanc_info));
6383 ret = afe_aanc_mod_enable(this_afe.apr, port_id, 0);
6384 if (ret)
6385 pr_err("%s: AFE mod disable failed %d\n",
6386 __func__, ret);
6387 }
6388
6389 /*
6390 * even if ramp down configuration failed it is not serious enough to
6391 * warrant bailaing out.
6392 */
6393 if (afe_spk_ramp_dn_cfg(port_id) < 0)
6394 pr_err("%s: ramp down configuration failed\n", __func__);
6395
6396 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6397 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6398 stop.hdr.pkt_size = sizeof(stop);
6399 stop.hdr.src_port = 0;
6400 stop.hdr.dest_port = 0;
6401 stop.hdr.token = index;
6402 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
6403 stop.port_id = q6audio_get_port_id(port_id);
6404 stop.reserved = 0;
6405
6406 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
6407 if (ret)
6408 pr_err("%s: AFE close failed %d\n", __func__, ret);
6409
6410fail_cmd:
6411 return ret;
6412}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306413EXPORT_SYMBOL(afe_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306414
6415int afe_set_digital_codec_core_clock(u16 port_id,
6416 struct afe_digital_clk_cfg *cfg)
6417{
6418 struct afe_lpass_digital_clk_config_command clk_cfg;
6419 int index = 0;
6420 int ret = 0;
6421
6422 if (!cfg) {
6423 pr_err("%s: clock cfg is NULL\n", __func__);
6424 ret = -EINVAL;
6425 return ret;
6426 }
6427
6428 ret = afe_q6_interface_prepare();
6429 if (ret != 0) {
6430 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6431 return ret;
6432 }
6433
6434 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6435 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6436 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6437 clk_cfg.hdr.src_port = 0;
6438 clk_cfg.hdr.dest_port = 0;
6439 clk_cfg.hdr.token = index;
6440
6441 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6442 /*default rx port is taken to enable the codec digital clock*/
6443 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6444 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6445 - sizeof(clk_cfg.param);
6446 clk_cfg.param.payload_address_lsw = 0x00;
6447 clk_cfg.param.payload_address_msw = 0x00;
6448 clk_cfg.param.mem_map_handle = 0x00;
6449 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6450 clk_cfg.pdata.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
6451 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6452 clk_cfg.clk_cfg = *cfg;
6453
6454 pr_debug("%s: Minor version =0x%x clk val = %d\n"
6455 "clk root = 0x%x resrv = 0x%x\n",
6456 __func__, cfg->i2s_cfg_minor_version,
6457 cfg->clk_val, cfg->clk_root, cfg->reserved);
6458
6459 atomic_set(&this_afe.state, 1);
6460 atomic_set(&this_afe.status, 0);
6461 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6462 if (ret < 0) {
6463 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6464 __func__, port_id, ret);
6465 ret = -EINVAL;
6466 goto fail_cmd;
6467 }
6468
6469 ret = wait_event_timeout(this_afe.wait[index],
6470 (atomic_read(&this_afe.state) == 0),
6471 msecs_to_jiffies(TIMEOUT_MS));
6472 if (!ret) {
6473 pr_err("%s: wait_event timeout\n", __func__);
6474 ret = -EINVAL;
6475 goto fail_cmd;
6476 }
6477 if (atomic_read(&this_afe.status) > 0) {
6478 pr_err("%s: config cmd failed [%s]\n",
6479 __func__, adsp_err_get_err_str(
6480 atomic_read(&this_afe.status)));
6481 ret = adsp_err_get_lnx_err_code(
6482 atomic_read(&this_afe.status));
6483 goto fail_cmd;
6484 }
6485
6486fail_cmd:
6487 return ret;
6488}
6489
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306490/**
6491 * afe_set_lpass_clock - Enable AFE lpass clock
6492 *
6493 * @port_id: AFE port id
6494 * @cfg: pointer to clk set struct
6495 *
6496 * Returns 0 on success, appropriate error code otherwise
6497 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306498int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg)
6499{
6500 struct afe_lpass_clk_config_command clk_cfg;
6501 int index = 0;
6502 int ret = 0;
6503
6504 if (!cfg) {
6505 pr_err("%s: clock cfg is NULL\n", __func__);
6506 ret = -EINVAL;
6507 return ret;
6508 }
6509 index = q6audio_get_port_index(port_id);
6510 if (index < 0 || index >= AFE_MAX_PORTS) {
6511 pr_err("%s: AFE port index[%d] invalid!\n",
6512 __func__, index);
6513 return -EINVAL;
6514 }
6515 ret = q6audio_is_digital_pcm_interface(port_id);
6516 if (ret < 0) {
6517 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6518 __func__, ret);
6519 return -EINVAL;
6520 }
6521
6522 ret = afe_q6_interface_prepare();
6523 if (ret != 0) {
6524 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6525 return ret;
6526 }
6527
6528 mutex_lock(&this_afe.afe_cmd_lock);
6529 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6530 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6531 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6532 clk_cfg.hdr.src_port = 0;
6533 clk_cfg.hdr.dest_port = 0;
6534 clk_cfg.hdr.token = index;
6535
6536 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6537 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6538 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6539 - sizeof(clk_cfg.param);
6540 clk_cfg.param.payload_address_lsw = 0x00;
6541 clk_cfg.param.payload_address_msw = 0x00;
6542 clk_cfg.param.mem_map_handle = 0x00;
6543 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6544 clk_cfg.pdata.param_id = AFE_PARAM_ID_LPAIF_CLK_CONFIG;
6545 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6546 clk_cfg.clk_cfg = *cfg;
6547
6548 pr_debug("%s: Minor version =0x%x clk val1 = %d\n"
6549 "clk val2 = %d, clk src = 0x%x\n"
6550 "clk root = 0x%x clk mode = 0x%x resrv = 0x%x\n"
6551 "port id = 0x%x\n",
6552 __func__, cfg->i2s_cfg_minor_version,
6553 cfg->clk_val1, cfg->clk_val2, cfg->clk_src,
6554 cfg->clk_root, cfg->clk_set_mode,
6555 cfg->reserved, q6audio_get_port_id(port_id));
6556
6557 atomic_set(&this_afe.state, 1);
6558 atomic_set(&this_afe.status, 0);
6559 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6560 if (ret < 0) {
6561 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6562 __func__, port_id, ret);
6563 ret = -EINVAL;
6564 goto fail_cmd;
6565 }
6566
6567 ret = wait_event_timeout(this_afe.wait[index],
6568 (atomic_read(&this_afe.state) == 0),
6569 msecs_to_jiffies(TIMEOUT_MS));
6570 if (!ret) {
6571 pr_err("%s: wait_event timeout\n", __func__);
6572 ret = -EINVAL;
6573 goto fail_cmd;
6574 }
6575 if (atomic_read(&this_afe.status) > 0) {
6576 pr_err("%s: config cmd failed [%s]\n",
6577 __func__, adsp_err_get_err_str(
6578 atomic_read(&this_afe.status)));
6579 ret = adsp_err_get_lnx_err_code(
6580 atomic_read(&this_afe.status));
6581 goto fail_cmd;
6582 }
6583
6584fail_cmd:
6585 mutex_unlock(&this_afe.afe_cmd_lock);
6586 return ret;
6587}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306588EXPORT_SYMBOL(afe_set_lpass_clock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306589
6590/**
6591 * afe_set_lpass_clk_cfg - Set AFE clk config
6592 *
6593 * @index: port index
6594 * @cfg: pointer to clk set struct
6595 *
6596 * Returns 0 on success, appropriate error code otherwise
6597 */
6598int afe_set_lpass_clk_cfg(int index, struct afe_clk_set *cfg)
6599{
6600 struct afe_lpass_clk_config_command_v2 clk_cfg;
6601 int ret = 0;
6602
6603 if (!cfg) {
6604 pr_err("%s: clock cfg is NULL\n", __func__);
6605 ret = -EINVAL;
6606 return ret;
6607 }
6608
6609 if (index < 0 || index >= AFE_MAX_PORTS) {
6610 pr_err("%s: index[%d] invalid!\n", __func__, index);
6611 return -EINVAL;
6612 }
6613
6614 ret = afe_q6_interface_prepare();
6615 if (ret != 0) {
6616 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6617 return ret;
6618 }
6619
6620 mutex_lock(&this_afe.afe_cmd_lock);
6621 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6622 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6623 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6624 clk_cfg.hdr.src_port = 0;
6625 clk_cfg.hdr.dest_port = 0;
6626 clk_cfg.hdr.token = index;
6627
6628 clk_cfg.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
6629 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6630 - sizeof(clk_cfg.param);
6631 clk_cfg.param.payload_address_lsw = 0x00;
6632 clk_cfg.param.payload_address_msw = 0x00;
6633 clk_cfg.param.mem_map_handle = 0x00;
6634 clk_cfg.pdata.module_id = AFE_MODULE_CLOCK_SET;
6635 clk_cfg.pdata.param_id = AFE_PARAM_ID_CLOCK_SET;
6636 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6637 clk_cfg.clk_cfg = *cfg;
6638
6639
6640 pr_debug("%s: Minor version =0x%x clk id = %d\n"
6641 "clk freq (Hz) = %d, clk attri = 0x%x\n"
6642 "clk root = 0x%x clk enable = 0x%x\n",
6643 __func__, cfg->clk_set_minor_version,
6644 cfg->clk_id, cfg->clk_freq_in_hz, cfg->clk_attri,
6645 cfg->clk_root, cfg->enable);
6646
6647 atomic_set(&this_afe.state, 1);
6648 atomic_set(&this_afe.status, 0);
6649 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6650 if (ret < 0) {
6651 pr_err("%s: AFE clk cfg failed with ret %d\n",
6652 __func__, ret);
6653 ret = -EINVAL;
6654 goto fail_cmd;
6655 }
6656
6657 ret = wait_event_timeout(this_afe.wait[index],
6658 (atomic_read(&this_afe.state) == 0),
6659 msecs_to_jiffies(TIMEOUT_MS));
6660 if (!ret) {
6661 pr_err("%s: wait_event timeout\n", __func__);
6662 ret = -EINVAL;
6663 goto fail_cmd;
6664 } else {
6665 /* set ret to 0 as no timeout happened */
6666 ret = 0;
6667 }
6668 if (atomic_read(&this_afe.status) != 0) {
6669 pr_err("%s: config cmd failed\n", __func__);
6670 ret = -EINVAL;
6671 goto fail_cmd;
6672 }
6673
6674fail_cmd:
6675 mutex_unlock(&this_afe.afe_cmd_lock);
6676 return ret;
6677}
6678EXPORT_SYMBOL(afe_set_lpass_clk_cfg);
6679
6680/**
6681 * afe_set_lpass_clock_v2 - Enable AFE lpass clock
6682 *
6683 * @port_id: AFE port id
6684 * @cfg: pointer to clk set struct
6685 *
6686 * Returns 0 on success, appropriate error code otherwise
6687 */
6688int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
6689{
6690 int index = 0;
6691 int ret = 0;
6692
6693 index = q6audio_get_port_index(port_id);
6694 if (index < 0 || index >= AFE_MAX_PORTS) {
6695 pr_err("%s: AFE port index[%d] invalid!\n",
6696 __func__, index);
6697 return -EINVAL;
6698 }
6699 ret = q6audio_is_digital_pcm_interface(port_id);
6700 if (ret < 0) {
6701 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6702 __func__, ret);
6703 return -EINVAL;
6704 }
6705
6706 ret = afe_set_lpass_clk_cfg(index, cfg);
6707 if (ret)
6708 pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
6709 __func__, ret);
6710
6711 return ret;
6712}
6713EXPORT_SYMBOL(afe_set_lpass_clock_v2);
6714
Raja Mallike1b2f792018-06-01 13:17:36 +05306715static int afe_get_service_ver(void)
6716{
6717 int ret = 0;
6718 size_t ver_size;
6719 struct avcs_fwk_ver_info *ver_info = NULL;
6720
6721 ver_size = sizeof(struct avcs_get_fwk_version) +
6722 sizeof(struct avs_svc_api_info);
6723 ver_info = kzalloc(ver_size, GFP_KERNEL);
6724 if (ver_info == NULL)
6725 return -ENOMEM;
6726
6727 ret = q6core_get_service_version(AVCS_SERVICE_ID_AFE, ver_info, ver_size);
6728 if (ret)
6729 pr_err("%s: q6core_get_service_version failed %d\n",
6730 __func__, ret);
6731
6732 return ret;
6733}
6734
6735enum lpass_clk_ver afe_get_lpass_clk_ver(void)
6736{
6737 enum lpass_clk_ver lpass_clk_ver;
6738
6739 /*
6740 * Use different APIs to set the LPASS clock depending on the AFE
6741 * version. On success afe_get_service_ver returns 0 signyfing the
6742 * latest AFE version is supported. Use LPASS clock version 2 if the
6743 * latest AFE version is supported, otherwise use LPASS clock version 1.
6744 */
6745 lpass_clk_ver = (afe_get_service_ver() == 0) ?
6746 LPASS_CLK_VER_2 : LPASS_CLK_VER_1;
6747
6748 pr_debug("%s: returning %s\n", __func__,
6749 (lpass_clk_ver == LPASS_CLK_VER_2) ?
6750 "LPASS_CLK_VER_2" : "LPASS_CLK_VER_1");
6751
6752 return lpass_clk_ver;
6753}
6754EXPORT_SYMBOL(afe_get_lpass_clk_ver);
6755
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306756int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
6757 struct afe_digital_clk_cfg *cfg)
6758{
6759 struct afe_lpass_digital_clk_config_command clk_cfg;
6760 int index = 0;
6761 int ret = 0;
6762
6763 if (!cfg) {
6764 pr_err("%s: clock cfg is NULL\n", __func__);
6765 ret = -EINVAL;
6766 return ret;
6767 }
6768 index = q6audio_get_port_index(port_id);
6769 if (index < 0 || index >= AFE_MAX_PORTS) {
6770 pr_err("%s: AFE port index[%d] invalid!\n",
6771 __func__, index);
6772 return -EINVAL;
6773 }
6774 ret = q6audio_is_digital_pcm_interface(port_id);
6775 if (ret < 0) {
6776 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6777 __func__, ret);
6778 return -EINVAL;
6779 }
6780
6781 ret = afe_q6_interface_prepare();
6782 if (ret != 0) {
6783 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6784 return ret;
6785 }
6786
6787 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6788 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6789 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6790 clk_cfg.hdr.src_port = 0;
6791 clk_cfg.hdr.dest_port = 0;
6792 clk_cfg.hdr.token = index;
6793
6794 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6795 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6796 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6797 - sizeof(clk_cfg.param);
6798 clk_cfg.param.payload_address_lsw = 0x00;
6799 clk_cfg.param.payload_address_msw = 0x00;
6800 clk_cfg.param.mem_map_handle = 0x00;
6801 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6802 clk_cfg.pdata.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
6803 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6804 clk_cfg.clk_cfg = *cfg;
6805
6806 pr_debug("%s: Minor version =0x%x clk val = %d\n"
6807 "clk root = 0x%x resrv = 0x%x port id = 0x%x\n",
6808 __func__, cfg->i2s_cfg_minor_version,
6809 cfg->clk_val, cfg->clk_root, cfg->reserved,
6810 q6audio_get_port_id(port_id));
6811
6812 atomic_set(&this_afe.state, 1);
6813 atomic_set(&this_afe.status, 0);
6814 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6815 if (ret < 0) {
6816 pr_err("%s: AFE enable for port 0x0x%x ret %d\n",
6817 __func__, port_id, ret);
6818 ret = -EINVAL;
6819 goto fail_cmd;
6820 }
6821
6822 ret = wait_event_timeout(this_afe.wait[index],
6823 (atomic_read(&this_afe.state) == 0),
6824 msecs_to_jiffies(TIMEOUT_MS));
6825 if (!ret) {
6826 pr_err("%s: wait_event timeout\n", __func__);
6827 ret = -EINVAL;
6828 goto fail_cmd;
6829 }
6830 if (atomic_read(&this_afe.status) > 0) {
6831 pr_err("%s: config cmd failed [%s]\n",
6832 __func__, adsp_err_get_err_str(
6833 atomic_read(&this_afe.status)));
6834 ret = adsp_err_get_lnx_err_code(
6835 atomic_read(&this_afe.status));
6836 goto fail_cmd;
6837 }
6838
6839fail_cmd:
6840 return ret;
6841}
6842
6843int afe_enable_lpass_core_shared_clock(u16 port_id, u32 enable)
6844{
6845 struct afe_lpass_core_shared_clk_config_command clk_cfg;
6846 int index = 0;
6847 int ret = 0;
6848
6849 index = q6audio_get_port_index(port_id);
6850 if (index < 0 || index >= AFE_MAX_PORTS) {
6851 pr_err("%s: AFE port index[%d] invalid!\n",
6852 __func__, index);
6853 return -EINVAL;
6854 }
6855 ret = q6audio_is_digital_pcm_interface(port_id);
6856 if (ret < 0) {
6857 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6858 __func__, ret);
6859 return -EINVAL;
6860 }
6861
6862 ret = afe_q6_interface_prepare();
6863 if (ret != 0) {
6864 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6865 return ret;
6866 }
6867
6868 mutex_lock(&this_afe.afe_cmd_lock);
6869 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6870 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6871 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6872 clk_cfg.hdr.src_port = 0;
6873 clk_cfg.hdr.dest_port = 0;
6874 clk_cfg.hdr.token = index;
6875
6876 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6877 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6878 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6879 - sizeof(clk_cfg.param);
6880 clk_cfg.param.payload_address_lsw = 0x00;
6881 clk_cfg.param.payload_address_msw = 0x00;
6882 clk_cfg.param.mem_map_handle = 0x00;
6883 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6884 clk_cfg.pdata.param_id = AFE_PARAM_ID_LPASS_CORE_SHARED_CLOCK_CONFIG;
6885 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6886 clk_cfg.clk_cfg.lpass_core_shared_clk_cfg_minor_version =
6887 AFE_API_VERSION_LPASS_CORE_SHARED_CLK_CONFIG;
6888 clk_cfg.clk_cfg.enable = enable;
6889
6890 pr_debug("%s: port id = %d, enable = %d\n",
6891 __func__, q6audio_get_port_id(port_id), enable);
6892
6893 atomic_set(&this_afe.state, 1);
6894 atomic_set(&this_afe.status, 0);
6895 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6896 if (ret < 0) {
6897 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6898 __func__, port_id, ret);
6899 ret = -EINVAL;
6900 goto fail_cmd;
6901 }
6902
6903 ret = wait_event_timeout(this_afe.wait[index],
6904 (atomic_read(&this_afe.state) == 0),
6905 msecs_to_jiffies(TIMEOUT_MS));
6906 if (!ret) {
6907 pr_err("%s: wait_event timeout\n", __func__);
6908 ret = -EINVAL;
6909 goto fail_cmd;
6910 }
6911 if (atomic_read(&this_afe.status) > 0) {
6912 pr_err("%s: config cmd failed [%s]\n",
6913 __func__, adsp_err_get_err_str(
6914 atomic_read(&this_afe.status)));
6915 ret = adsp_err_get_lnx_err_code(
6916 atomic_read(&this_afe.status));
6917 goto fail_cmd;
6918 }
6919
6920fail_cmd:
6921 mutex_unlock(&this_afe.afe_cmd_lock);
6922 return ret;
6923}
6924
6925int q6afe_check_osr_clk_freq(u32 freq)
6926{
6927 int ret = 0;
6928
6929 switch (freq) {
6930 case Q6AFE_LPASS_OSR_CLK_12_P288_MHZ:
Karthikeyan Mani7190b892017-12-10 23:50:37 -08006931 case Q6AFE_LPASS_OSR_CLK_9_P600_MHZ:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306932 case Q6AFE_LPASS_OSR_CLK_8_P192_MHZ:
6933 case Q6AFE_LPASS_OSR_CLK_6_P144_MHZ:
6934 case Q6AFE_LPASS_OSR_CLK_4_P096_MHZ:
6935 case Q6AFE_LPASS_OSR_CLK_3_P072_MHZ:
6936 case Q6AFE_LPASS_OSR_CLK_2_P048_MHZ:
6937 case Q6AFE_LPASS_OSR_CLK_1_P536_MHZ:
6938 case Q6AFE_LPASS_OSR_CLK_1_P024_MHZ:
6939 case Q6AFE_LPASS_OSR_CLK_768_kHZ:
6940 case Q6AFE_LPASS_OSR_CLK_512_kHZ:
6941 break;
6942 default:
6943 pr_err("%s: deafault freq 0x%x\n",
6944 __func__, freq);
6945 ret = -EINVAL;
6946 }
6947 return ret;
6948}
6949
6950int afe_get_sp_th_vi_ftm_data(struct afe_sp_th_vi_get_param *th_vi)
6951{
6952 int ret = -EINVAL;
6953 int index = 0, port = SLIMBUS_4_TX;
6954
6955 if (!th_vi) {
6956 pr_err("%s: Invalid params\n", __func__);
6957 goto done;
6958 }
6959 if (this_afe.vi_tx_port != -1)
6960 port = this_afe.vi_tx_port;
6961
6962 ret = q6audio_validate_port(port);
6963 if (ret < 0) {
6964 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6965 goto done;
6966 }
6967 index = q6audio_get_port_index(port);
6968 if (index < 0) {
6969 pr_err("%s: invalid port 0x%x, index %d\n",
6970 __func__, port, index);
6971 ret = -EINVAL;
6972 goto done;
6973 }
6974 th_vi->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6975 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6976 th_vi->hdr.pkt_size = sizeof(*th_vi);
6977 th_vi->hdr.src_port = 0;
6978 th_vi->hdr.dest_port = 0;
6979 th_vi->hdr.token = index;
6980 th_vi->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6981 th_vi->get_param.mem_map_handle = 0;
6982 th_vi->get_param.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
6983 th_vi->get_param.param_id = AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS;
6984 th_vi->get_param.payload_address_lsw = 0;
6985 th_vi->get_param.payload_address_msw = 0;
6986 th_vi->get_param.payload_size = sizeof(*th_vi)
6987 - sizeof(th_vi->get_param) - sizeof(th_vi->hdr);
6988 th_vi->get_param.port_id = q6audio_get_port_id(port);
6989 th_vi->pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
6990 th_vi->pdata.param_id = AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS;
6991 th_vi->pdata.param_size = sizeof(th_vi->param);
6992 atomic_set(&this_afe.status, 0);
6993 atomic_set(&this_afe.state, 1);
6994 ret = apr_send_pkt(this_afe.apr, (uint32_t *)th_vi);
6995 if (ret < 0) {
6996 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
6997 __func__, port, th_vi->get_param.param_id, ret);
6998 goto done;
6999 }
7000 ret = wait_event_timeout(this_afe.wait[index],
7001 (atomic_read(&this_afe.state) == 0),
7002 msecs_to_jiffies(TIMEOUT_MS));
7003 if (!ret) {
7004 pr_err("%s: wait_event timeout\n", __func__);
7005 ret = -EINVAL;
7006 goto done;
7007 }
7008 if (atomic_read(&this_afe.status) > 0) {
7009 pr_err("%s: config cmd failed [%s]\n",
7010 __func__, adsp_err_get_err_str(
7011 atomic_read(&this_afe.status)));
7012 ret = adsp_err_get_lnx_err_code(atomic_read(&this_afe.status));
7013 goto done;
7014 }
7015 memcpy(&th_vi->param, &this_afe.th_vi_resp.param,
7016 sizeof(this_afe.th_vi_resp.param));
7017 pr_debug("%s: DC resistance %d %d temp %d %d status %d %d\n",
7018 __func__, th_vi->param.dc_res_q24[SP_V2_SPKR_1],
7019 th_vi->param.dc_res_q24[SP_V2_SPKR_2],
7020 th_vi->param.temp_q22[SP_V2_SPKR_1],
7021 th_vi->param.temp_q22[SP_V2_SPKR_2],
7022 th_vi->param.status[SP_V2_SPKR_1],
7023 th_vi->param.status[SP_V2_SPKR_2]);
7024 ret = 0;
7025done:
7026 return ret;
7027}
7028
7029int afe_get_sp_ex_vi_ftm_data(struct afe_sp_ex_vi_get_param *ex_vi)
7030{
7031 int ret = -EINVAL;
7032 int index = 0, port = SLIMBUS_4_TX;
7033
7034 if (!ex_vi) {
7035 pr_err("%s: Invalid params\n", __func__);
7036 goto done;
7037 }
7038 if (this_afe.vi_tx_port != -1)
7039 port = this_afe.vi_tx_port;
7040
7041 ret = q6audio_validate_port(port);
7042 if (ret < 0) {
7043 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
7044 goto done;
7045 }
7046
7047 index = q6audio_get_port_index(port);
7048 if (index < 0) {
7049 pr_err("%s: invalid index %d port 0x%x\n", __func__,
7050 index, port);
7051 ret = -EINVAL;
7052 goto done;
7053 }
7054
7055 ex_vi->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7056 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
7057 ex_vi->hdr.pkt_size = sizeof(*ex_vi);
7058 ex_vi->hdr.src_port = 0;
7059 ex_vi->hdr.dest_port = 0;
7060 ex_vi->hdr.token = index;
7061 ex_vi->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
7062 ex_vi->get_param.mem_map_handle = 0;
7063 ex_vi->get_param.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
7064 ex_vi->get_param.param_id = AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS;
7065 ex_vi->get_param.payload_address_lsw = 0;
7066 ex_vi->get_param.payload_address_msw = 0;
7067 ex_vi->get_param.payload_size = sizeof(*ex_vi)
7068 - sizeof(ex_vi->get_param) - sizeof(ex_vi->hdr);
7069 ex_vi->get_param.port_id = q6audio_get_port_id(port);
7070 ex_vi->pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
7071 ex_vi->pdata.param_id = AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS;
7072 ex_vi->pdata.param_size = sizeof(ex_vi->param);
7073 atomic_set(&this_afe.status, 0);
7074 atomic_set(&this_afe.state, 1);
7075 ret = apr_send_pkt(this_afe.apr, (uint32_t *)ex_vi);
7076 if (ret < 0) {
7077 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
7078 __func__, port, ex_vi->get_param.param_id, ret);
7079 goto done;
7080 }
7081 ret = wait_event_timeout(this_afe.wait[index],
7082 (atomic_read(&this_afe.state) == 0),
7083 msecs_to_jiffies(TIMEOUT_MS));
7084 if (!ret) {
7085 pr_err("%s: wait_event timeout\n", __func__);
7086 ret = -EINVAL;
7087 goto done;
7088 }
7089 if (atomic_read(&this_afe.status) > 0) {
7090 pr_err("%s: config cmd failed [%s]\n",
7091 __func__, adsp_err_get_err_str(
7092 atomic_read(&this_afe.status)));
7093 ret = adsp_err_get_lnx_err_code(atomic_read(&this_afe.status));
7094 goto done;
7095 }
7096 memcpy(&ex_vi->param, &this_afe.ex_vi_resp.param,
7097 sizeof(this_afe.ex_vi_resp.param));
7098 pr_debug("%s: freq %d %d resistance %d %d qfactor %d %d state %d %d\n",
7099 __func__, ex_vi->param.freq_q20[SP_V2_SPKR_1],
7100 ex_vi->param.freq_q20[SP_V2_SPKR_2],
7101 ex_vi->param.resis_q24[SP_V2_SPKR_1],
7102 ex_vi->param.resis_q24[SP_V2_SPKR_2],
7103 ex_vi->param.qmct_q24[SP_V2_SPKR_1],
7104 ex_vi->param.qmct_q24[SP_V2_SPKR_2],
7105 ex_vi->param.status[SP_V2_SPKR_1],
7106 ex_vi->param.status[SP_V2_SPKR_2]);
7107 ret = 0;
7108done:
7109 return ret;
7110}
7111
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307112/**
7113 * afe_get_av_dev_drift -
7114 * command to retrieve AV drift
7115 *
7116 * @timing_stats: timing stats to be updated with AV drift values
7117 * @port: AFE port ID
7118 *
7119 * Returns 0 on success or error on failure
7120 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307121int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
7122 u16 port)
7123{
7124 int ret = -EINVAL;
7125 int index = 0;
7126 struct afe_av_dev_drift_get_param av_dev_drift;
7127
7128 if (!timing_stats) {
7129 pr_err("%s: Invalid params\n", __func__);
7130 goto exit;
7131 }
7132
7133 ret = q6audio_validate_port(port);
7134 if (ret < 0) {
7135 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
7136 ret = -EINVAL;
7137 goto exit;
7138 }
7139
7140 index = q6audio_get_port_index(port);
7141 if (index < 0 || index >= AFE_MAX_PORTS) {
7142 pr_err("%s: Invalid AFE port index[%d]\n",
7143 __func__, index);
7144 ret = -EINVAL;
7145 goto exit;
7146 }
7147
7148 memset(&av_dev_drift, 0, sizeof(struct afe_av_dev_drift_get_param));
7149
7150 av_dev_drift.hdr.hdr_field =
7151 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7152 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
7153 av_dev_drift.hdr.pkt_size = sizeof(av_dev_drift);
7154 av_dev_drift.hdr.src_port = 0;
7155 av_dev_drift.hdr.dest_port = 0;
7156 av_dev_drift.hdr.token = index;
7157 av_dev_drift.hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
7158 av_dev_drift.get_param.mem_map_handle = 0;
7159 av_dev_drift.get_param.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
7160 av_dev_drift.get_param.param_id = AFE_PARAM_ID_DEV_TIMING_STATS;
7161 av_dev_drift.get_param.payload_address_lsw = 0;
7162 av_dev_drift.get_param.payload_address_msw = 0;
7163 av_dev_drift.get_param.payload_size = sizeof(av_dev_drift)
7164 - sizeof(av_dev_drift.get_param) - sizeof(av_dev_drift.hdr);
7165 av_dev_drift.get_param.port_id = q6audio_get_port_id(port);
7166 av_dev_drift.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
7167 av_dev_drift.pdata.param_id = AFE_PARAM_ID_DEV_TIMING_STATS;
7168 av_dev_drift.pdata.param_size = sizeof(av_dev_drift.timing_stats);
7169 atomic_set(&this_afe.status, 0);
7170 atomic_set(&this_afe.state, 1);
7171 ret = apr_send_pkt(this_afe.apr, (uint32_t *)&av_dev_drift);
7172 if (ret < 0) {
7173 pr_err("%s: get param port 0x%x param id[0x%x] failed %d\n",
7174 __func__, port, av_dev_drift.get_param.param_id, ret);
7175 goto exit;
7176 }
7177
7178 ret = wait_event_timeout(this_afe.wait[index],
7179 (atomic_read(&this_afe.state) == 0),
7180 msecs_to_jiffies(TIMEOUT_MS));
7181 if (!ret) {
7182 pr_err("%s: wait_event timeout\n", __func__);
7183 ret = -EINVAL;
7184 goto exit;
7185 }
7186
7187 if (atomic_read(&this_afe.status) > 0) {
7188 pr_err("%s: config cmd failed [%s]\n",
7189 __func__, adsp_err_get_err_str(
7190 atomic_read(&this_afe.status)));
7191 ret = adsp_err_get_lnx_err_code(
7192 atomic_read(&this_afe.status));
7193 goto exit;
7194 }
7195
7196 memcpy(timing_stats, &this_afe.av_dev_drift_resp.timing_stats,
7197 sizeof(this_afe.av_dev_drift_resp.timing_stats));
7198 ret = 0;
7199exit:
7200 return ret;
7201}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307202EXPORT_SYMBOL(afe_get_av_dev_drift);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307203
7204int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp)
7205{
7206 int ret = -EINVAL;
7207 int index = 0, port = SLIMBUS_4_TX;
7208
7209 if (!calib_resp) {
7210 pr_err("%s: Invalid params\n", __func__);
7211 goto fail_cmd;
7212 }
7213 if (this_afe.vi_tx_port != -1)
7214 port = this_afe.vi_tx_port;
7215
7216 ret = q6audio_validate_port(port);
7217 if (ret < 0) {
7218 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
7219 ret = -EINVAL;
7220 goto fail_cmd;
7221 }
7222 index = q6audio_get_port_index(port);
7223 if (index < 0 || index >= AFE_MAX_PORTS) {
7224 pr_err("%s: AFE port index[%d] invalid!\n",
7225 __func__, index);
7226 ret = -EINVAL;
7227 goto fail_cmd;
7228 }
7229 calib_resp->hdr.hdr_field =
7230 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7231 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
7232 calib_resp->hdr.pkt_size = sizeof(*calib_resp);
7233 calib_resp->hdr.src_port = 0;
7234 calib_resp->hdr.dest_port = 0;
7235 calib_resp->hdr.token = index;
7236 calib_resp->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
7237 calib_resp->get_param.mem_map_handle = 0;
7238 calib_resp->get_param.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
7239 calib_resp->get_param.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2;
7240 calib_resp->get_param.payload_address_lsw = 0;
7241 calib_resp->get_param.payload_address_msw = 0;
7242 calib_resp->get_param.payload_size = sizeof(*calib_resp)
7243 - sizeof(calib_resp->get_param) - sizeof(calib_resp->hdr);
7244 calib_resp->get_param.port_id = q6audio_get_port_id(port);
7245 calib_resp->pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
7246 calib_resp->pdata.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2;
7247 calib_resp->pdata.param_size = sizeof(calib_resp->res_cfg);
7248 atomic_set(&this_afe.status, 0);
7249 atomic_set(&this_afe.state, 1);
7250 ret = apr_send_pkt(this_afe.apr, (uint32_t *)calib_resp);
7251 if (ret < 0) {
7252 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
7253 __func__, port, calib_resp->get_param.param_id, ret);
7254 goto fail_cmd;
7255 }
7256 ret = wait_event_timeout(this_afe.wait[index],
7257 (atomic_read(&this_afe.state) == 0),
7258 msecs_to_jiffies(TIMEOUT_MS));
7259 if (!ret) {
7260 pr_err("%s: wait_event timeout\n", __func__);
7261 ret = -EINVAL;
7262 goto fail_cmd;
7263 }
7264 if (atomic_read(&this_afe.status) > 0) {
7265 pr_err("%s: config cmd failed [%s]\n",
7266 __func__, adsp_err_get_err_str(
7267 atomic_read(&this_afe.status)));
7268 ret = adsp_err_get_lnx_err_code(
7269 atomic_read(&this_afe.status));
7270 goto fail_cmd;
7271 }
7272 memcpy(&calib_resp->res_cfg, &this_afe.calib_data.res_cfg,
7273 sizeof(this_afe.calib_data.res_cfg));
7274 pr_info("%s: state %s resistance %d %d\n", __func__,
7275 fbsp_state[calib_resp->res_cfg.th_vi_ca_state],
7276 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1],
7277 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]);
7278 ret = 0;
7279fail_cmd:
7280 return ret;
7281}
7282
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307283/**
7284 * afe_spk_prot_feed_back_cfg -
7285 * command to setup spk protection feedback config
7286 *
7287 * @src_port: source port id
7288 * @dst_port: destination port id
7289 * @l_ch: left speaker active or not
7290 * @r_ch: right speaker active or not
7291 * @enable: flag to enable or disable
7292 *
7293 * Returns 0 on success or error on failure
7294 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307295int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
7296 int l_ch, int r_ch, u32 enable)
7297{
7298 int ret = -EINVAL;
7299 union afe_spkr_prot_config prot_config;
7300 int index = 0;
7301
7302 if (!enable) {
7303 pr_debug("%s: Disable Feedback tx path", __func__);
7304 this_afe.vi_tx_port = -1;
7305 this_afe.vi_rx_port = -1;
7306 return 0;
7307 }
7308
7309 if ((q6audio_validate_port(src_port) < 0) ||
7310 (q6audio_validate_port(dst_port) < 0)) {
7311 pr_err("%s: invalid ports src 0x%x dst 0x%x",
7312 __func__, src_port, dst_port);
7313 goto fail_cmd;
7314 }
7315 if (!l_ch && !r_ch) {
7316 pr_err("%s: error ch values zero\n", __func__);
7317 goto fail_cmd;
7318 }
7319 pr_debug("%s: src_port 0x%x dst_port 0x%x l_ch %d r_ch %d\n",
7320 __func__, src_port, dst_port, l_ch, r_ch);
7321 memset(&prot_config, 0, sizeof(prot_config));
7322 prot_config.feedback_path_cfg.dst_portid =
7323 q6audio_get_port_id(dst_port);
7324 if (l_ch) {
7325 prot_config.feedback_path_cfg.chan_info[index++] = 1;
7326 prot_config.feedback_path_cfg.chan_info[index++] = 2;
7327 }
7328 if (r_ch) {
7329 prot_config.feedback_path_cfg.chan_info[index++] = 3;
7330 prot_config.feedback_path_cfg.chan_info[index++] = 4;
7331 }
7332 prot_config.feedback_path_cfg.num_channels = index;
7333 pr_debug("%s no of channels: %d\n", __func__, index);
7334 prot_config.feedback_path_cfg.minor_version = 1;
7335 ret = afe_spk_prot_prepare(src_port, dst_port,
7336 AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config);
7337fail_cmd:
7338 return ret;
7339}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307340EXPORT_SYMBOL(afe_spk_prot_feed_back_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307341
7342static int get_cal_type_index(int32_t cal_type)
7343{
7344 int ret = -EINVAL;
7345
7346 switch (cal_type) {
7347 case AFE_COMMON_RX_CAL_TYPE:
7348 ret = AFE_COMMON_RX_CAL;
7349 break;
7350 case AFE_COMMON_TX_CAL_TYPE:
7351 ret = AFE_COMMON_TX_CAL;
7352 break;
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307353 case AFE_LSM_TX_CAL_TYPE:
7354 ret = AFE_LSM_TX_CAL;
7355 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307356 case AFE_AANC_CAL_TYPE:
7357 ret = AFE_AANC_CAL;
7358 break;
7359 case AFE_HW_DELAY_CAL_TYPE:
7360 ret = AFE_HW_DELAY_CAL;
7361 break;
7362 case AFE_FB_SPKR_PROT_CAL_TYPE:
7363 ret = AFE_FB_SPKR_PROT_CAL;
7364 break;
7365 case AFE_SIDETONE_CAL_TYPE:
7366 ret = AFE_SIDETONE_CAL;
7367 break;
7368 case AFE_SIDETONE_IIR_CAL_TYPE:
7369 ret = AFE_SIDETONE_IIR_CAL;
7370 break;
7371 case AFE_TOPOLOGY_CAL_TYPE:
7372 ret = AFE_TOPOLOGY_CAL;
7373 break;
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307374 case AFE_LSM_TOPOLOGY_CAL_TYPE:
7375 ret = AFE_LSM_TOPOLOGY_CAL;
7376 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307377 case AFE_CUST_TOPOLOGY_CAL_TYPE:
7378 ret = AFE_CUST_TOPOLOGY_CAL;
7379 break;
7380 default:
7381 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
7382 }
7383 return ret;
7384}
7385
7386int afe_alloc_cal(int32_t cal_type, size_t data_size,
7387 void *data)
7388{
7389 int ret = 0;
7390 int cal_index;
7391
7392 cal_index = get_cal_type_index(cal_type);
7393 pr_debug("%s: cal_type = %d cal_index = %d\n",
7394 __func__, cal_type, cal_index);
7395
7396 if (cal_index < 0) {
7397 pr_err("%s: could not get cal index %d!\n",
7398 __func__, cal_index);
7399 ret = -EINVAL;
7400 goto done;
7401 }
7402
7403 ret = cal_utils_alloc_cal(data_size, data,
7404 this_afe.cal_data[cal_index], 0, NULL);
7405 if (ret < 0) {
7406 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
7407 __func__, ret, cal_type);
7408 ret = -EINVAL;
7409 goto done;
7410 }
7411done:
7412 return ret;
7413}
7414
7415static int afe_dealloc_cal(int32_t cal_type, size_t data_size,
7416 void *data)
7417{
7418 int ret = 0;
7419 int cal_index;
7420
7421 pr_debug("%s:\n", __func__);
7422
7423 cal_index = get_cal_type_index(cal_type);
7424 if (cal_index < 0) {
7425 pr_err("%s: could not get cal index %d!\n",
7426 __func__, cal_index);
7427 ret = -EINVAL;
7428 goto done;
7429 }
7430
7431 ret = cal_utils_dealloc_cal(data_size, data,
7432 this_afe.cal_data[cal_index]);
7433 if (ret < 0) {
7434 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
7435 __func__, ret, cal_type);
7436 ret = -EINVAL;
7437 goto done;
7438 }
7439done:
7440 return ret;
7441}
7442
7443static int afe_set_cal(int32_t cal_type, size_t data_size,
7444 void *data)
7445{
7446 int ret = 0;
7447 int cal_index;
7448
7449 pr_debug("%s:\n", __func__);
7450
7451 cal_index = get_cal_type_index(cal_type);
7452 if (cal_index < 0) {
7453 pr_err("%s: could not get cal index %d!\n",
7454 __func__, cal_index);
7455 ret = -EINVAL;
7456 goto done;
7457 }
7458
7459 ret = cal_utils_set_cal(data_size, data,
7460 this_afe.cal_data[cal_index], 0, NULL);
7461 if (ret < 0) {
7462 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
7463 __func__, ret, cal_type);
7464 ret = -EINVAL;
7465 goto done;
7466 }
7467
7468 if (cal_index == AFE_CUST_TOPOLOGY_CAL) {
7469 mutex_lock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
7470 this_afe.set_custom_topology = 1;
7471 pr_debug("%s:[AFE_CUSTOM_TOPOLOGY] ret = %d, cal type = %d!\n",
7472 __func__, ret, cal_type);
7473 mutex_unlock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
7474 }
7475
7476done:
7477 return ret;
7478}
7479
7480static struct cal_block_data *afe_find_hw_delay_by_path(
7481 struct cal_type_data *cal_type, int path)
7482{
7483 struct list_head *ptr, *next;
7484 struct cal_block_data *cal_block = NULL;
7485
7486 pr_debug("%s:\n", __func__);
7487
7488 list_for_each_safe(ptr, next,
7489 &cal_type->cal_blocks) {
7490
7491 cal_block = list_entry(ptr,
7492 struct cal_block_data, list);
7493
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07007494 if (cal_utils_is_cal_stale(cal_block))
7495 continue;
7496
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307497 if (((struct audio_cal_info_hw_delay *)cal_block->cal_info)
7498 ->path == path) {
7499 return cal_block;
7500 }
7501 }
7502 return NULL;
7503}
7504
7505static int afe_get_cal_hw_delay(int32_t path,
7506 struct audio_cal_hw_delay_entry *entry)
7507{
7508 int ret = 0;
7509 int i;
7510 struct cal_block_data *cal_block = NULL;
7511 struct audio_cal_hw_delay_data *hw_delay_info = NULL;
7512
7513 pr_debug("%s:\n", __func__);
7514
7515 if (this_afe.cal_data[AFE_HW_DELAY_CAL] == NULL) {
7516 pr_err("%s: AFE_HW_DELAY_CAL not initialized\n", __func__);
7517 ret = -EINVAL;
7518 goto done;
7519 }
7520 if (entry == NULL) {
7521 pr_err("%s: entry is NULL\n", __func__);
7522 ret = -EINVAL;
7523 goto done;
7524 }
7525 if ((path >= MAX_PATH_TYPE) || (path < 0)) {
7526 pr_err("%s: bad path: %d\n",
7527 __func__, path);
7528 ret = -EINVAL;
7529 goto done;
7530 }
7531
7532 mutex_lock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
7533 cal_block = afe_find_hw_delay_by_path(
7534 this_afe.cal_data[AFE_HW_DELAY_CAL], path);
7535 if (cal_block == NULL)
7536 goto unlock;
7537
7538 hw_delay_info = &((struct audio_cal_info_hw_delay *)
7539 cal_block->cal_info)->data;
7540 if (hw_delay_info->num_entries > MAX_HW_DELAY_ENTRIES) {
7541 pr_err("%s: invalid num entries: %d\n",
7542 __func__, hw_delay_info->num_entries);
7543 ret = -EINVAL;
7544 goto unlock;
7545 }
7546
7547 for (i = 0; i < hw_delay_info->num_entries; i++) {
7548 if (hw_delay_info->entry[i].sample_rate ==
7549 entry->sample_rate) {
7550 entry->delay_usec = hw_delay_info->entry[i].delay_usec;
7551 break;
7552 }
7553 }
7554 if (i == hw_delay_info->num_entries) {
7555 pr_err("%s: Unable to find delay for sample rate %d\n",
7556 __func__, entry->sample_rate);
7557 ret = -EFAULT;
7558 goto unlock;
7559 }
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07007560
7561 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307562 pr_debug("%s: Path = %d samplerate = %u usec = %u status %d\n",
7563 __func__, path, entry->sample_rate, entry->delay_usec, ret);
7564unlock:
7565 mutex_unlock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
7566done:
7567 return ret;
7568}
7569
7570static int afe_set_cal_sp_th_vi_ftm_cfg(int32_t cal_type, size_t data_size,
7571 void *data)
7572{
7573 int ret = 0;
7574 struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data;
7575
7576 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
7577 cal_data == NULL ||
7578 data_size != sizeof(*cal_data))
7579 goto done;
7580
7581 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7582 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7583 memcpy(&this_afe.th_ftm_cfg, &cal_data->cal_info,
7584 sizeof(this_afe.th_ftm_cfg));
7585 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7586done:
7587 return ret;
7588}
7589
7590static int afe_set_cal_sp_ex_vi_ftm_cfg(int32_t cal_type, size_t data_size,
7591 void *data)
7592{
7593 int ret = 0;
7594 struct audio_cal_type_sp_ex_vi_ftm_cfg *cal_data = data;
7595
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 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7602 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7603 memcpy(&this_afe.ex_ftm_cfg, &cal_data->cal_info,
7604 sizeof(this_afe.ex_ftm_cfg));
7605 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7606done:
7607 return ret;
7608}
7609
7610static int afe_set_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
7611 void *data)
7612{
7613 int ret = 0;
7614 struct audio_cal_type_fb_spk_prot_cfg *cal_data = data;
7615
7616 pr_debug("%s:\n", __func__);
7617
7618 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
7619 goto done;
7620 if (cal_data == NULL)
7621 goto done;
7622 if (data_size != sizeof(*cal_data))
7623 goto done;
7624
7625 if (cal_data->cal_info.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
7626 __pm_wakeup_event(&wl.ws, jiffies_to_msecs(WAKELOCK_TIMEOUT));
7627 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7628 memcpy(&this_afe.prot_cfg, &cal_data->cal_info,
7629 sizeof(this_afe.prot_cfg));
7630 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7631done:
7632 return ret;
7633}
7634
7635static int afe_get_cal_sp_th_vi_ftm_param(int32_t cal_type, size_t data_size,
7636 void *data)
7637{
7638 int i, ret = 0;
7639 struct audio_cal_type_sp_th_vi_param *cal_data = data;
7640 struct afe_sp_th_vi_get_param th_vi;
7641
7642 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7643 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
7644 cal_data == NULL ||
7645 data_size != sizeof(*cal_data))
7646 goto done;
7647
7648 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7649 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7650 cal_data->cal_info.status[i] = -EINVAL;
7651 cal_data->cal_info.r_dc_q24[i] = -1;
7652 cal_data->cal_info.temp_q22[i] = -1;
7653 }
7654 if (!afe_get_sp_th_vi_ftm_data(&th_vi)) {
7655 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7656 pr_debug("%s: ftm param status = %d\n",
7657 __func__, th_vi.param.status[i]);
7658 if (th_vi.param.status[i] == FBSP_IN_PROGRESS) {
7659 cal_data->cal_info.status[i] = -EAGAIN;
7660 } else if (th_vi.param.status[i] == FBSP_SUCCESS) {
7661 cal_data->cal_info.status[i] = 0;
7662 cal_data->cal_info.r_dc_q24[i] =
7663 th_vi.param.dc_res_q24[i];
7664 cal_data->cal_info.temp_q22[i] =
7665 th_vi.param.temp_q22[i];
7666 }
7667 }
7668 }
7669 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7670done:
7671 return ret;
7672}
7673
7674static int afe_get_cal_sp_ex_vi_ftm_param(int32_t cal_type, size_t data_size,
7675 void *data)
7676{
7677 int i, ret = 0;
7678 struct audio_cal_type_sp_ex_vi_param *cal_data = data;
7679 struct afe_sp_ex_vi_get_param ex_vi;
7680
7681 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7682 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
7683 cal_data == NULL ||
7684 data_size != sizeof(*cal_data))
7685 goto done;
7686
7687 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7688 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7689 cal_data->cal_info.status[i] = -EINVAL;
7690 cal_data->cal_info.freq_q20[i] = -1;
7691 cal_data->cal_info.resis_q24[i] = -1;
7692 cal_data->cal_info.qmct_q24[i] = -1;
7693 }
7694 if (!afe_get_sp_ex_vi_ftm_data(&ex_vi)) {
7695 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7696 pr_debug("%s: ftm param status = %d\n",
7697 __func__, ex_vi.param.status[i]);
7698 if (ex_vi.param.status[i] == FBSP_IN_PROGRESS) {
7699 cal_data->cal_info.status[i] = -EAGAIN;
7700 } else if (ex_vi.param.status[i] == FBSP_SUCCESS) {
7701 cal_data->cal_info.status[i] = 0;
7702 cal_data->cal_info.freq_q20[i] =
7703 ex_vi.param.freq_q20[i];
7704 cal_data->cal_info.resis_q24[i] =
7705 ex_vi.param.resis_q24[i];
7706 cal_data->cal_info.qmct_q24[i] =
7707 ex_vi.param.qmct_q24[i];
7708 }
7709 }
7710 }
7711 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7712done:
7713 return ret;
7714}
7715
7716static int afe_get_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
7717 void *data)
7718{
7719 int ret = 0;
7720 struct audio_cal_type_fb_spk_prot_status *cal_data = data;
7721 struct afe_spkr_prot_get_vi_calib calib_resp;
7722
7723 pr_debug("%s:\n", __func__);
7724
7725 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
7726 goto done;
7727 if (cal_data == NULL)
7728 goto done;
7729 if (data_size != sizeof(*cal_data))
7730 goto done;
7731
7732 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7733 if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATED) {
7734 cal_data->cal_info.r0[SP_V2_SPKR_1] =
7735 this_afe.prot_cfg.r0[SP_V2_SPKR_1];
7736 cal_data->cal_info.r0[SP_V2_SPKR_2] =
7737 this_afe.prot_cfg.r0[SP_V2_SPKR_2];
7738 cal_data->cal_info.status = 0;
7739 } else if (this_afe.prot_cfg.mode ==
7740 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
7741 /*Call AFE to query the status*/
7742 cal_data->cal_info.status = -EINVAL;
7743 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
7744 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
7745 if (!afe_spk_prot_get_calib_data(&calib_resp)) {
7746 if (calib_resp.res_cfg.th_vi_ca_state ==
7747 FBSP_IN_PROGRESS)
7748 cal_data->cal_info.status = -EAGAIN;
7749 else if (calib_resp.res_cfg.th_vi_ca_state ==
7750 FBSP_SUCCESS) {
7751 cal_data->cal_info.status = 0;
7752 cal_data->cal_info.r0[SP_V2_SPKR_1] =
7753 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_1];
7754 cal_data->cal_info.r0[SP_V2_SPKR_2] =
7755 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_2];
7756 }
7757 }
7758 if (!cal_data->cal_info.status) {
7759 this_afe.prot_cfg.mode =
7760 MSM_SPKR_PROT_CALIBRATED;
7761 this_afe.prot_cfg.r0[SP_V2_SPKR_1] =
7762 cal_data->cal_info.r0[SP_V2_SPKR_1];
7763 this_afe.prot_cfg.r0[SP_V2_SPKR_2] =
7764 cal_data->cal_info.r0[SP_V2_SPKR_2];
7765 }
7766 } else {
7767 /*Indicates calibration data is invalid*/
7768 cal_data->cal_info.status = -EINVAL;
7769 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
7770 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
7771 }
7772 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7773 __pm_relax(&wl.ws);
7774done:
7775 return ret;
7776}
7777
7778static int afe_map_cal_data(int32_t cal_type,
7779 struct cal_block_data *cal_block)
7780{
7781 int ret = 0;
7782 int cal_index;
7783
7784 pr_debug("%s:\n", __func__);
7785
7786 cal_index = get_cal_type_index(cal_type);
7787 if (cal_index < 0) {
7788 pr_err("%s: could not get cal index %d!\n",
7789 __func__, cal_index);
7790 ret = -EINVAL;
7791 goto done;
7792 }
7793
7794
7795 mutex_lock(&this_afe.afe_cmd_lock);
7796 atomic_set(&this_afe.mem_map_cal_index, cal_index);
7797 ret = afe_cmd_memory_map(cal_block->cal_data.paddr,
7798 cal_block->map_data.map_size);
7799 atomic_set(&this_afe.mem_map_cal_index, -1);
7800 if (ret < 0) {
7801 pr_err("%s: mmap did not work! size = %zd ret %d\n",
7802 __func__,
7803 cal_block->map_data.map_size, ret);
7804 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
7805 __func__,
7806 &cal_block->cal_data.paddr,
7807 cal_block->map_data.map_size);
7808 mutex_unlock(&this_afe.afe_cmd_lock);
7809 goto done;
7810 }
7811 cal_block->map_data.q6map_handle = atomic_read(&this_afe.
7812 mem_map_cal_handles[cal_index]);
7813 mutex_unlock(&this_afe.afe_cmd_lock);
7814done:
7815 return ret;
7816}
7817
7818static int afe_unmap_cal_data(int32_t cal_type,
7819 struct cal_block_data *cal_block)
7820{
7821 int ret = 0;
7822 int cal_index;
7823
7824 pr_debug("%s:\n", __func__);
7825
7826 cal_index = get_cal_type_index(cal_type);
7827 if (cal_index < 0) {
7828 pr_err("%s: could not get cal index %d!\n",
7829 __func__, cal_index);
7830 ret = -EINVAL;
7831 goto done;
7832 }
7833
7834 if (cal_block == NULL) {
7835 pr_err("%s: Cal block is NULL!\n",
7836 __func__);
7837 goto done;
7838 }
7839
7840 if (cal_block->map_data.q6map_handle == 0) {
7841 pr_err("%s: Map handle is NULL, nothing to unmap\n",
7842 __func__);
7843 goto done;
7844 }
7845
7846 atomic_set(&this_afe.mem_map_cal_handles[cal_index],
7847 cal_block->map_data.q6map_handle);
7848 atomic_set(&this_afe.mem_map_cal_index, cal_index);
7849 ret = afe_cmd_memory_unmap_nowait(
7850 cal_block->map_data.q6map_handle);
7851 atomic_set(&this_afe.mem_map_cal_index, -1);
7852 if (ret < 0) {
7853 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
7854 __func__, cal_index, ret);
7855 }
7856 cal_block->map_data.q6map_handle = 0;
7857done:
7858 return ret;
7859}
7860
7861static void afe_delete_cal_data(void)
7862{
7863 pr_debug("%s:\n", __func__);
7864
7865 cal_utils_destroy_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data);
7866}
7867
7868static int afe_init_cal_data(void)
7869{
7870 int ret = 0;
7871 struct cal_type_info cal_type_info[] = {
7872 {{AFE_COMMON_RX_CAL_TYPE,
7873 {afe_alloc_cal, afe_dealloc_cal, NULL,
7874 afe_set_cal, NULL, NULL} },
7875 {afe_map_cal_data, afe_unmap_cal_data,
7876 cal_utils_match_buf_num} },
7877
7878 {{AFE_COMMON_TX_CAL_TYPE,
7879 {afe_alloc_cal, afe_dealloc_cal, NULL,
7880 afe_set_cal, NULL, NULL} },
7881 {afe_map_cal_data, afe_unmap_cal_data,
7882 cal_utils_match_buf_num} },
7883
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307884 {{AFE_LSM_TX_CAL_TYPE,
7885 {afe_alloc_cal, afe_dealloc_cal, NULL,
7886 afe_set_cal, NULL, NULL} },
7887 {afe_map_cal_data, afe_unmap_cal_data,
7888 cal_utils_match_buf_num} },
7889
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307890 {{AFE_AANC_CAL_TYPE,
7891 {afe_alloc_cal, afe_dealloc_cal, NULL,
7892 afe_set_cal, NULL, NULL} },
7893 {afe_map_cal_data, afe_unmap_cal_data,
7894 cal_utils_match_buf_num} },
7895
7896 {{AFE_FB_SPKR_PROT_CAL_TYPE,
7897 {NULL, NULL, NULL, afe_set_cal_fb_spkr_prot,
7898 afe_get_cal_fb_spkr_prot, NULL} },
7899 {NULL, NULL, cal_utils_match_buf_num} },
7900
7901 {{AFE_HW_DELAY_CAL_TYPE,
7902 {NULL, NULL, NULL,
7903 afe_set_cal, NULL, NULL} },
7904 {NULL, NULL, cal_utils_match_buf_num} },
7905
7906 {{AFE_SIDETONE_CAL_TYPE,
7907 {NULL, NULL, NULL,
7908 afe_set_cal, NULL, NULL} },
7909 {NULL, NULL, cal_utils_match_buf_num} },
7910
7911 {{AFE_SIDETONE_IIR_CAL_TYPE,
7912 {NULL, NULL, NULL,
7913 afe_set_cal, NULL, NULL} },
7914 {NULL, NULL, cal_utils_match_buf_num} },
7915
7916 {{AFE_TOPOLOGY_CAL_TYPE,
7917 {NULL, NULL, NULL,
7918 afe_set_cal, NULL, NULL} },
7919 {NULL, NULL,
7920 cal_utils_match_buf_num} },
7921
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307922 {{AFE_LSM_TOPOLOGY_CAL_TYPE,
7923 {NULL, NULL, NULL,
7924 afe_set_cal, NULL, NULL} },
7925 {NULL, NULL,
7926 cal_utils_match_buf_num} },
7927
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307928 {{AFE_CUST_TOPOLOGY_CAL_TYPE,
7929 {afe_alloc_cal, afe_dealloc_cal, NULL,
7930 afe_set_cal, NULL, NULL} },
7931 {afe_map_cal_data, afe_unmap_cal_data,
7932 cal_utils_match_buf_num} },
7933
7934 {{AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE,
7935 {NULL, NULL, NULL, afe_set_cal_sp_th_vi_ftm_cfg,
7936 afe_get_cal_sp_th_vi_ftm_param, NULL} },
7937 {NULL, NULL, cal_utils_match_buf_num} },
7938
7939 {{AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE,
7940 {NULL, NULL, NULL, afe_set_cal_sp_ex_vi_ftm_cfg,
7941 afe_get_cal_sp_ex_vi_ftm_param, NULL} },
7942 {NULL, NULL, cal_utils_match_buf_num} },
7943 };
7944 pr_debug("%s:\n", __func__);
7945
7946 ret = cal_utils_create_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data,
7947 cal_type_info);
7948 if (ret < 0) {
7949 pr_err("%s: could not create cal type! %d\n",
7950 __func__, ret);
7951 ret = -EINVAL;
7952 goto err;
7953 }
7954
7955 return ret;
7956err:
7957 afe_delete_cal_data();
7958 return ret;
7959}
7960
7961int afe_map_rtac_block(struct rtac_cal_block_data *cal_block)
7962{
7963 int result = 0;
7964
7965 pr_debug("%s:\n", __func__);
7966
7967 if (cal_block == NULL) {
7968 pr_err("%s: cal_block is NULL!\n",
7969 __func__);
7970 result = -EINVAL;
7971 goto done;
7972 }
7973
7974 if (cal_block->cal_data.paddr == 0) {
7975 pr_debug("%s: No address to map!\n",
7976 __func__);
7977 result = -EINVAL;
7978 goto done;
7979 }
7980
7981 if (cal_block->map_data.map_size == 0) {
7982 pr_debug("%s: map size is 0!\n",
7983 __func__);
7984 result = -EINVAL;
7985 goto done;
7986 }
7987
7988 result = afe_cmd_memory_map(cal_block->cal_data.paddr,
7989 cal_block->map_data.map_size);
7990 if (result < 0) {
7991 pr_err("%s: afe_cmd_memory_map failed for addr = 0x%pK, size = %d, err %d\n",
7992 __func__, &cal_block->cal_data.paddr,
7993 cal_block->map_data.map_size, result);
7994 return result;
7995 }
7996 cal_block->map_data.map_handle = this_afe.mmap_handle;
7997
7998done:
7999 return result;
8000}
8001
8002int afe_unmap_rtac_block(uint32_t *mem_map_handle)
8003{
8004 int result = 0;
8005
8006 pr_debug("%s:\n", __func__);
8007
8008 if (mem_map_handle == NULL) {
8009 pr_err("%s: Map handle is NULL, nothing to unmap\n",
8010 __func__);
8011 goto done;
8012 }
8013
8014 if (*mem_map_handle == 0) {
8015 pr_debug("%s: Map handle is 0, nothing to unmap\n",
8016 __func__);
8017 goto done;
8018 }
8019
8020 result = afe_cmd_memory_unmap(*mem_map_handle);
8021 if (result) {
8022 pr_err("%s: AFE memory unmap failed %d, handle 0x%x\n",
8023 __func__, result, *mem_map_handle);
8024 goto done;
8025 } else {
8026 *mem_map_handle = 0;
8027 }
8028
8029done:
8030 return result;
8031}
8032
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308033int __init afe_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308034{
8035 int i = 0, ret;
8036
8037 atomic_set(&this_afe.state, 0);
8038 atomic_set(&this_afe.status, 0);
8039 atomic_set(&this_afe.mem_map_cal_index, -1);
8040 this_afe.apr = NULL;
8041 this_afe.dtmf_gen_rx_portid = -1;
8042 this_afe.mmap_handle = 0;
8043 this_afe.vi_tx_port = -1;
8044 this_afe.vi_rx_port = -1;
8045 this_afe.prot_cfg.mode = MSM_SPKR_PROT_DISABLED;
8046 this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
8047 this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
8048 mutex_init(&this_afe.afe_cmd_lock);
8049 for (i = 0; i < AFE_MAX_PORTS; i++) {
8050 this_afe.afe_cal_mode[i] = AFE_CAL_MODE_DEFAULT;
8051 this_afe.afe_sample_rates[i] = 0;
8052 this_afe.dev_acdb_id[i] = 0;
8053 init_waitqueue_head(&this_afe.wait[i]);
8054 }
8055 wakeup_source_init(&wl.ws, "spkr-prot");
8056 ret = afe_init_cal_data();
8057 if (ret)
8058 pr_err("%s: could not init cal data! %d\n", __func__, ret);
8059
8060 config_debug_fs_init();
8061 return 0;
8062}
8063
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05308064void afe_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308065{
Laxminath Kasam468ece32017-11-28 12:40:22 +05308066 if (this_afe.apr) {
8067 apr_reset(this_afe.apr);
8068 atomic_set(&this_afe.state, 0);
8069 this_afe.apr = NULL;
8070 rtac_set_afe_handle(this_afe.apr);
8071 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308072 afe_delete_cal_data();
8073
8074 config_debug_fs_exit();
8075 mutex_destroy(&this_afe.afe_cmd_lock);
8076 wakeup_source_trash(&wl.ws);
8077}