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