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