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