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