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