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