blob: f80d271eb9290d1e69af5502955ea60f83b18679 [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 &&
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05302975 format != ASM_MEDIA_FMT_CELT && format != ASM_MEDIA_FMT_LDAC) {
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;
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05303069 if (format == ASM_MEDIA_FMT_LDAC) {
3070 config.port.media_type.sample_rate =
3071 config.port.enc_blk_param.enc_blk_config.ldac_config.
3072 custom_config.sample_rate;
3073 } else {
3074 config.port.media_type.sample_rate =
3075 afe_config.slim_sch.sample_rate;
3076 }
3077
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303078 if (afe_in_bit_width)
3079 config.port.media_type.bit_width = afe_in_bit_width;
3080 else
3081 config.port.media_type.bit_width =
3082 afe_config.slim_sch.bit_width;
3083
3084 if (afe_in_channels)
3085 config.port.media_type.num_channels = afe_in_channels;
3086 else
3087 config.port.media_type.num_channels =
3088 afe_config.slim_sch.num_channels;
3089 config.port.media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
3090 config.port.media_type.reserved = 0;
3091
3092 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3093 if (ret) {
3094 pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
3095 __func__, port_id, ret);
3096 goto exit;
3097 }
3098
3099exit:
3100 return ret;
3101}
3102
3103static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
3104 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
3105 union afe_enc_config_data *cfg, u32 enc_format)
3106{
3107 struct afe_audioif_config_command config;
3108 int ret = 0;
3109 int cfg_type;
3110 int index = 0;
3111 enum afe_mad_type mad_type;
3112 uint16_t port_index;
3113
3114 if (!afe_config) {
3115 pr_err("%s: Error, no configuration data\n", __func__);
3116 ret = -EINVAL;
3117 return ret;
3118 }
3119
3120 if ((port_id == RT_PROXY_DAI_001_RX) ||
3121 (port_id == RT_PROXY_DAI_002_TX)) {
3122 pr_debug("%s: before incrementing pcm_afe_instance %d port_id 0x%x\n",
3123 __func__,
3124 pcm_afe_instance[port_id & 0x1], port_id);
3125 port_id = VIRTUAL_ID_TO_PORTID(port_id);
3126 pcm_afe_instance[port_id & 0x1]++;
3127 return 0;
3128 }
3129 if ((port_id == RT_PROXY_DAI_002_RX) ||
3130 (port_id == RT_PROXY_DAI_001_TX)) {
3131 pr_debug("%s: before incrementing proxy_afe_instance %d port_id 0x%x\n",
3132 __func__,
3133 proxy_afe_instance[port_id & 0x1], port_id);
3134
3135 if (!afe_close_done[port_id & 0x1]) {
3136 /*close pcm dai corresponding to the proxy dai*/
3137 afe_close(port_id - 0x10);
3138 pcm_afe_instance[port_id & 0x1]++;
3139 pr_debug("%s: reconfigure afe port again\n", __func__);
3140 }
3141 proxy_afe_instance[port_id & 0x1]++;
3142 afe_close_done[port_id & 0x1] = false;
3143 port_id = VIRTUAL_ID_TO_PORTID(port_id);
3144 }
3145
3146 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
3147
3148 index = q6audio_get_port_index(port_id);
3149 if (index < 0 || index >= AFE_MAX_PORTS) {
3150 pr_err("%s: AFE port index[%d] invalid!\n",
3151 __func__, index);
3152 return -EINVAL;
3153 }
3154 ret = q6audio_validate_port(port_id);
3155 if (ret < 0) {
3156 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
3157 return -EINVAL;
3158 }
3159
3160 ret = afe_q6_interface_prepare();
3161 if (ret != 0) {
3162 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3163 return ret;
3164 }
3165
3166 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
3167 this_afe.afe_sample_rates[index] = rate;
3168
3169 if (this_afe.rt_cb)
3170 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
3171 }
3172
3173 mutex_lock(&this_afe.afe_cmd_lock);
3174 /* Also send the topology id here: */
3175 port_index = afe_get_port_index(port_id);
3176 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
3177 /* One time call: only for first time */
3178 afe_send_custom_topology();
3179 afe_send_port_topology_id(port_id);
3180 afe_send_cal(port_id);
3181 afe_send_hw_delay(port_id, rate);
3182 }
3183
3184 /* Start SW MAD module */
3185 mad_type = afe_port_get_mad_type(port_id);
3186 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
3187 mad_type);
3188 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
3189 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
3190 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
3191 pr_err("%s: AFE isn't configured yet for\n"
3192 "HW MAD try Again\n", __func__);
3193 ret = -EAGAIN;
3194 goto fail_cmd;
3195 }
3196 ret = afe_turn_onoff_hw_mad(mad_type, true);
3197 if (ret) {
3198 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
3199 __func__, ret);
3200 goto fail_cmd;
3201 }
3202 }
3203
3204 if ((this_afe.aanc_info.aanc_active) &&
3205 (this_afe.aanc_info.aanc_tx_port == port_id)) {
3206 this_afe.aanc_info.aanc_tx_port_sample_rate = rate;
3207 port_index =
3208 afe_get_port_index(this_afe.aanc_info.aanc_rx_port);
3209 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3210 this_afe.aanc_info.aanc_rx_port_sample_rate =
3211 this_afe.afe_sample_rates[port_index];
3212 } else {
3213 pr_err("%s: Invalid port index %d\n",
3214 __func__, port_index);
3215 ret = -EINVAL;
3216 goto fail_cmd;
3217 }
3218 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
3219 this_afe.aanc_info.aanc_rx_port);
3220 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
3221 }
3222
3223 if ((port_id == AFE_PORT_ID_USB_RX) ||
3224 (port_id == AFE_PORT_ID_USB_TX)) {
3225 ret = afe_port_send_usb_dev_param(port_id, afe_config);
3226 if (ret) {
3227 pr_err("%s: AFE device param for port 0x%x failed %d\n",
3228 __func__, port_id, ret);
3229 ret = -EINVAL;
3230 goto fail_cmd;
3231 }
3232 }
3233
3234 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3235 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3236 config.hdr.pkt_size = sizeof(config);
3237 config.hdr.src_port = 0;
3238 config.hdr.dest_port = 0;
3239 config.hdr.token = index;
3240
3241 switch (port_id) {
3242 case AFE_PORT_ID_PRIMARY_PCM_RX:
3243 case AFE_PORT_ID_PRIMARY_PCM_TX:
3244 case AFE_PORT_ID_SECONDARY_PCM_RX:
3245 case AFE_PORT_ID_SECONDARY_PCM_TX:
3246 case AFE_PORT_ID_TERTIARY_PCM_RX:
3247 case AFE_PORT_ID_TERTIARY_PCM_TX:
3248 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3249 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303250 case AFE_PORT_ID_QUINARY_PCM_RX:
3251 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303252 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
3253 break;
3254 case PRIMARY_I2S_RX:
3255 case PRIMARY_I2S_TX:
3256 case SECONDARY_I2S_RX:
3257 case SECONDARY_I2S_TX:
3258 case MI2S_RX:
3259 case MI2S_TX:
3260 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3261 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3262 case AFE_PORT_ID_SECONDARY_MI2S_RX:
3263 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
3264 case AFE_PORT_ID_SECONDARY_MI2S_TX:
3265 case AFE_PORT_ID_TERTIARY_MI2S_RX:
3266 case AFE_PORT_ID_TERTIARY_MI2S_TX:
3267 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3268 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3269 case AFE_PORT_ID_QUINARY_MI2S_RX:
3270 case AFE_PORT_ID_QUINARY_MI2S_TX:
3271 case AFE_PORT_ID_SENARY_MI2S_TX:
3272 case AFE_PORT_ID_INT0_MI2S_RX:
3273 case AFE_PORT_ID_INT0_MI2S_TX:
3274 case AFE_PORT_ID_INT1_MI2S_RX:
3275 case AFE_PORT_ID_INT1_MI2S_TX:
3276 case AFE_PORT_ID_INT2_MI2S_RX:
3277 case AFE_PORT_ID_INT2_MI2S_TX:
3278 case AFE_PORT_ID_INT3_MI2S_RX:
3279 case AFE_PORT_ID_INT3_MI2S_TX:
3280 case AFE_PORT_ID_INT4_MI2S_RX:
3281 case AFE_PORT_ID_INT4_MI2S_TX:
3282 case AFE_PORT_ID_INT5_MI2S_RX:
3283 case AFE_PORT_ID_INT5_MI2S_TX:
3284 case AFE_PORT_ID_INT6_MI2S_RX:
3285 case AFE_PORT_ID_INT6_MI2S_TX:
3286 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
3287 break;
3288 case HDMI_RX:
3289 case DISPLAY_PORT_RX:
3290 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
3291 break;
3292 case VOICE_PLAYBACK_TX:
3293 case VOICE2_PLAYBACK_TX:
3294 case VOICE_RECORD_RX:
3295 case VOICE_RECORD_TX:
3296 cfg_type = AFE_PARAM_ID_PSEUDO_PORT_CONFIG;
3297 break;
3298 case SLIMBUS_0_RX:
3299 case SLIMBUS_0_TX:
3300 case SLIMBUS_1_RX:
3301 case SLIMBUS_1_TX:
3302 case SLIMBUS_2_RX:
3303 case SLIMBUS_2_TX:
3304 case SLIMBUS_3_RX:
3305 case SLIMBUS_3_TX:
3306 case SLIMBUS_4_RX:
3307 case SLIMBUS_4_TX:
3308 case SLIMBUS_5_RX:
3309 case SLIMBUS_5_TX:
3310 case SLIMBUS_6_RX:
3311 case SLIMBUS_6_TX:
3312 case SLIMBUS_7_RX:
3313 case SLIMBUS_7_TX:
3314 case SLIMBUS_8_RX:
3315 case SLIMBUS_8_TX:
3316 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
3317 break;
3318 case AFE_PORT_ID_USB_RX:
3319 case AFE_PORT_ID_USB_TX:
3320 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
3321 break;
3322 case RT_PROXY_PORT_001_RX:
3323 case RT_PROXY_PORT_001_TX:
3324 cfg_type = AFE_PARAM_ID_RT_PROXY_CONFIG;
3325 break;
3326 case INT_BT_SCO_RX:
3327 case INT_BT_A2DP_RX:
3328 case INT_BT_SCO_TX:
3329 case INT_FM_RX:
3330 case INT_FM_TX:
3331 cfg_type = AFE_PARAM_ID_INTERNAL_BT_FM_CONFIG;
3332 break;
3333 default:
3334 pr_err("%s: Invalid port id 0x%x\n", __func__, port_id);
3335 ret = -EINVAL;
3336 goto fail_cmd;
3337 }
3338 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3339 config.param.port_id = q6audio_get_port_id(port_id);
3340 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
3341 sizeof(config.param);
3342 config.param.payload_address_lsw = 0x00;
3343 config.param.payload_address_msw = 0x00;
3344 config.param.mem_map_handle = 0x00;
3345 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3346 config.pdata.param_id = cfg_type;
3347 config.pdata.param_size = sizeof(config.port);
3348
3349 config.port = *afe_config;
3350 if ((enc_format != ASM_MEDIA_FMT_NONE) &&
3351 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
3352 config.port.slim_sch.data_format =
3353 AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED;
3354 }
3355 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3356 if (ret) {
3357 pr_err("%s: AFE enable for port 0x%x failed %d\n",
3358 __func__, port_id, ret);
3359 goto fail_cmd;
3360 }
3361
3362 if ((enc_format != ASM_MEDIA_FMT_NONE) &&
3363 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
3364 pr_debug("%s: Found AFE encoder support for SLIMBUS enc_format = %d\n",
3365 __func__, enc_format);
3366 ret = q6afe_send_enc_config(port_id, cfg, enc_format,
3367 *afe_config, afe_in_channels,
3368 afe_in_bit_width);
3369 if (ret) {
3370 pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
3371 __func__, port_id, ret);
3372 goto fail_cmd;
3373 }
3374 }
3375
3376 port_index = afe_get_port_index(port_id);
3377 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3378 /*
3379 * If afe_port_start() for tx port called before
3380 * rx port, then aanc rx sample rate is zero. So,
3381 * AANC state machine in AFE will not get triggered.
3382 * Make sure to check whether aanc is active during
3383 * afe_port_start() for rx port and if aanc rx
3384 * sample rate is zero, call afe_aanc_start to configure
3385 * aanc with valid sample rates.
3386 */
3387 if (this_afe.aanc_info.aanc_active &&
3388 !this_afe.aanc_info.aanc_rx_port_sample_rate) {
3389 this_afe.aanc_info.aanc_rx_port_sample_rate =
3390 this_afe.afe_sample_rates[port_index];
3391 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
3392 this_afe.aanc_info.aanc_rx_port);
3393 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
3394 }
3395 } else {
3396 pr_err("%s: Invalid port index %d\n", __func__, port_index);
3397 ret = -EINVAL;
3398 goto fail_cmd;
3399 }
3400 ret = afe_send_cmd_port_start(port_id);
3401
3402fail_cmd:
3403 mutex_unlock(&this_afe.afe_cmd_lock);
3404 return ret;
3405}
3406
3407/**
3408 * afe_port_start - to configure AFE session with
3409 * specified port configuration
3410 *
3411 * @port_id: AFE port id number
3412 * @afe_config: port configutation
3413 * @rate: sampling rate of port
3414 *
3415 * Returns 0 on success or error value on port start failure.
3416 */
3417int afe_port_start(u16 port_id, union afe_port_config *afe_config,
3418 u32 rate)
3419{
3420 return __afe_port_start(port_id, afe_config, rate,
3421 0, 0, NULL, ASM_MEDIA_FMT_NONE);
3422}
3423EXPORT_SYMBOL(afe_port_start);
3424
3425/**
3426 * afe_port_start_v2 - to configure AFE session with
3427 * specified port configuration and encoder params
3428 *
3429 * @port_id: AFE port id number
3430 * @afe_config: port configutation
3431 * @rate: sampling rate of port
3432 * @cfg: AFE encoder configuration information to setup encoder
3433 * @afe_in_channels: AFE input channel configuration, this needs
3434 * update only if input channel is differ from AFE output
3435 *
3436 * Returns 0 on success or error value on port start failure.
3437 */
3438int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
3439 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
3440 struct afe_enc_config *enc_cfg)
3441{
3442 return __afe_port_start(port_id, afe_config, rate,
3443 afe_in_channels, afe_in_bit_width,
3444 &enc_cfg->data, enc_cfg->format);
3445}
3446EXPORT_SYMBOL(afe_port_start_v2);
3447
3448int afe_get_port_index(u16 port_id)
3449{
3450 switch (port_id) {
3451 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
3452 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
3453 case AFE_PORT_ID_PRIMARY_PCM_RX:
3454 return IDX_AFE_PORT_ID_PRIMARY_PCM_RX;
3455 case AFE_PORT_ID_PRIMARY_PCM_TX:
3456 return IDX_AFE_PORT_ID_PRIMARY_PCM_TX;
3457 case AFE_PORT_ID_SECONDARY_PCM_RX:
3458 return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
3459 case AFE_PORT_ID_SECONDARY_PCM_TX:
3460 return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
3461 case AFE_PORT_ID_TERTIARY_PCM_RX:
3462 return IDX_AFE_PORT_ID_TERTIARY_PCM_RX;
3463 case AFE_PORT_ID_TERTIARY_PCM_TX:
3464 return IDX_AFE_PORT_ID_TERTIARY_PCM_TX;
3465 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3466 return IDX_AFE_PORT_ID_QUATERNARY_PCM_RX;
3467 case AFE_PORT_ID_QUATERNARY_PCM_TX:
3468 return IDX_AFE_PORT_ID_QUATERNARY_PCM_TX;
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303469 case AFE_PORT_ID_QUINARY_PCM_RX:
3470 return IDX_AFE_PORT_ID_QUINARY_PCM_RX;
3471 case AFE_PORT_ID_QUINARY_PCM_TX:
3472 return IDX_AFE_PORT_ID_QUINARY_PCM_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303473 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
3474 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
3475 case MI2S_RX: return IDX_MI2S_RX;
3476 case MI2S_TX: return IDX_MI2S_TX;
3477 case HDMI_RX: return IDX_HDMI_RX;
3478 case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX;
3479 case AFE_PORT_ID_SPDIF_RX: return IDX_SPDIF_RX;
3480 case RSVD_2: return IDX_RSVD_2;
3481 case RSVD_3: return IDX_RSVD_3;
3482 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
3483 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
3484 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
3485 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
3486 case VOICE2_PLAYBACK_TX: return IDX_VOICE2_PLAYBACK_TX;
3487 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
3488 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
3489 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
3490 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
3491 case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
3492 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
3493 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
3494 case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
3495 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
3496 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
3497 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
3498 case INT_FM_RX: return IDX_INT_FM_RX;
3499 case INT_FM_TX: return IDX_INT_FM_TX;
3500 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
3501 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
3502 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
3503 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
3504 case SLIMBUS_5_RX: return IDX_SLIMBUS_5_RX;
3505 case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX;
3506 case SLIMBUS_6_RX: return IDX_SLIMBUS_6_RX;
3507 case SLIMBUS_6_TX: return IDX_SLIMBUS_6_TX;
3508 case SLIMBUS_7_RX: return IDX_SLIMBUS_7_RX;
3509 case SLIMBUS_7_TX: return IDX_SLIMBUS_7_TX;
3510 case SLIMBUS_8_RX: return IDX_SLIMBUS_8_RX;
3511 case SLIMBUS_8_TX: return IDX_SLIMBUS_8_TX;
3512 case AFE_PORT_ID_USB_RX: return IDX_AFE_PORT_ID_USB_RX;
3513 case AFE_PORT_ID_USB_TX: return IDX_AFE_PORT_ID_USB_TX;
3514 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3515 return IDX_AFE_PORT_ID_PRIMARY_MI2S_RX;
3516 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3517 return IDX_AFE_PORT_ID_PRIMARY_MI2S_TX;
3518 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3519 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
3520 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3521 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX;
3522 case AFE_PORT_ID_SECONDARY_MI2S_RX:
3523 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX;
3524 case AFE_PORT_ID_SECONDARY_MI2S_TX:
3525 return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX;
3526 case AFE_PORT_ID_TERTIARY_MI2S_RX:
3527 return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX;
3528 case AFE_PORT_ID_TERTIARY_MI2S_TX:
3529 return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX;
3530 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
3531 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_SD1;
3532 case AFE_PORT_ID_QUINARY_MI2S_RX:
3533 return IDX_AFE_PORT_ID_QUINARY_MI2S_RX;
3534 case AFE_PORT_ID_QUINARY_MI2S_TX:
3535 return IDX_AFE_PORT_ID_QUINARY_MI2S_TX;
3536 case AFE_PORT_ID_SENARY_MI2S_TX:
3537 return IDX_AFE_PORT_ID_SENARY_MI2S_TX;
3538 case AFE_PORT_ID_PRIMARY_TDM_RX:
3539 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_0;
3540 case AFE_PORT_ID_PRIMARY_TDM_TX:
3541 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_0;
3542 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
3543 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_1;
3544 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
3545 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_1;
3546 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
3547 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_2;
3548 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
3549 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_2;
3550 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
3551 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_3;
3552 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
3553 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_3;
3554 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
3555 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_4;
3556 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
3557 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_4;
3558 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
3559 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_5;
3560 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
3561 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_5;
3562 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
3563 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_6;
3564 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
3565 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_6;
3566 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
3567 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_7;
3568 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
3569 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_7;
3570 case AFE_PORT_ID_SECONDARY_TDM_RX:
3571 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_0;
3572 case AFE_PORT_ID_SECONDARY_TDM_TX:
3573 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_0;
3574 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
3575 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_1;
3576 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
3577 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_1;
3578 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
3579 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_2;
3580 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
3581 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_2;
3582 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
3583 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_3;
3584 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
3585 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_3;
3586 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
3587 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_4;
3588 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
3589 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_4;
3590 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
3591 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_5;
3592 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
3593 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_5;
3594 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
3595 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_6;
3596 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
3597 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_6;
3598 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
3599 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_7;
3600 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
3601 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_7;
3602 case AFE_PORT_ID_TERTIARY_TDM_RX:
3603 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_0;
3604 case AFE_PORT_ID_TERTIARY_TDM_TX:
3605 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_0;
3606 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
3607 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_1;
3608 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
3609 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_1;
3610 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
3611 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_2;
3612 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
3613 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_2;
3614 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
3615 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_3;
3616 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
3617 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_3;
3618 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
3619 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_4;
3620 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
3621 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_4;
3622 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
3623 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_5;
3624 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
3625 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_5;
3626 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
3627 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_6;
3628 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
3629 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_6;
3630 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
3631 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_7;
3632 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
3633 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_7;
3634 case AFE_PORT_ID_QUATERNARY_TDM_RX:
3635 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_0;
3636 case AFE_PORT_ID_QUATERNARY_TDM_TX:
3637 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_0;
3638 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
3639 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_1;
3640 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
3641 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_1;
3642 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
3643 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_2;
3644 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
3645 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_2;
3646 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
3647 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_3;
3648 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
3649 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_3;
3650 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
3651 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_4;
3652 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
3653 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_4;
3654 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
3655 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_5;
3656 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
3657 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_5;
3658 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
3659 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_6;
3660 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
3661 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_6;
3662 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
3663 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_7;
3664 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
3665 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_7;
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303666 case AFE_PORT_ID_QUINARY_TDM_RX:
3667 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_0;
3668 case AFE_PORT_ID_QUINARY_TDM_TX:
3669 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_0;
3670 case AFE_PORT_ID_QUINARY_TDM_RX_1:
3671 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_1;
3672 case AFE_PORT_ID_QUINARY_TDM_TX_1:
3673 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_1;
3674 case AFE_PORT_ID_QUINARY_TDM_RX_2:
3675 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_2;
3676 case AFE_PORT_ID_QUINARY_TDM_TX_2:
3677 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_2;
3678 case AFE_PORT_ID_QUINARY_TDM_RX_3:
3679 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_3;
3680 case AFE_PORT_ID_QUINARY_TDM_TX_3:
3681 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_3;
3682 case AFE_PORT_ID_QUINARY_TDM_RX_4:
3683 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_4;
3684 case AFE_PORT_ID_QUINARY_TDM_TX_4:
3685 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_4;
3686 case AFE_PORT_ID_QUINARY_TDM_RX_5:
3687 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_5;
3688 case AFE_PORT_ID_QUINARY_TDM_TX_5:
3689 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_5;
3690 case AFE_PORT_ID_QUINARY_TDM_RX_6:
3691 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_6;
3692 case AFE_PORT_ID_QUINARY_TDM_TX_6:
3693 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_6;
3694 case AFE_PORT_ID_QUINARY_TDM_RX_7:
3695 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_7;
3696 case AFE_PORT_ID_QUINARY_TDM_TX_7:
3697 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_7;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303698 case AFE_PORT_ID_INT0_MI2S_RX:
3699 return IDX_AFE_PORT_ID_INT0_MI2S_RX;
3700 case AFE_PORT_ID_INT0_MI2S_TX:
3701 return IDX_AFE_PORT_ID_INT0_MI2S_TX;
3702 case AFE_PORT_ID_INT1_MI2S_RX:
3703 return IDX_AFE_PORT_ID_INT1_MI2S_RX;
3704 case AFE_PORT_ID_INT1_MI2S_TX:
3705 return IDX_AFE_PORT_ID_INT1_MI2S_TX;
3706 case AFE_PORT_ID_INT2_MI2S_RX:
3707 return IDX_AFE_PORT_ID_INT2_MI2S_RX;
3708 case AFE_PORT_ID_INT2_MI2S_TX:
3709 return IDX_AFE_PORT_ID_INT2_MI2S_TX;
3710 case AFE_PORT_ID_INT3_MI2S_RX:
3711 return IDX_AFE_PORT_ID_INT3_MI2S_RX;
3712 case AFE_PORT_ID_INT3_MI2S_TX:
3713 return IDX_AFE_PORT_ID_INT3_MI2S_TX;
3714 case AFE_PORT_ID_INT4_MI2S_RX:
3715 return IDX_AFE_PORT_ID_INT4_MI2S_RX;
3716 case AFE_PORT_ID_INT4_MI2S_TX:
3717 return IDX_AFE_PORT_ID_INT4_MI2S_TX;
3718 case AFE_PORT_ID_INT5_MI2S_RX:
3719 return IDX_AFE_PORT_ID_INT5_MI2S_RX;
3720 case AFE_PORT_ID_INT5_MI2S_TX:
3721 return IDX_AFE_PORT_ID_INT5_MI2S_TX;
3722 case AFE_PORT_ID_INT6_MI2S_RX:
3723 return IDX_AFE_PORT_ID_INT6_MI2S_RX;
3724 case AFE_PORT_ID_INT6_MI2S_TX:
3725 return IDX_AFE_PORT_ID_INT6_MI2S_TX;
3726 default:
3727 pr_err("%s: port 0x%x\n", __func__, port_id);
3728 return -EINVAL;
3729 }
3730}
3731
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303732/**
3733 * afe_open -
3734 * command to open AFE port
3735 *
3736 * @port_id: AFE port id
3737 * @afe_config: AFE port config to pass
3738 * @rate: sample rate
3739 *
3740 * Returns 0 on success or error on failure
3741 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303742int afe_open(u16 port_id,
3743 union afe_port_config *afe_config, int rate)
3744{
3745 struct afe_port_cmd_device_start start;
3746 struct afe_audioif_config_command config;
3747 int ret = 0;
3748 int cfg_type;
3749 int index = 0;
3750
3751 if (!afe_config) {
3752 pr_err("%s: Error, no configuration data\n", __func__);
3753 ret = -EINVAL;
3754 return ret;
3755 }
3756
3757 pr_err("%s: port_id 0x%x rate %d\n", __func__, port_id, rate);
3758
3759 index = q6audio_get_port_index(port_id);
3760 if (index < 0 || index >= AFE_MAX_PORTS) {
3761 pr_err("%s: AFE port index[%d] invalid!\n",
3762 __func__, index);
3763 return -EINVAL;
3764 }
3765 ret = q6audio_validate_port(port_id);
3766 if (ret < 0) {
3767 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
3768 return -EINVAL;
3769 }
3770
3771 if ((port_id == RT_PROXY_DAI_001_RX) ||
3772 (port_id == RT_PROXY_DAI_002_TX)) {
3773 pr_err("%s: wrong port 0x%x\n", __func__, port_id);
3774 return -EINVAL;
3775 }
3776 if ((port_id == RT_PROXY_DAI_002_RX) ||
3777 (port_id == RT_PROXY_DAI_001_TX))
3778 port_id = VIRTUAL_ID_TO_PORTID(port_id);
3779
3780 ret = afe_q6_interface_prepare();
3781 if (ret != 0) {
3782 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3783 return -EINVAL;
3784 }
3785
3786 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
3787 this_afe.afe_sample_rates[index] = rate;
3788
3789 if (this_afe.rt_cb)
3790 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
3791 }
3792
3793 /* Also send the topology id here: */
3794 afe_send_custom_topology(); /* One time call: only for first time */
3795 afe_send_port_topology_id(port_id);
3796
3797 ret = q6audio_validate_port(port_id);
3798 if (ret < 0) {
3799 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
3800 __func__, port_id, ret);
3801 return -EINVAL;
3802 }
3803 mutex_lock(&this_afe.afe_cmd_lock);
3804
3805 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3806 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3807 config.hdr.pkt_size = sizeof(config);
3808 config.hdr.src_port = 0;
3809 config.hdr.dest_port = 0;
3810 config.hdr.token = index;
3811 switch (port_id) {
3812 case PRIMARY_I2S_RX:
3813 case PRIMARY_I2S_TX:
3814 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
3815 break;
3816 case AFE_PORT_ID_PRIMARY_PCM_RX:
3817 case AFE_PORT_ID_PRIMARY_PCM_TX:
3818 case AFE_PORT_ID_SECONDARY_PCM_RX:
3819 case AFE_PORT_ID_SECONDARY_PCM_TX:
3820 case AFE_PORT_ID_TERTIARY_PCM_RX:
3821 case AFE_PORT_ID_TERTIARY_PCM_TX:
3822 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3823 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303824 case AFE_PORT_ID_QUINARY_PCM_RX:
3825 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303826 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
3827 break;
3828 case SECONDARY_I2S_RX:
3829 case SECONDARY_I2S_TX:
3830 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3831 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3832 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3833 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3834 case MI2S_RX:
3835 case MI2S_TX:
3836 case AFE_PORT_ID_QUINARY_MI2S_RX:
3837 case AFE_PORT_ID_QUINARY_MI2S_TX:
3838 case AFE_PORT_ID_SENARY_MI2S_TX:
3839 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
3840 break;
3841 case HDMI_RX:
3842 case DISPLAY_PORT_RX:
3843 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
3844 break;
3845 case SLIMBUS_0_RX:
3846 case SLIMBUS_0_TX:
3847 case SLIMBUS_1_RX:
3848 case SLIMBUS_1_TX:
3849 case SLIMBUS_2_RX:
3850 case SLIMBUS_2_TX:
3851 case SLIMBUS_3_RX:
3852 case SLIMBUS_3_TX:
3853 case SLIMBUS_4_RX:
3854 case SLIMBUS_4_TX:
3855 case SLIMBUS_5_RX:
3856 case SLIMBUS_6_RX:
3857 case SLIMBUS_6_TX:
3858 case SLIMBUS_7_RX:
3859 case SLIMBUS_7_TX:
3860 case SLIMBUS_8_RX:
3861 case SLIMBUS_8_TX:
3862 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
3863 break;
3864 case AFE_PORT_ID_USB_RX:
3865 case AFE_PORT_ID_USB_TX:
3866 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
3867 break;
3868 default:
3869 pr_err("%s: Invalid port id 0x%x\n",
3870 __func__, port_id);
3871 ret = -EINVAL;
3872 goto fail_cmd;
3873 }
3874 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3875 config.param.port_id = q6audio_get_port_id(port_id);
3876 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr)
3877 - sizeof(config.param);
3878 config.param.payload_address_lsw = 0x00;
3879 config.param.payload_address_msw = 0x00;
3880 config.param.mem_map_handle = 0x00;
3881 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3882 config.pdata.param_id = cfg_type;
3883 config.pdata.param_size = sizeof(config.port);
3884
3885 config.port = *afe_config;
3886 pr_debug("%s: param PL size=%d iparam_size[%d][%zd %zd %zd %zd] param_id[0x%x]\n",
3887 __func__, config.param.payload_size, config.pdata.param_size,
3888 sizeof(config), sizeof(config.param), sizeof(config.port),
3889 sizeof(struct apr_hdr), config.pdata.param_id);
3890
3891 ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
3892 if (ret) {
3893 pr_err("%s: AFE enable for port 0x%x opcode[0x%x]failed %d\n",
3894 __func__, port_id, cfg_type, ret);
3895 goto fail_cmd;
3896 }
3897 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3898 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3899 start.hdr.pkt_size = sizeof(start);
3900 start.hdr.src_port = 0;
3901 start.hdr.dest_port = 0;
3902 start.hdr.token = index;
3903 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
3904 start.port_id = q6audio_get_port_id(port_id);
3905 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
3906 __func__, start.hdr.opcode, start.port_id);
3907
3908 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
3909 if (ret) {
3910 pr_err("%s: AFE enable for port 0x%x failed %d\n", __func__,
3911 port_id, ret);
3912 goto fail_cmd;
3913 }
3914
3915fail_cmd:
3916 mutex_unlock(&this_afe.afe_cmd_lock);
3917 return ret;
3918}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303919EXPORT_SYMBOL(afe_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303920
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303921/**
3922 * afe_loopback -
3923 * command to set loopback between AFE ports
3924 *
3925 * @enable: enable or disable loopback
3926 * @rx_port: AFE RX port ID
3927 * @tx_port: AFE TX port ID
3928 *
3929 * Returns 0 on success or error on failure
3930 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303931int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
3932{
3933 struct afe_loopback_cfg_v1 lb_cmd;
3934 int ret = 0;
3935 int index = 0;
3936
3937 if (rx_port == MI2S_RX)
3938 rx_port = AFE_PORT_ID_PRIMARY_MI2S_RX;
3939 if (tx_port == MI2S_TX)
3940 tx_port = AFE_PORT_ID_PRIMARY_MI2S_TX;
3941
3942 ret = afe_q6_interface_prepare();
3943 if (ret != 0) {
3944 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3945 return ret;
3946 }
3947
3948 index = q6audio_get_port_index(rx_port);
3949 if (index < 0 || index >= AFE_MAX_PORTS) {
3950 pr_err("%s: AFE port index[%d] invalid!\n",
3951 __func__, index);
3952 return -EINVAL;
3953 }
3954 ret = q6audio_validate_port(rx_port);
3955 if (ret < 0) {
3956 pr_err("%s: Invalid port 0x%x ret %d", __func__, rx_port, ret);
3957 return -EINVAL;
3958 }
3959
3960 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3961 APR_HDR_LEN(20), APR_PKT_VER);
3962 lb_cmd.hdr.pkt_size = sizeof(lb_cmd);
3963 lb_cmd.hdr.src_port = 0;
3964 lb_cmd.hdr.dest_port = 0;
3965 lb_cmd.hdr.token = index;
3966 lb_cmd.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
3967 lb_cmd.param.port_id = tx_port;
3968 lb_cmd.param.payload_size = (sizeof(lb_cmd) - sizeof(struct apr_hdr) -
3969 sizeof(struct afe_port_cmd_set_param_v2));
3970 lb_cmd.param.payload_address_lsw = 0x00;
3971 lb_cmd.param.payload_address_msw = 0x00;
3972 lb_cmd.param.mem_map_handle = 0x00;
3973 lb_cmd.pdata.module_id = AFE_MODULE_LOOPBACK;
3974 lb_cmd.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
3975 lb_cmd.pdata.param_size = lb_cmd.param.payload_size -
3976 sizeof(struct afe_port_param_data_v2);
3977
3978 lb_cmd.dst_port_id = rx_port;
3979 lb_cmd.routing_mode = LB_MODE_DEFAULT;
3980 lb_cmd.enable = (enable ? 1 : 0);
3981 lb_cmd.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
3982
3983 ret = afe_apr_send_pkt(&lb_cmd, &this_afe.wait[index]);
3984 if (ret)
3985 pr_err("%s: AFE loopback failed %d\n", __func__, ret);
3986 return ret;
3987}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303988EXPORT_SYMBOL(afe_loopback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303989
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303990/**
3991 * afe_loopback_gain -
3992 * command to set gain for AFE loopback
3993 *
3994 * @port_id: AFE port id
3995 * @volume: gain value to set
3996 *
3997 * Returns 0 on success or error on failure
3998 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303999int afe_loopback_gain(u16 port_id, u16 volume)
4000{
4001 struct afe_loopback_gain_per_path_param set_param;
4002 int ret = 0;
4003 int index = 0;
4004
4005 if (this_afe.apr == NULL) {
4006 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4007 0xFFFFFFFF, &this_afe);
4008 pr_debug("%s: Register AFE\n", __func__);
4009 if (this_afe.apr == NULL) {
4010 pr_err("%s: Unable to register AFE\n", __func__);
4011 ret = -ENODEV;
4012 return ret;
4013 }
4014 rtac_set_afe_handle(this_afe.apr);
4015 }
4016
4017 ret = q6audio_validate_port(port_id);
4018 if (ret < 0) {
4019 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
4020 __func__, port_id, ret);
4021 ret = -EINVAL;
4022 goto fail_cmd;
4023 }
4024 index = q6audio_get_port_index(port_id);
4025 if (index < 0 || index >= AFE_MAX_PORTS) {
4026 pr_err("%s: AFE port index[%d] invalid!\n",
4027 __func__, index);
4028 return -EINVAL;
4029 }
4030 ret = q6audio_validate_port(port_id);
4031 if (ret < 0) {
4032 pr_err("%s: Invalid port 0x%x ret %d",
4033 __func__, port_id, ret);
4034 return -EINVAL;
4035 }
4036
4037 /* RX ports numbers are even .TX ports numbers are odd. */
4038 if (port_id % 2 == 0) {
4039 pr_err("%s: Failed : afe loopback gain only for TX ports. port_id %d\n",
4040 __func__, port_id);
4041 ret = -EINVAL;
4042 goto fail_cmd;
4043 }
4044
4045 pr_debug("%s: port 0x%x volume %d\n", __func__, port_id, volume);
4046
4047 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4048 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4049 set_param.hdr.pkt_size = sizeof(set_param);
4050 set_param.hdr.src_port = 0;
4051 set_param.hdr.dest_port = 0;
4052 set_param.hdr.token = index;
4053 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
4054
4055 set_param.param.port_id = port_id;
4056 set_param.param.payload_size =
4057 (sizeof(struct afe_loopback_gain_per_path_param) -
4058 sizeof(struct apr_hdr) - sizeof(struct afe_port_cmd_set_param_v2));
4059 set_param.param.payload_address_lsw = 0;
4060 set_param.param.payload_address_msw = 0;
4061 set_param.param.mem_map_handle = 0;
4062
4063 set_param.pdata.module_id = AFE_MODULE_LOOPBACK;
4064 set_param.pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
4065 set_param.pdata.param_size =
4066 (set_param.param.payload_size -
4067 sizeof(struct afe_port_param_data_v2));
4068 set_param.rx_port_id = port_id;
4069 set_param.gain = volume;
4070
4071 ret = afe_apr_send_pkt(&set_param, &this_afe.wait[index]);
4072 if (ret) {
4073 pr_err("%s: AFE param set failed for port 0x%x ret %d\n",
4074 __func__, port_id, ret);
4075 goto fail_cmd;
4076 }
4077
4078fail_cmd:
4079 return ret;
4080}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304081EXPORT_SYMBOL(afe_loopback_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304082
4083int afe_pseudo_port_start_nowait(u16 port_id)
4084{
4085 struct afe_pseudoport_start_command start;
4086 int ret = 0;
4087
4088 pr_debug("%s: port_id=0x%x\n", __func__, port_id);
4089 if (this_afe.apr == NULL) {
4090 pr_err("%s: AFE APR is not registered\n", __func__);
4091 return -ENODEV;
4092 }
4093
4094
4095 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4096 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4097 start.hdr.pkt_size = sizeof(start);
4098 start.hdr.src_port = 0;
4099 start.hdr.dest_port = 0;
4100 start.hdr.token = 0;
4101 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
4102 start.port_id = port_id;
4103 start.timing = 1;
4104
4105 ret = afe_apr_send_pkt(&start, NULL);
4106 if (ret) {
4107 pr_err("%s: AFE enable for port 0x%x failed %d\n",
4108 __func__, port_id, ret);
4109 return ret;
4110 }
4111 return 0;
4112}
4113
4114int afe_start_pseudo_port(u16 port_id)
4115{
4116 int ret = 0;
4117 struct afe_pseudoport_start_command start;
4118 int index = 0;
4119
4120 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4121
4122 ret = afe_q6_interface_prepare();
4123 if (ret != 0) {
4124 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4125 return ret;
4126 }
4127
4128 index = q6audio_get_port_index(port_id);
4129 if (index < 0 || index >= AFE_MAX_PORTS) {
4130 pr_err("%s: AFE port index[%d] invalid!\n",
4131 __func__, index);
4132 return -EINVAL;
4133 }
4134 ret = q6audio_validate_port(port_id);
4135 if (ret < 0) {
4136 pr_err("%s: Invalid port 0x%x ret %d",
4137 __func__, port_id, ret);
4138 return -EINVAL;
4139 }
4140
4141 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4142 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4143 start.hdr.pkt_size = sizeof(start);
4144 start.hdr.src_port = 0;
4145 start.hdr.dest_port = 0;
4146 start.hdr.token = 0;
4147 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
4148 start.port_id = port_id;
4149 start.timing = 1;
4150 start.hdr.token = index;
4151
4152 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
4153 if (ret)
4154 pr_err("%s: AFE enable for port 0x%x failed %d\n",
4155 __func__, port_id, ret);
4156 return ret;
4157}
4158
4159int afe_pseudo_port_stop_nowait(u16 port_id)
4160{
4161 int ret = 0;
4162 struct afe_pseudoport_stop_command stop;
4163 int index = 0;
4164
4165 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4166
4167 if (this_afe.apr == NULL) {
4168 pr_err("%s: AFE is already closed\n", __func__);
4169 return -EINVAL;
4170 }
4171 index = q6audio_get_port_index(port_id);
4172 if (index < 0 || index >= AFE_MAX_PORTS) {
4173 pr_err("%s: AFE port index[%d] invalid!\n",
4174 __func__, index);
4175 return -EINVAL;
4176 }
4177 ret = q6audio_validate_port(port_id);
4178 if (ret < 0) {
4179 pr_err("%s: Invalid port 0x%x ret %d",
4180 __func__, port_id, ret);
4181 return -EINVAL;
4182 }
4183
4184 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4185 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4186 stop.hdr.pkt_size = sizeof(stop);
4187 stop.hdr.src_port = 0;
4188 stop.hdr.dest_port = 0;
4189 stop.hdr.token = 0;
4190 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
4191 stop.port_id = port_id;
4192 stop.reserved = 0;
4193 stop.hdr.token = index;
4194
4195 ret = afe_apr_send_pkt(&stop, NULL);
4196 if (ret)
4197 pr_err("%s: AFE close failed %d\n", __func__, ret);
4198
4199 return ret;
4200}
4201
4202int afe_port_group_set_param(u16 group_id,
4203 union afe_port_group_config *afe_group_config)
4204{
4205 int ret;
4206 struct afe_port_group_create config;
4207 int cfg_type;
4208
4209 if (!afe_group_config) {
4210 pr_err("%s: Error, no configuration data\n", __func__);
4211 return -EINVAL;
4212 }
4213
4214 pr_debug("%s: group id: 0x%x\n", __func__, group_id);
4215
4216 ret = afe_q6_interface_prepare();
4217 if (ret != 0) {
4218 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4219 return ret;
4220 }
4221
4222 switch (group_id) {
4223 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX:
4224 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX:
4225 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_RX:
4226 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_TX:
4227 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_RX:
4228 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_TX:
4229 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_RX:
4230 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304231 case AFE_GROUP_DEVICE_ID_QUINARY_TDM_RX:
4232 case AFE_GROUP_DEVICE_ID_QUINARY_TDM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304233 cfg_type = AFE_PARAM_ID_GROUP_DEVICE_TDM_CONFIG;
4234 break;
4235 default:
4236 pr_err("%s: Invalid group id 0x%x\n", __func__, group_id);
4237 return -EINVAL;
4238 }
4239
4240 memset(&config, 0, sizeof(config));
4241 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4242 APR_HDR_LEN(APR_HDR_SIZE),
4243 APR_PKT_VER);
4244 config.hdr.pkt_size = sizeof(config);
4245 config.hdr.src_port = 0;
4246 config.hdr.dest_port = 0;
4247 config.hdr.token = IDX_GLOBAL_CFG;
4248 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
4249
4250 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
4251 sizeof(config.param);
4252 config.param.payload_address_lsw = 0x00;
4253 config.param.payload_address_msw = 0x00;
4254 config.param.mem_map_handle = 0x00;
4255 config.pdata.module_id = AFE_MODULE_GROUP_DEVICE;
4256 config.pdata.param_id = cfg_type;
4257 config.pdata.param_size = sizeof(config.data);
4258 config.data = *afe_group_config;
4259
4260 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
4261 if (ret)
4262 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_CFG failed %d\n",
4263 __func__, ret);
4264
4265 return ret;
4266}
4267
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304268/**
4269 * afe_port_group_enable -
4270 * command to enable AFE port group
4271 *
4272 * @group_id: group ID for AFE port group
4273 * @afe_group_config: config for AFE group
4274 * @enable: flag to indicate enable or disable
4275 *
4276 * Returns 0 on success or error on failure
4277 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304278int afe_port_group_enable(u16 group_id,
4279 union afe_port_group_config *afe_group_config,
4280 u16 enable)
4281{
4282 int ret;
4283 struct afe_port_group_create config;
4284
4285 pr_debug("%s: group id: 0x%x enable: %d\n", __func__,
4286 group_id, enable);
4287
4288 ret = afe_q6_interface_prepare();
4289 if (ret != 0) {
4290 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4291 return ret;
4292 }
4293
4294 if (enable) {
4295 ret = afe_port_group_set_param(group_id, afe_group_config);
4296 if (ret < 0) {
4297 pr_err("%s: afe send failed %d\n", __func__, ret);
4298 return ret;
4299 }
4300 }
4301
4302 memset(&config, 0, sizeof(config));
4303 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4304 APR_HDR_LEN(APR_HDR_SIZE),
4305 APR_PKT_VER);
4306 config.hdr.pkt_size = sizeof(config);
4307 config.hdr.src_port = 0;
4308 config.hdr.dest_port = 0;
4309 config.hdr.token = IDX_GLOBAL_CFG;
4310 config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
4311
4312 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
4313 sizeof(config.param);
4314 config.param.payload_address_lsw = 0x00;
4315 config.param.payload_address_msw = 0x00;
4316 config.param.mem_map_handle = 0x00;
4317 config.pdata.module_id = AFE_MODULE_GROUP_DEVICE;
4318 config.pdata.param_id = AFE_PARAM_ID_GROUP_DEVICE_ENABLE;
4319 config.pdata.param_size = sizeof(config.data);
4320 config.data.group_enable.group_id = group_id;
4321 config.data.group_enable.enable = enable;
4322
4323 ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
4324 if (ret)
4325 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_ENABLE failed %d\n",
4326 __func__, ret);
4327
4328 return ret;
4329}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304330EXPORT_SYMBOL(afe_port_group_enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304331
4332int afe_stop_pseudo_port(u16 port_id)
4333{
4334 int ret = 0;
4335 struct afe_pseudoport_stop_command stop;
4336 int index = 0;
4337
4338 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4339
4340 if (this_afe.apr == NULL) {
4341 pr_err("%s: AFE is already closed\n", __func__);
4342 return -EINVAL;
4343 }
4344
4345 index = q6audio_get_port_index(port_id);
4346 if (index < 0 || index >= AFE_MAX_PORTS) {
4347 pr_err("%s: AFE port index[%d] invalid!\n",
4348 __func__, index);
4349 return -EINVAL;
4350 }
4351 ret = q6audio_validate_port(port_id);
4352 if (ret < 0) {
4353 pr_err("%s: Invalid port 0x%x ret %d\n",
4354 __func__, port_id, ret);
4355 return -EINVAL;
4356 }
4357
4358 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4359 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4360 stop.hdr.pkt_size = sizeof(stop);
4361 stop.hdr.src_port = 0;
4362 stop.hdr.dest_port = 0;
4363 stop.hdr.token = 0;
4364 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
4365 stop.port_id = port_id;
4366 stop.reserved = 0;
4367 stop.hdr.token = index;
4368
4369 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
4370 if (ret)
4371 pr_err("%s: AFE close failed %d\n", __func__, ret);
4372
4373 return ret;
4374}
4375
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304376/**
4377 * afe_req_mmap_handle -
4378 * Retrieve AFE memory map handle
4379 *
4380 * @ac: AFE audio client
4381 *
4382 * Returns memory map handle
4383 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304384uint32_t afe_req_mmap_handle(struct afe_audio_client *ac)
4385{
4386 return ac->mem_map_handle;
4387}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304388EXPORT_SYMBOL(afe_req_mmap_handle);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304389
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304390/**
4391 * q6afe_audio_client_alloc -
4392 * Assign new AFE audio client
4393 *
4394 * @priv: privata data to hold for audio client
4395 *
4396 * Returns ac pointer on success or NULL on failure
4397 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304398struct afe_audio_client *q6afe_audio_client_alloc(void *priv)
4399{
4400 struct afe_audio_client *ac;
4401 int lcnt = 0;
4402
4403 ac = kzalloc(sizeof(struct afe_audio_client), GFP_KERNEL);
4404 if (!ac)
4405 return NULL;
4406
4407 ac->priv = priv;
4408
4409 init_waitqueue_head(&ac->cmd_wait);
4410 INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
4411 INIT_LIST_HEAD(&ac->port[1].mem_map_handle);
4412 pr_debug("%s: mem_map_handle list init'ed\n", __func__);
4413 mutex_init(&ac->cmd_lock);
4414 for (lcnt = 0; lcnt <= OUT; lcnt++) {
4415 mutex_init(&ac->port[lcnt].lock);
4416 spin_lock_init(&ac->port[lcnt].dsp_lock);
4417 }
4418 atomic_set(&ac->cmd_state, 0);
4419
4420 return ac;
4421}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304422EXPORT_SYMBOL(q6afe_audio_client_alloc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304423
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304424/**
4425 * q6afe_audio_client_buf_alloc_contiguous -
4426 * Allocate contiguous shared buffers
4427 *
4428 * @dir: RX or TX direction of AFE port
4429 * @ac: AFE audio client handle
4430 * @bufsz: size of each shared buffer
4431 * @bufcnt: number of buffers
4432 *
4433 * Returns 0 on success or error on failure
4434 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304435int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir,
4436 struct afe_audio_client *ac,
4437 unsigned int bufsz,
4438 unsigned int bufcnt)
4439{
4440 int cnt = 0;
4441 int rc = 0;
4442 struct afe_audio_buffer *buf;
4443 size_t len;
4444
4445 if (!(ac) || ((dir != IN) && (dir != OUT))) {
4446 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
4447 return -EINVAL;
4448 }
4449
4450 pr_debug("%s: bufsz[%d]bufcnt[%d]\n",
4451 __func__,
4452 bufsz, bufcnt);
4453
4454 if (ac->port[dir].buf) {
4455 pr_debug("%s: buffer already allocated\n", __func__);
4456 return 0;
4457 }
4458 mutex_lock(&ac->cmd_lock);
4459 buf = kzalloc(((sizeof(struct afe_audio_buffer))*bufcnt),
4460 GFP_KERNEL);
4461
4462 if (!buf) {
4463 pr_err("%s: null buf\n", __func__);
4464 mutex_unlock(&ac->cmd_lock);
4465 goto fail;
4466 }
4467
4468 ac->port[dir].buf = buf;
4469
4470 rc = msm_audio_ion_alloc("afe_client", &buf[0].client,
4471 &buf[0].handle, bufsz*bufcnt,
4472 &buf[0].phys, &len,
4473 &buf[0].data);
4474 if (rc) {
4475 pr_err("%s: audio ION alloc failed, rc = %d\n",
4476 __func__, rc);
4477 mutex_unlock(&ac->cmd_lock);
4478 goto fail;
4479 }
4480
4481 buf[0].used = dir ^ 1;
4482 buf[0].size = bufsz;
4483 buf[0].actual_size = bufsz;
4484 cnt = 1;
4485 while (cnt < bufcnt) {
4486 if (bufsz > 0) {
4487 buf[cnt].data = buf[0].data + (cnt * bufsz);
4488 buf[cnt].phys = buf[0].phys + (cnt * bufsz);
4489 if (!buf[cnt].data) {
4490 pr_err("%s: Buf alloc failed\n",
4491 __func__);
4492 mutex_unlock(&ac->cmd_lock);
4493 goto fail;
4494 }
4495 buf[cnt].used = dir ^ 1;
4496 buf[cnt].size = bufsz;
4497 buf[cnt].actual_size = bufsz;
4498 pr_debug("%s: data[%pK]phys[%pK][%pK]\n", __func__,
4499 buf[cnt].data,
4500 &buf[cnt].phys,
4501 &buf[cnt].phys);
4502 }
4503 cnt++;
4504 }
4505 ac->port[dir].max_buf_cnt = cnt;
4506 mutex_unlock(&ac->cmd_lock);
4507 return 0;
4508fail:
4509 pr_err("%s: jump fail\n", __func__);
4510 q6afe_audio_client_buf_free_contiguous(dir, ac);
4511 return -EINVAL;
4512}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304513EXPORT_SYMBOL(q6afe_audio_client_buf_alloc_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304514
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304515/**
4516 * afe_memory_map -
4517 * command to map shared buffers to AFE
4518 *
4519 * @dma_addr_p: DMA physical address
4520 * @dma_buf_sz: shared DMA buffer size
4521 * @ac: AFE audio client handle
4522 *
4523 * Returns 0 on success or error on failure
4524 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304525int afe_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz,
4526 struct afe_audio_client *ac)
4527{
4528 int ret = 0;
4529
4530 mutex_lock(&this_afe.afe_cmd_lock);
4531 ac->mem_map_handle = 0;
4532 ret = afe_cmd_memory_map(dma_addr_p, dma_buf_sz);
4533 if (ret < 0) {
4534 pr_err("%s: afe_cmd_memory_map failed %d\n",
4535 __func__, ret);
4536
4537 mutex_unlock(&this_afe.afe_cmd_lock);
4538 return ret;
4539 }
4540 ac->mem_map_handle = this_afe.mmap_handle;
4541 mutex_unlock(&this_afe.afe_cmd_lock);
4542
4543 return ret;
4544}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304545EXPORT_SYMBOL(afe_memory_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304546
4547int afe_cmd_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz)
4548{
4549 int ret = 0;
4550 int cmd_size = 0;
4551 void *payload = NULL;
4552 void *mmap_region_cmd = NULL;
4553 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
4554 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
4555 int index = 0;
4556
4557 pr_debug("%s:\n", __func__);
4558
4559 if (this_afe.apr == NULL) {
4560 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4561 0xFFFFFFFF, &this_afe);
4562 pr_debug("%s: Register AFE\n", __func__);
4563 if (this_afe.apr == NULL) {
4564 pr_err("%s: Unable to register AFE\n", __func__);
4565 ret = -ENODEV;
4566 return ret;
4567 }
4568 rtac_set_afe_handle(this_afe.apr);
4569 }
4570 if (dma_buf_sz % SZ_4K != 0) {
4571 /*
4572 * The memory allocated by msm_audio_ion_alloc is always 4kB
4573 * aligned, ADSP expects the size to be 4kB aligned as well
4574 * so re-adjusts the buffer size before passing to ADSP.
4575 */
4576 dma_buf_sz = PAGE_ALIGN(dma_buf_sz);
4577 }
4578
4579 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
4580 + sizeof(struct afe_service_shared_map_region_payload);
4581
4582 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
4583 if (!mmap_region_cmd)
4584 return -ENOMEM;
4585
4586 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
4587 mmap_region_cmd;
4588 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4589 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4590 mregion->hdr.pkt_size = cmd_size;
4591 mregion->hdr.src_port = 0;
4592 mregion->hdr.dest_port = 0;
4593 mregion->hdr.token = 0;
4594 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
4595 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
4596 mregion->num_regions = 1;
4597 mregion->property_flag = 0x00;
4598 /* Todo */
4599 index = mregion->hdr.token = IDX_RSVD_2;
4600
4601 payload = ((u8 *) mmap_region_cmd +
4602 sizeof(struct afe_service_cmd_shared_mem_map_regions));
4603
4604 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
4605
4606 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
4607 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
4608 mregion_pl->mem_size_bytes = dma_buf_sz;
4609
4610 pr_debug("%s: dma_addr_p 0x%pK , size %d\n", __func__,
4611 &dma_addr_p, dma_buf_sz);
4612 atomic_set(&this_afe.state, 1);
4613 atomic_set(&this_afe.status, 0);
4614 this_afe.mmap_handle = 0;
4615 ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
4616 if (ret < 0) {
4617 pr_err("%s: AFE memory map cmd failed %d\n",
4618 __func__, ret);
4619 ret = -EINVAL;
4620 goto fail_cmd;
4621 }
4622
4623 ret = wait_event_timeout(this_afe.wait[index],
4624 (atomic_read(&this_afe.state) == 0),
4625 msecs_to_jiffies(TIMEOUT_MS));
4626 if (!ret) {
4627 pr_err("%s: wait_event timeout\n", __func__);
4628 ret = -EINVAL;
4629 goto fail_cmd;
4630 }
4631 if (atomic_read(&this_afe.status) > 0) {
4632 pr_err("%s: config cmd failed [%s]\n",
4633 __func__, adsp_err_get_err_str(
4634 atomic_read(&this_afe.status)));
4635 ret = adsp_err_get_lnx_err_code(
4636 atomic_read(&this_afe.status));
4637 goto fail_cmd;
4638 }
4639
4640 kfree(mmap_region_cmd);
4641 return 0;
4642fail_cmd:
4643 kfree(mmap_region_cmd);
4644 pr_err("%s: fail_cmd\n", __func__);
4645 return ret;
4646}
4647
4648int afe_cmd_memory_map_nowait(int port_id, phys_addr_t dma_addr_p,
4649 u32 dma_buf_sz)
4650{
4651 int ret = 0;
4652 int cmd_size = 0;
4653 void *payload = NULL;
4654 void *mmap_region_cmd = NULL;
4655 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
4656 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
4657 int index = 0;
4658
4659 pr_debug("%s:\n", __func__);
4660
4661 if (this_afe.apr == NULL) {
4662 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4663 0xFFFFFFFF, &this_afe);
4664 pr_debug("%s: Register AFE\n", __func__);
4665 if (this_afe.apr == NULL) {
4666 pr_err("%s: Unable to register AFE\n", __func__);
4667 ret = -ENODEV;
4668 return ret;
4669 }
4670 rtac_set_afe_handle(this_afe.apr);
4671 }
4672 index = q6audio_get_port_index(port_id);
4673 if (index < 0 || index >= AFE_MAX_PORTS) {
4674 pr_err("%s: AFE port index[%d] invalid!\n",
4675 __func__, index);
4676 return -EINVAL;
4677 }
4678 ret = q6audio_validate_port(port_id);
4679 if (ret < 0) {
4680 pr_err("%s: Invalid port 0x%x ret %d",
4681 __func__, port_id, ret);
4682 return -EINVAL;
4683 }
4684
4685 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
4686 + sizeof(struct afe_service_shared_map_region_payload);
4687
4688 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
4689 if (!mmap_region_cmd)
4690 return -ENOMEM;
4691
4692 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
4693 mmap_region_cmd;
4694 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4695 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4696 mregion->hdr.pkt_size = sizeof(mregion);
4697 mregion->hdr.src_port = 0;
4698 mregion->hdr.dest_port = 0;
4699 mregion->hdr.token = 0;
4700 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
4701 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
4702 mregion->num_regions = 1;
4703 mregion->property_flag = 0x00;
4704
4705 payload = ((u8 *) mmap_region_cmd +
4706 sizeof(struct afe_service_cmd_shared_mem_map_regions));
4707 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
4708
4709 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
4710 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
4711 mregion_pl->mem_size_bytes = dma_buf_sz;
4712
4713 ret = afe_apr_send_pkt(mmap_region_cmd, NULL);
4714 if (ret)
4715 pr_err("%s: AFE memory map cmd failed %d\n",
4716 __func__, ret);
4717 kfree(mmap_region_cmd);
4718 return ret;
4719}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304720
4721/**
4722 * q6afe_audio_client_buf_free_contiguous -
4723 * frees the shared contiguous memory
4724 *
4725 * @dir: RX or TX direction of port
4726 * @ac: AFE audio client handle
4727 *
4728 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304729int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
4730 struct afe_audio_client *ac)
4731{
4732 struct afe_audio_port_data *port;
4733 int cnt = 0;
4734
4735 mutex_lock(&ac->cmd_lock);
4736 port = &ac->port[dir];
4737 if (!port->buf) {
4738 pr_err("%s: buf is null\n", __func__);
4739 mutex_unlock(&ac->cmd_lock);
4740 return 0;
4741 }
4742 cnt = port->max_buf_cnt - 1;
4743
4744 if (port->buf[0].data) {
4745 pr_debug("%s: data[%pK]phys[%pK][%pK] , client[%pK] handle[%pK]\n",
4746 __func__,
4747 port->buf[0].data,
4748 &port->buf[0].phys,
4749 &port->buf[0].phys,
4750 port->buf[0].client,
4751 port->buf[0].handle);
4752 msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
4753 port->buf[0].client = NULL;
4754 port->buf[0].handle = NULL;
4755 }
4756
4757 while (cnt >= 0) {
4758 port->buf[cnt].data = NULL;
4759 port->buf[cnt].phys = 0;
4760 cnt--;
4761 }
4762 port->max_buf_cnt = 0;
4763 kfree(port->buf);
4764 port->buf = NULL;
4765 mutex_unlock(&ac->cmd_lock);
4766 return 0;
4767}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304768EXPORT_SYMBOL(q6afe_audio_client_buf_free_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304769
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304770/**
4771 * q6afe_audio_client_free -
4772 * frees the audio client from AFE
4773 *
4774 * @ac: AFE audio client handle
4775 *
4776 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304777void q6afe_audio_client_free(struct afe_audio_client *ac)
4778{
4779 int loopcnt;
4780 struct afe_audio_port_data *port;
4781
4782 if (!ac) {
4783 pr_err("%s: audio client is NULL\n", __func__);
4784 return;
4785 }
4786 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
4787 port = &ac->port[loopcnt];
4788 if (!port->buf)
4789 continue;
4790 pr_debug("%s: loopcnt = %d\n", __func__, loopcnt);
4791 q6afe_audio_client_buf_free_contiguous(loopcnt, ac);
4792 }
4793 kfree(ac);
4794}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304795EXPORT_SYMBOL(q6afe_audio_client_free);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304796
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304797/**
4798 * afe_cmd_memory_unmap -
4799 * command to unmap memory for AFE shared buffer
4800 *
4801 * @mem_map_handle: memory map handle to be unmapped
4802 *
4803 * Returns 0 on success or error on failure
4804 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304805int afe_cmd_memory_unmap(u32 mem_map_handle)
4806{
4807 int ret = 0;
4808 struct afe_service_cmd_shared_mem_unmap_regions mregion;
4809 int index = 0;
4810
4811 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
4812
4813 if (this_afe.apr == NULL) {
4814 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4815 0xFFFFFFFF, &this_afe);
4816 pr_debug("%s: Register AFE\n", __func__);
4817 if (this_afe.apr == NULL) {
4818 pr_err("%s: Unable to register AFE\n", __func__);
4819 ret = -ENODEV;
4820 return ret;
4821 }
4822 rtac_set_afe_handle(this_afe.apr);
4823 }
4824
4825 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4826 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4827 mregion.hdr.pkt_size = sizeof(mregion);
4828 mregion.hdr.src_port = 0;
4829 mregion.hdr.dest_port = 0;
4830 mregion.hdr.token = 0;
4831 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
4832 mregion.mem_map_handle = mem_map_handle;
4833
4834 /* Todo */
4835 index = mregion.hdr.token = IDX_RSVD_2;
4836
4837 atomic_set(&this_afe.status, 0);
4838 ret = afe_apr_send_pkt(&mregion, &this_afe.wait[index]);
4839 if (ret)
4840 pr_err("%s: AFE memory unmap cmd failed %d\n",
4841 __func__, ret);
4842
4843 return ret;
4844}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304845EXPORT_SYMBOL(afe_cmd_memory_unmap);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304846
4847int afe_cmd_memory_unmap_nowait(u32 mem_map_handle)
4848{
4849 int ret = 0;
4850 struct afe_service_cmd_shared_mem_unmap_regions mregion;
4851
4852 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
4853
4854 if (this_afe.apr == NULL) {
4855 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4856 0xFFFFFFFF, &this_afe);
4857 pr_debug("%s: Register AFE\n", __func__);
4858 if (this_afe.apr == NULL) {
4859 pr_err("%s: Unable to register AFE\n", __func__);
4860 ret = -ENODEV;
4861 return ret;
4862 }
4863 rtac_set_afe_handle(this_afe.apr);
4864 }
4865
4866 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4867 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4868 mregion.hdr.pkt_size = sizeof(mregion);
4869 mregion.hdr.src_port = 0;
4870 mregion.hdr.dest_port = 0;
4871 mregion.hdr.token = 0;
4872 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
4873 mregion.mem_map_handle = mem_map_handle;
4874
4875 ret = afe_apr_send_pkt(&mregion, NULL);
4876 if (ret)
4877 pr_err("%s: AFE memory unmap cmd failed %d\n",
4878 __func__, ret);
4879 return ret;
4880}
4881
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304882/**
4883 * afe_register_get_events -
4884 * register for events from proxy port
4885 *
4886 * @port_id: Port ID to register events
4887 * @cb: callback function to invoke for events from proxy port
4888 * @private_data: private data to sent back in callback fn
4889 *
4890 * Returns 0 on success or error on failure
4891 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304892int afe_register_get_events(u16 port_id,
4893 void (*cb)(uint32_t opcode,
4894 uint32_t token, uint32_t *payload, void *priv),
4895 void *private_data)
4896{
4897 int ret = 0;
4898 struct afe_service_cmd_register_rt_port_driver rtproxy;
4899
4900 pr_debug("%s: port_id: 0x%x\n", __func__, port_id);
4901
4902 if (this_afe.apr == NULL) {
4903 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4904 0xFFFFFFFF, &this_afe);
4905 pr_debug("%s: Register AFE\n", __func__);
4906 if (this_afe.apr == NULL) {
4907 pr_err("%s: Unable to register AFE\n", __func__);
4908 ret = -ENODEV;
4909 return ret;
4910 }
4911 rtac_set_afe_handle(this_afe.apr);
4912 }
4913 if ((port_id == RT_PROXY_DAI_002_RX) ||
4914 (port_id == RT_PROXY_DAI_001_TX)) {
4915 port_id = VIRTUAL_ID_TO_PORTID(port_id);
4916 } else {
4917 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
4918 return -EINVAL;
4919 }
4920
4921 if (port_id == RT_PROXY_PORT_001_TX) {
4922 this_afe.tx_cb = cb;
4923 this_afe.tx_private_data = private_data;
4924 } else if (port_id == RT_PROXY_PORT_001_RX) {
4925 this_afe.rx_cb = cb;
4926 this_afe.rx_private_data = private_data;
4927 }
4928
4929 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4930 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4931 rtproxy.hdr.pkt_size = sizeof(rtproxy);
4932 rtproxy.hdr.src_port = 1;
4933 rtproxy.hdr.dest_port = 1;
4934 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER;
4935 rtproxy.port_id = port_id;
4936 rtproxy.reserved = 0;
4937
4938 ret = afe_apr_send_pkt(&rtproxy, NULL);
4939 if (ret)
4940 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
4941 __func__, ret);
4942 return ret;
4943}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304944EXPORT_SYMBOL(afe_register_get_events);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304945
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304946/**
4947 * afe_unregister_get_events -
4948 * unregister for events from proxy port
4949 *
4950 * @port_id: Port ID to unregister events
4951 *
4952 * Returns 0 on success or error on failure
4953 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304954int afe_unregister_get_events(u16 port_id)
4955{
4956 int ret = 0;
4957 struct afe_service_cmd_unregister_rt_port_driver rtproxy;
4958 int index = 0;
4959
4960 pr_debug("%s:\n", __func__);
4961
4962 if (this_afe.apr == NULL) {
4963 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4964 0xFFFFFFFF, &this_afe);
4965 pr_debug("%s: Register AFE\n", __func__);
4966 if (this_afe.apr == NULL) {
4967 pr_err("%s: Unable to register AFE\n", __func__);
4968 ret = -ENODEV;
4969 return ret;
4970 }
4971 rtac_set_afe_handle(this_afe.apr);
4972 }
4973
4974 if ((port_id == RT_PROXY_DAI_002_RX) ||
4975 (port_id == RT_PROXY_DAI_001_TX)) {
4976 port_id = VIRTUAL_ID_TO_PORTID(port_id);
4977 } else {
4978 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
4979 return -EINVAL;
4980 }
4981
4982 index = q6audio_get_port_index(port_id);
4983 if (index < 0 || index >= AFE_MAX_PORTS) {
4984 pr_err("%s: AFE port index[%d] invalid!\n",
4985 __func__, index);
4986 return -EINVAL;
4987 }
4988 ret = q6audio_validate_port(port_id);
4989 if (ret < 0) {
4990 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
4991 return -EINVAL;
4992 }
4993
4994 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4995 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4996 rtproxy.hdr.pkt_size = sizeof(rtproxy);
4997 rtproxy.hdr.src_port = 0;
4998 rtproxy.hdr.dest_port = 0;
4999 rtproxy.hdr.token = 0;
5000 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER;
5001 rtproxy.port_id = port_id;
5002 rtproxy.reserved = 0;
5003
5004 rtproxy.hdr.token = index;
5005
5006 if (port_id == RT_PROXY_PORT_001_TX) {
5007 this_afe.tx_cb = NULL;
5008 this_afe.tx_private_data = NULL;
5009 } else if (port_id == RT_PROXY_PORT_001_RX) {
5010 this_afe.rx_cb = NULL;
5011 this_afe.rx_private_data = NULL;
5012 }
5013
5014 ret = afe_apr_send_pkt(&rtproxy, &this_afe.wait[index]);
5015 if (ret)
5016 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
5017 __func__, ret);
5018 return ret;
5019}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305020EXPORT_SYMBOL(afe_unregister_get_events);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305021
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305022/**
5023 * afe_rt_proxy_port_write -
5024 * command for AFE RT proxy port write
5025 *
5026 * @buf_addr_p: Physical buffer address with
5027 * playback data to proxy port
5028 * @mem_map_handle: memory map handle of write buffer
5029 * @bytes: number of bytes to write
5030 *
5031 * Returns 0 on success or error on failure
5032 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305033int afe_rt_proxy_port_write(phys_addr_t buf_addr_p,
5034 u32 mem_map_handle, int bytes)
5035{
5036 int ret = 0;
5037 struct afe_port_data_cmd_rt_proxy_port_write_v2 afecmd_wr;
5038
5039 if (this_afe.apr == NULL) {
5040 pr_err("%s: register to AFE is not done\n", __func__);
5041 ret = -ENODEV;
5042 return ret;
5043 }
5044 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
5045 &buf_addr_p, bytes);
5046
5047 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5048 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5049 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
5050 afecmd_wr.hdr.src_port = 0;
5051 afecmd_wr.hdr.dest_port = 0;
5052 afecmd_wr.hdr.token = 0;
5053 afecmd_wr.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2;
5054 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
5055 afecmd_wr.buffer_address_lsw = lower_32_bits(buf_addr_p);
5056 afecmd_wr.buffer_address_msw =
5057 msm_audio_populate_upper_32_bits(buf_addr_p);
5058 afecmd_wr.mem_map_handle = mem_map_handle;
5059 afecmd_wr.available_bytes = bytes;
5060 afecmd_wr.reserved = 0;
5061
5062 ret = afe_apr_send_pkt(&afecmd_wr, NULL);
5063 if (ret)
5064 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
5065 __func__, afecmd_wr.port_id, ret);
5066 return ret;
5067
5068}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305069EXPORT_SYMBOL(afe_rt_proxy_port_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305070
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305071/**
5072 * afe_rt_proxy_port_read -
5073 * command for AFE RT proxy port read
5074 *
5075 * @buf_addr_p: Physical buffer address to fill read data
5076 * @mem_map_handle: memory map handle for buffer read
5077 * @bytes: number of bytes to read
5078 *
5079 * Returns 0 on success or error on failure
5080 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305081int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
5082 u32 mem_map_handle, int bytes)
5083{
5084 int ret = 0;
5085 struct afe_port_data_cmd_rt_proxy_port_read_v2 afecmd_rd;
5086
5087 if (this_afe.apr == NULL) {
5088 pr_err("%s: register to AFE is not done\n", __func__);
5089 ret = -ENODEV;
5090 return ret;
5091 }
5092 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
5093 &buf_addr_p, bytes);
5094
5095 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5096 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5097 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
5098 afecmd_rd.hdr.src_port = 0;
5099 afecmd_rd.hdr.dest_port = 0;
5100 afecmd_rd.hdr.token = 0;
5101 afecmd_rd.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2;
5102 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
5103 afecmd_rd.buffer_address_lsw = lower_32_bits(buf_addr_p);
5104 afecmd_rd.buffer_address_msw =
5105 msm_audio_populate_upper_32_bits(buf_addr_p);
5106 afecmd_rd.available_bytes = bytes;
5107 afecmd_rd.mem_map_handle = mem_map_handle;
5108
5109 ret = afe_apr_send_pkt(&afecmd_rd, NULL);
5110 if (ret)
5111 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
5112 __func__, afecmd_rd.port_id, ret);
5113 return ret;
5114}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305115EXPORT_SYMBOL(afe_rt_proxy_port_read);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305116
5117#ifdef CONFIG_DEBUG_FS
5118static struct dentry *debugfs_afelb;
5119static struct dentry *debugfs_afelb_gain;
5120
5121static int afe_debug_open(struct inode *inode, struct file *file)
5122{
5123 file->private_data = inode->i_private;
5124 pr_info("%s: debug intf %s\n", __func__, (char *) file->private_data);
5125 return 0;
5126}
5127
5128static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
5129{
5130 char *token;
5131 int base, cnt;
5132
5133 token = strsep(&buf, " ");
5134
5135 for (cnt = 0; cnt < num_of_par; cnt++) {
5136 if (token != NULL) {
5137 if ((token[1] == 'x') || (token[1] == 'X'))
5138 base = 16;
5139 else
5140 base = 10;
5141
5142 if (kstrtoul(token, base, &param1[cnt]) != 0) {
5143 pr_err("%s: kstrtoul failed\n",
5144 __func__);
5145 return -EINVAL;
5146 }
5147
5148 token = strsep(&buf, " ");
5149 } else {
5150 pr_err("%s: token NULL\n", __func__);
5151 return -EINVAL;
5152 }
5153 }
5154 return 0;
5155}
5156#define AFE_LOOPBACK_ON (1)
5157#define AFE_LOOPBACK_OFF (0)
5158static ssize_t afe_debug_write(struct file *filp,
5159 const char __user *ubuf, size_t cnt, loff_t *ppos)
5160{
5161 char *lb_str = filp->private_data;
5162 char lbuf[32];
5163 int rc;
5164 unsigned long param[5];
5165
5166 if (cnt > sizeof(lbuf) - 1) {
5167 pr_err("%s: cnt %zd size %zd\n", __func__, cnt, sizeof(lbuf)-1);
5168 return -EINVAL;
5169 }
5170
5171 rc = copy_from_user(lbuf, ubuf, cnt);
5172 if (rc) {
5173 pr_err("%s: copy from user failed %d\n", __func__, rc);
5174 return -EFAULT;
5175 }
5176
5177 lbuf[cnt] = '\0';
5178
5179 if (!strcmp(lb_str, "afe_loopback")) {
5180 rc = afe_get_parameters(lbuf, param, 3);
5181 if (!rc) {
5182 pr_info("%s: %lu %lu %lu\n", lb_str, param[0], param[1],
5183 param[2]);
5184
5185 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
5186 AFE_LOOPBACK_OFF)) {
5187 pr_err("%s: Error, parameter 0 incorrect\n",
5188 __func__);
5189 rc = -EINVAL;
5190 goto afe_error;
5191 }
5192 if ((q6audio_validate_port(param[1]) < 0) ||
5193 (q6audio_validate_port(param[2])) < 0) {
5194 pr_err("%s: Error, invalid afe port\n",
5195 __func__);
5196 }
5197 if (this_afe.apr == NULL) {
5198 pr_err("%s: Error, AFE not opened\n", __func__);
5199 rc = -EINVAL;
5200 } else {
5201 rc = afe_loopback(param[0], param[1], param[2]);
5202 }
5203 } else {
5204 pr_err("%s: Error, invalid parameters\n", __func__);
5205 rc = -EINVAL;
5206 }
5207
5208 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
5209 rc = afe_get_parameters(lbuf, param, 2);
5210 if (!rc) {
5211 pr_info("%s: %s %lu %lu\n",
5212 __func__, lb_str, param[0], param[1]);
5213
5214 rc = q6audio_validate_port(param[0]);
5215 if (rc < 0) {
5216 pr_err("%s: Error, invalid afe port %d %lu\n",
5217 __func__, rc, param[0]);
5218 rc = -EINVAL;
5219 goto afe_error;
5220 }
5221
5222 if (param[1] > 100) {
5223 pr_err("%s: Error, volume should be 0 to 100 percentage param = %lu\n",
5224 __func__, param[1]);
5225 rc = -EINVAL;
5226 goto afe_error;
5227 }
5228
5229 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
5230
5231 if (this_afe.apr == NULL) {
5232 pr_err("%s: Error, AFE not opened\n", __func__);
5233 rc = -EINVAL;
5234 } else {
5235 rc = afe_loopback_gain(param[0], param[1]);
5236 }
5237 } else {
5238 pr_err("%s: Error, invalid parameters\n", __func__);
5239 rc = -EINVAL;
5240 }
5241 }
5242
5243afe_error:
5244 if (rc == 0)
5245 rc = cnt;
5246 else
5247 pr_err("%s: rc = %d\n", __func__, rc);
5248
5249 return rc;
5250}
5251
5252static const struct file_operations afe_debug_fops = {
5253 .open = afe_debug_open,
5254 .write = afe_debug_write
5255};
5256
5257static void config_debug_fs_init(void)
5258{
5259 debugfs_afelb = debugfs_create_file("afe_loopback",
5260 0664, NULL, (void *) "afe_loopback",
5261 &afe_debug_fops);
5262
5263 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
5264 0664, NULL, (void *) "afe_loopback_gain",
5265 &afe_debug_fops);
5266}
5267static void config_debug_fs_exit(void)
5268{
5269 debugfs_remove(debugfs_afelb);
5270 debugfs_remove(debugfs_afelb_gain);
5271}
5272#else
5273static void config_debug_fs_init(void)
5274{
5275}
5276static void config_debug_fs_exit(void)
5277{
5278}
5279#endif
5280
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305281/**
5282 * afe_set_dtmf_gen_rx_portid -
5283 * Set port_id for DTMF tone generation
5284 *
5285 * @port_id: AFE port id
5286 * @set: set or reset port id value for dtmf gen
5287 *
5288 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305289void afe_set_dtmf_gen_rx_portid(u16 port_id, int set)
5290{
5291 if (set)
5292 this_afe.dtmf_gen_rx_portid = port_id;
5293 else if (this_afe.dtmf_gen_rx_portid == port_id)
5294 this_afe.dtmf_gen_rx_portid = -1;
5295}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305296EXPORT_SYMBOL(afe_set_dtmf_gen_rx_portid);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305297
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305298/**
5299 * afe_dtmf_generate_rx - command to generate AFE DTMF RX
5300 *
5301 * @duration_in_ms: Duration in ms for dtmf tone
5302 * @high_freq: Higher frequency for dtmf
5303 * @low_freq: lower frequency for dtmf
5304 * @gain: Gain value for DTMF tone
5305 *
5306 * Returns 0 on success, appropriate error code otherwise
5307 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305308int afe_dtmf_generate_rx(int64_t duration_in_ms,
5309 uint16_t high_freq,
5310 uint16_t low_freq, uint16_t gain)
5311{
5312 int ret = 0;
5313 int index = 0;
5314 struct afe_dtmf_generation_command cmd_dtmf;
5315
5316 pr_debug("%s: DTMF AFE Gen\n", __func__);
5317
5318 if (afe_validate_port(this_afe.dtmf_gen_rx_portid) < 0) {
5319 pr_err("%s: Failed : Invalid Port id = 0x%x\n",
5320 __func__, this_afe.dtmf_gen_rx_portid);
5321 ret = -EINVAL;
5322 goto fail_cmd;
5323 }
5324
5325 if (this_afe.apr == NULL) {
5326 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5327 0xFFFFFFFF, &this_afe);
5328 pr_debug("%s: Register AFE\n", __func__);
5329 if (this_afe.apr == NULL) {
5330 pr_err("%s: Unable to register AFE\n", __func__);
5331 ret = -ENODEV;
5332 return ret;
5333 }
5334 rtac_set_afe_handle(this_afe.apr);
5335 }
5336
5337 pr_debug("%s: dur=%lld: hfreq=%d lfreq=%d gain=%d portid=0x%x\n",
5338 __func__,
5339 duration_in_ms, high_freq, low_freq, gain,
5340 this_afe.dtmf_gen_rx_portid);
5341
5342 cmd_dtmf.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5343 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5344 cmd_dtmf.hdr.pkt_size = sizeof(cmd_dtmf);
5345 cmd_dtmf.hdr.src_port = 0;
5346 cmd_dtmf.hdr.dest_port = 0;
5347 cmd_dtmf.hdr.token = 0;
5348 cmd_dtmf.hdr.opcode = AFE_PORTS_CMD_DTMF_CTL;
5349 cmd_dtmf.duration_in_ms = duration_in_ms;
5350 cmd_dtmf.high_freq = high_freq;
5351 cmd_dtmf.low_freq = low_freq;
5352 cmd_dtmf.gain = gain;
5353 cmd_dtmf.num_ports = 1;
5354 cmd_dtmf.port_ids = q6audio_get_port_id(this_afe.dtmf_gen_rx_portid);
5355
5356 atomic_set(&this_afe.state, 1);
5357 atomic_set(&this_afe.status, 0);
5358 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_dtmf);
5359 if (ret < 0) {
5360 pr_err("%s: AFE DTMF failed for num_ports:%d ids:0x%x\n",
5361 __func__, cmd_dtmf.num_ports, cmd_dtmf.port_ids);
5362 ret = -EINVAL;
5363 goto fail_cmd;
5364 }
5365 index = q6audio_get_port_index(this_afe.dtmf_gen_rx_portid);
5366 if (index < 0 || index >= AFE_MAX_PORTS) {
5367 pr_err("%s: AFE port index[%d] invalid!\n",
5368 __func__, index);
5369 ret = -EINVAL;
5370 goto fail_cmd;
5371 }
5372 ret = wait_event_timeout(this_afe.wait[index],
5373 (atomic_read(&this_afe.state) == 0),
5374 msecs_to_jiffies(TIMEOUT_MS));
5375 if (!ret) {
5376 pr_err("%s: wait_event timeout\n", __func__);
5377 ret = -EINVAL;
5378 goto fail_cmd;
5379 }
5380 if (atomic_read(&this_afe.status) > 0) {
5381 pr_err("%s: config cmd failed [%s]\n",
5382 __func__, adsp_err_get_err_str(
5383 atomic_read(&this_afe.status)));
5384 ret = adsp_err_get_lnx_err_code(
5385 atomic_read(&this_afe.status));
5386 goto fail_cmd;
5387 }
5388 return 0;
5389
5390fail_cmd:
5391 pr_err("%s: failed %d\n", __func__, ret);
5392 return ret;
5393}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305394EXPORT_SYMBOL(afe_dtmf_generate_rx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305395
5396static int afe_sidetone_iir(u16 tx_port_id)
5397{
5398 struct afe_loopback_iir_cfg_v2 iir_sidetone;
5399 int ret;
5400 int index = 0;
5401 uint16_t size = 0;
5402 int cal_index = AFE_SIDETONE_IIR_CAL;
5403 int iir_pregain = 0;
5404 int iir_num_biquad_stages = 0;
5405 int iir_enable;
5406 struct cal_block_data *cal_block;
5407 int mid;
5408
5409 memset(&iir_sidetone, 0, sizeof(iir_sidetone));
5410 index = q6audio_get_port_index(tx_port_id);
5411 iir_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5412 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5413 iir_sidetone.hdr.pkt_size = sizeof(iir_sidetone);
5414 iir_sidetone.hdr.src_port = 0;
5415 iir_sidetone.hdr.dest_port = 0;
5416 iir_sidetone.hdr.token = index;
5417 iir_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
5418 iir_sidetone.param.port_id = tx_port_id;
5419 iir_sidetone.param.payload_address_lsw = 0x00;
5420 iir_sidetone.param.payload_address_msw = 0x00;
5421 iir_sidetone.param.mem_map_handle = 0x00;
5422
5423 if (this_afe.cal_data[cal_index] == NULL) {
5424 pr_err("%s: cal data is NULL\n", __func__);
5425 ret = -EINVAL;
5426 goto done;
5427 }
5428 mutex_lock(&this_afe.cal_data[cal_index]->lock);
5429 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
5430 if (cal_block == NULL) {
5431 pr_err("%s: cal_block not found\n ", __func__);
5432 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5433 ret = -EINVAL;
5434 goto done;
5435 }
5436
5437 iir_pregain = ((struct audio_cal_info_sidetone_iir *)
5438 cal_block->cal_info)->pregain;
5439 iir_enable = ((struct audio_cal_info_sidetone_iir *)
5440 cal_block->cal_info)->iir_enable;
5441 iir_num_biquad_stages = ((struct audio_cal_info_sidetone_iir *)
5442 cal_block->cal_info)->num_biquad_stages;
5443 mid = ((struct audio_cal_info_sidetone_iir *)
5444 cal_block->cal_info)->mid;
5445
5446 /*
5447 * calculate the actual size of payload based on no of stages
5448 * enabled in calibration
5449 */
5450 size = (MAX_SIDETONE_IIR_DATA_SIZE / MAX_NO_IIR_FILTER_STAGE) *
5451 iir_num_biquad_stages;
5452 /*
5453 * For an odd number of stages, 2 bytes of padding are
5454 * required at the end of the payload.
5455 */
5456 if (iir_num_biquad_stages % 2) {
5457 pr_debug("%s: adding 2 to size:%d\n", __func__, size);
5458 size = size + 2;
5459 }
5460 memcpy(&iir_sidetone.st_iir_filter_config_data.iir_config,
5461 &((struct audio_cal_info_sidetone_iir *)
5462 cal_block->cal_info)->iir_config,
5463 sizeof(iir_sidetone.st_iir_filter_config_data.iir_config));
5464 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5465
5466 /*
5467 * Calculate the payload size for setparams command
5468 */
5469 iir_sidetone.param.payload_size = (sizeof(iir_sidetone) -
5470 sizeof(struct apr_hdr) -
5471 sizeof(struct afe_port_cmd_set_param_v2) -
5472 (MAX_SIDETONE_IIR_DATA_SIZE - size));
5473
5474 pr_debug("%s: payload size :%d\n", __func__,
5475 iir_sidetone.param.payload_size);
5476
5477 /*
5478 * Set IIR enable params
5479 */
5480 iir_sidetone.st_iir_enable_pdata.module_id = mid;
5481 iir_sidetone.st_iir_enable_pdata.param_id =
5482 AFE_PARAM_ID_ENABLE;
5483 iir_sidetone.st_iir_enable_pdata.param_size =
5484 sizeof(iir_sidetone.st_iir_mode_enable_data);
5485 iir_sidetone.st_iir_mode_enable_data.enable = iir_enable;
5486
5487 /*
5488 * Set IIR filter config params
5489 */
5490 iir_sidetone.st_iir_filter_config_pdata.module_id = mid;
5491 iir_sidetone.st_iir_filter_config_pdata.param_id =
5492 AFE_PARAM_ID_SIDETONE_IIR_FILTER_CONFIG;
5493 iir_sidetone.st_iir_filter_config_pdata.param_size =
5494 sizeof(iir_sidetone.st_iir_filter_config_data.num_biquad_stages)
5495 +
5496 sizeof(iir_sidetone.st_iir_filter_config_data.pregain) + size;
5497 iir_sidetone.st_iir_filter_config_pdata.reserved = 0;
5498 iir_sidetone.st_iir_filter_config_data.num_biquad_stages =
5499 iir_num_biquad_stages;
5500 iir_sidetone.st_iir_filter_config_data.pregain = iir_pregain;
5501 pr_debug("%s: tx(0x%x)mid(0x%x)iir_en(%d)stg(%d)gain(0x%x)size(%d)\n",
5502 __func__, tx_port_id, mid,
5503 iir_sidetone.st_iir_mode_enable_data.enable,
5504 iir_sidetone.st_iir_filter_config_data.num_biquad_stages,
5505 iir_sidetone.st_iir_filter_config_data.pregain,
5506 iir_sidetone.st_iir_filter_config_pdata.param_size);
5507 ret = afe_apr_send_pkt(&iir_sidetone, &this_afe.wait[index]);
5508 if (ret)
5509 pr_err("%s: AFE sidetone failed for tx_port(0x%x)\n",
5510 __func__, tx_port_id);
5511
5512done:
5513 return ret;
5514
5515}
5516
5517static int afe_sidetone(u16 tx_port_id, u16 rx_port_id, bool enable)
5518{
5519 struct afe_st_loopback_cfg_v1 cmd_sidetone;
5520 int ret;
5521 int index;
5522 int cal_index = AFE_SIDETONE_CAL;
5523 int sidetone_gain;
5524 int sidetone_enable;
5525 struct cal_block_data *cal_block;
5526 int mid = 0;
5527
5528 memset(&cmd_sidetone, 0, sizeof(cmd_sidetone));
5529 if (this_afe.cal_data[cal_index] == NULL) {
5530 pr_err("%s: cal data is NULL\n", __func__);
5531 ret = -EINVAL;
5532 goto done;
5533 }
5534 mutex_lock(&this_afe.cal_data[cal_index]->lock);
5535 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
5536 if (cal_block == NULL) {
5537 pr_err("%s: cal_block not found\n", __func__);
5538 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5539 ret = -EINVAL;
5540 goto done;
5541 }
5542 sidetone_gain = ((struct audio_cal_info_sidetone *)
5543 cal_block->cal_info)->gain;
5544 sidetone_enable = ((struct audio_cal_info_sidetone *)
5545 cal_block->cal_info)->enable;
5546 mid = ((struct audio_cal_info_sidetone *)
5547 cal_block->cal_info)->mid;
5548 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5549
5550 index = q6audio_get_port_index(tx_port_id);
5551 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5552 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5553 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
5554 cmd_sidetone.hdr.src_port = 0;
5555 cmd_sidetone.hdr.dest_port = 0;
5556 cmd_sidetone.hdr.token = index;
5557 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
5558 cmd_sidetone.param.port_id = tx_port_id;
5559 cmd_sidetone.param.payload_size = (sizeof(cmd_sidetone) -
5560 sizeof(struct apr_hdr) -
5561 sizeof(struct afe_port_cmd_set_param_v2));
5562 cmd_sidetone.param.payload_address_lsw = 0x00;
5563 cmd_sidetone.param.payload_address_msw = 0x00;
5564 cmd_sidetone.param.mem_map_handle = 0x00;
5565 cmd_sidetone.gain_pdata.module_id = AFE_MODULE_LOOPBACK;
5566 cmd_sidetone.gain_pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
5567 /*
5568 * size of actual payload only
5569 */
5570 cmd_sidetone.gain_pdata.param_size = sizeof(
5571 struct afe_loopback_sidetone_gain);
5572 cmd_sidetone.gain_data.rx_port_id = rx_port_id;
5573 cmd_sidetone.gain_data.gain = sidetone_gain;
5574
5575 cmd_sidetone.cfg_pdata.module_id = AFE_MODULE_LOOPBACK;
5576 cmd_sidetone.cfg_pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
5577 /*
5578 * size of actual payload only
5579 */
5580 cmd_sidetone.cfg_pdata.param_size = sizeof(struct loopback_cfg_data);
5581 cmd_sidetone.cfg_data.loopback_cfg_minor_version =
5582 AFE_API_VERSION_LOOPBACK_CONFIG;
5583 cmd_sidetone.cfg_data.dst_port_id = rx_port_id;
5584 cmd_sidetone.cfg_data.routing_mode = LB_MODE_SIDETONE;
5585 cmd_sidetone.cfg_data.enable = enable;
5586
5587 pr_debug("%s rx(0x%x) tx(0x%x) enable(%d) mid(0x%x) gain(%d) sidetone_enable(%d)\n",
5588 __func__, rx_port_id, tx_port_id,
5589 enable, mid, sidetone_gain, sidetone_enable);
5590
5591 ret = afe_apr_send_pkt(&cmd_sidetone, &this_afe.wait[index]);
5592 if (ret)
5593 pr_err("%s: AFE sidetone send failed for tx_port:%d rx_port:%d ret:%d\n",
5594 __func__, tx_port_id, rx_port_id, ret);
5595done:
5596 return ret;
5597}
5598
5599int afe_sidetone_enable(u16 tx_port_id, u16 rx_port_id, bool enable)
5600{
5601 int ret;
5602 int index;
5603
5604 index = q6audio_get_port_index(rx_port_id);
5605 if (index < 0 || index >= AFE_MAX_PORTS) {
5606 pr_err("%s: AFE port index[%d] invalid!\n",
5607 __func__, index);
5608 ret = -EINVAL;
5609 goto done;
5610 }
5611 if (q6audio_validate_port(rx_port_id) < 0) {
5612 pr_err("%s: Invalid port 0x%x\n",
5613 __func__, rx_port_id);
5614 ret = -EINVAL;
5615 goto done;
5616 }
5617 index = q6audio_get_port_index(tx_port_id);
5618 if (index < 0 || index >= AFE_MAX_PORTS) {
5619 pr_err("%s: AFE port index[%d] invalid!\n",
5620 __func__, index);
5621 ret = -EINVAL;
5622 goto done;
5623 }
5624 if (q6audio_validate_port(tx_port_id) < 0) {
5625 pr_err("%s: Invalid port 0x%x\n",
5626 __func__, tx_port_id);
5627 ret = -EINVAL;
5628 goto done;
5629 }
5630 if (enable) {
5631 ret = afe_sidetone_iir(tx_port_id);
5632 if (ret)
5633 goto done;
5634 }
5635
5636 ret = afe_sidetone(tx_port_id, rx_port_id, enable);
5637
5638done:
5639 return ret;
5640}
5641
5642int afe_validate_port(u16 port_id)
5643{
5644 int ret;
5645
5646 switch (port_id) {
5647 case PRIMARY_I2S_RX:
5648 case PRIMARY_I2S_TX:
5649 case AFE_PORT_ID_PRIMARY_PCM_RX:
5650 case AFE_PORT_ID_PRIMARY_PCM_TX:
5651 case AFE_PORT_ID_SECONDARY_PCM_RX:
5652 case AFE_PORT_ID_SECONDARY_PCM_TX:
5653 case AFE_PORT_ID_TERTIARY_PCM_RX:
5654 case AFE_PORT_ID_TERTIARY_PCM_TX:
5655 case AFE_PORT_ID_QUATERNARY_PCM_RX:
5656 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05305657 case AFE_PORT_ID_QUINARY_PCM_RX:
5658 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305659 case SECONDARY_I2S_RX:
5660 case SECONDARY_I2S_TX:
5661 case MI2S_RX:
5662 case MI2S_TX:
5663 case HDMI_RX:
5664 case DISPLAY_PORT_RX:
5665 case AFE_PORT_ID_SPDIF_RX:
5666 case RSVD_2:
5667 case RSVD_3:
5668 case DIGI_MIC_TX:
5669 case VOICE_RECORD_RX:
5670 case VOICE_RECORD_TX:
5671 case VOICE_PLAYBACK_TX:
5672 case VOICE2_PLAYBACK_TX:
5673 case SLIMBUS_0_RX:
5674 case SLIMBUS_0_TX:
5675 case SLIMBUS_1_RX:
5676 case SLIMBUS_1_TX:
5677 case SLIMBUS_2_RX:
5678 case SLIMBUS_2_TX:
5679 case SLIMBUS_3_RX:
5680 case INT_BT_SCO_RX:
5681 case INT_BT_SCO_TX:
5682 case INT_BT_A2DP_RX:
5683 case INT_FM_RX:
5684 case INT_FM_TX:
5685 case RT_PROXY_PORT_001_RX:
5686 case RT_PROXY_PORT_001_TX:
5687 case SLIMBUS_4_RX:
5688 case SLIMBUS_4_TX:
5689 case SLIMBUS_5_RX:
5690 case SLIMBUS_6_RX:
5691 case SLIMBUS_6_TX:
5692 case SLIMBUS_7_RX:
5693 case SLIMBUS_7_TX:
5694 case SLIMBUS_8_RX:
5695 case SLIMBUS_8_TX:
5696 case AFE_PORT_ID_USB_RX:
5697 case AFE_PORT_ID_USB_TX:
5698 case AFE_PORT_ID_PRIMARY_MI2S_RX:
5699 case AFE_PORT_ID_PRIMARY_MI2S_TX:
5700 case AFE_PORT_ID_SECONDARY_MI2S_RX:
5701 case AFE_PORT_ID_SECONDARY_MI2S_TX:
5702 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
5703 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
5704 case AFE_PORT_ID_TERTIARY_MI2S_RX:
5705 case AFE_PORT_ID_TERTIARY_MI2S_TX:
5706 case AFE_PORT_ID_QUINARY_MI2S_RX:
5707 case AFE_PORT_ID_QUINARY_MI2S_TX:
5708 case AFE_PORT_ID_SENARY_MI2S_TX:
5709 case AFE_PORT_ID_PRIMARY_TDM_RX:
5710 case AFE_PORT_ID_PRIMARY_TDM_TX:
5711 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
5712 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
5713 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
5714 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
5715 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
5716 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
5717 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
5718 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
5719 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
5720 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
5721 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
5722 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
5723 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
5724 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
5725 case AFE_PORT_ID_SECONDARY_TDM_RX:
5726 case AFE_PORT_ID_SECONDARY_TDM_TX:
5727 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
5728 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
5729 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
5730 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
5731 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
5732 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
5733 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
5734 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
5735 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
5736 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
5737 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
5738 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
5739 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
5740 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
5741 case AFE_PORT_ID_TERTIARY_TDM_RX:
5742 case AFE_PORT_ID_TERTIARY_TDM_TX:
5743 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
5744 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
5745 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
5746 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
5747 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
5748 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
5749 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
5750 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
5751 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
5752 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
5753 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
5754 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
5755 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
5756 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
5757 case AFE_PORT_ID_QUATERNARY_TDM_RX:
5758 case AFE_PORT_ID_QUATERNARY_TDM_TX:
5759 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
5760 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
5761 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
5762 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
5763 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
5764 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
5765 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
5766 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
5767 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
5768 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
5769 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
5770 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
5771 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
5772 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05305773 case AFE_PORT_ID_QUINARY_TDM_RX:
5774 case AFE_PORT_ID_QUINARY_TDM_TX:
5775 case AFE_PORT_ID_QUINARY_TDM_RX_1:
5776 case AFE_PORT_ID_QUINARY_TDM_TX_1:
5777 case AFE_PORT_ID_QUINARY_TDM_RX_2:
5778 case AFE_PORT_ID_QUINARY_TDM_TX_2:
5779 case AFE_PORT_ID_QUINARY_TDM_RX_3:
5780 case AFE_PORT_ID_QUINARY_TDM_TX_3:
5781 case AFE_PORT_ID_QUINARY_TDM_RX_4:
5782 case AFE_PORT_ID_QUINARY_TDM_TX_4:
5783 case AFE_PORT_ID_QUINARY_TDM_RX_5:
5784 case AFE_PORT_ID_QUINARY_TDM_TX_5:
5785 case AFE_PORT_ID_QUINARY_TDM_RX_6:
5786 case AFE_PORT_ID_QUINARY_TDM_TX_6:
5787 case AFE_PORT_ID_QUINARY_TDM_RX_7:
5788 case AFE_PORT_ID_QUINARY_TDM_TX_7:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305789 case AFE_PORT_ID_INT0_MI2S_RX:
5790 case AFE_PORT_ID_INT1_MI2S_RX:
5791 case AFE_PORT_ID_INT2_MI2S_RX:
5792 case AFE_PORT_ID_INT3_MI2S_RX:
5793 case AFE_PORT_ID_INT4_MI2S_RX:
5794 case AFE_PORT_ID_INT5_MI2S_RX:
5795 case AFE_PORT_ID_INT6_MI2S_RX:
5796 case AFE_PORT_ID_INT0_MI2S_TX:
5797 case AFE_PORT_ID_INT1_MI2S_TX:
5798 case AFE_PORT_ID_INT2_MI2S_TX:
5799 case AFE_PORT_ID_INT3_MI2S_TX:
5800 case AFE_PORT_ID_INT4_MI2S_TX:
5801 case AFE_PORT_ID_INT5_MI2S_TX:
5802 case AFE_PORT_ID_INT6_MI2S_TX:
5803 {
5804 ret = 0;
5805 break;
5806 }
5807
5808 default:
5809 pr_err("%s: default ret 0x%x\n", __func__, port_id);
5810 ret = -EINVAL;
5811 }
5812
5813 return ret;
5814}
5815
5816int afe_convert_virtual_to_portid(u16 port_id)
5817{
5818 int ret;
5819
5820 /*
5821 * if port_id is virtual, convert to physical..
5822 * if port_id is already physical, return physical
5823 */
5824 if (afe_validate_port(port_id) < 0) {
5825 if (port_id == RT_PROXY_DAI_001_RX ||
5826 port_id == RT_PROXY_DAI_001_TX ||
5827 port_id == RT_PROXY_DAI_002_RX ||
5828 port_id == RT_PROXY_DAI_002_TX) {
5829 ret = VIRTUAL_ID_TO_PORTID(port_id);
5830 } else {
5831 pr_err("%s: wrong port 0x%x\n",
5832 __func__, port_id);
5833 ret = -EINVAL;
5834 }
5835 } else
5836 ret = port_id;
5837
5838 return ret;
5839}
5840int afe_port_stop_nowait(int port_id)
5841{
5842 struct afe_port_cmd_device_stop stop;
5843 int ret = 0;
5844
5845 if (this_afe.apr == NULL) {
5846 pr_err("%s: AFE is already closed\n", __func__);
5847 ret = -EINVAL;
5848 goto fail_cmd;
5849 }
5850 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
5851 port_id = q6audio_convert_virtual_to_portid(port_id);
5852
5853 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5854 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5855 stop.hdr.pkt_size = sizeof(stop);
5856 stop.hdr.src_port = 0;
5857 stop.hdr.dest_port = 0;
5858 stop.hdr.token = 0;
5859 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
5860 stop.port_id = port_id;
5861 stop.reserved = 0;
5862
5863 ret = afe_apr_send_pkt(&stop, NULL);
5864 if (ret)
5865 pr_err("%s: AFE close failed %d\n", __func__, ret);
5866
5867fail_cmd:
5868 return ret;
5869
5870}
5871
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305872/**
5873 * afe_close - command to close AFE port
5874 *
5875 * @port_id: AFE port id
5876 *
5877 * Returns 0 on success, appropriate error code otherwise
5878 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305879int afe_close(int port_id)
5880{
5881 struct afe_port_cmd_device_stop stop;
5882 enum afe_mad_type mad_type;
5883 int ret = 0;
5884 int index = 0;
5885 uint16_t port_index;
5886
5887 if (this_afe.apr == NULL) {
5888 pr_err("%s: AFE is already closed\n", __func__);
5889 if ((port_id == RT_PROXY_DAI_001_RX) ||
5890 (port_id == RT_PROXY_DAI_002_TX))
5891 pcm_afe_instance[port_id & 0x1] = 0;
5892 if ((port_id == RT_PROXY_DAI_002_RX) ||
5893 (port_id == RT_PROXY_DAI_001_TX))
5894 proxy_afe_instance[port_id & 0x1] = 0;
5895 afe_close_done[port_id & 0x1] = true;
5896 ret = -EINVAL;
5897 goto fail_cmd;
5898 }
5899 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
5900 if ((port_id == RT_PROXY_DAI_001_RX) ||
5901 (port_id == RT_PROXY_DAI_002_TX)) {
5902 pr_debug("%s: before decrementing pcm_afe_instance %d\n",
5903 __func__, pcm_afe_instance[port_id & 0x1]);
5904 port_id = VIRTUAL_ID_TO_PORTID(port_id);
5905 pcm_afe_instance[port_id & 0x1]--;
5906 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
5907 proxy_afe_instance[port_id & 0x1] == 0)) ||
5908 afe_close_done[port_id & 0x1] == true)
5909 return 0;
5910
5911 afe_close_done[port_id & 0x1] = true;
5912 }
5913
5914 if ((port_id == RT_PROXY_DAI_002_RX) ||
5915 (port_id == RT_PROXY_DAI_001_TX)) {
5916 pr_debug("%s: before decrementing proxy_afe_instance %d\n",
5917 __func__, proxy_afe_instance[port_id & 0x1]);
5918 port_id = VIRTUAL_ID_TO_PORTID(port_id);
5919 proxy_afe_instance[port_id & 0x1]--;
5920 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
5921 proxy_afe_instance[port_id & 0x1] == 0)) ||
5922 afe_close_done[port_id & 0x1] == true)
5923 return 0;
5924
5925 afe_close_done[port_id & 0x1] = true;
5926 }
5927
5928 port_id = q6audio_convert_virtual_to_portid(port_id);
5929 index = q6audio_get_port_index(port_id);
5930 if (index < 0 || index >= AFE_MAX_PORTS) {
5931 pr_err("%s: AFE port index[%d] invalid!\n",
5932 __func__, index);
5933 return -EINVAL;
5934 }
5935 ret = q6audio_validate_port(port_id);
5936 if (ret < 0) {
5937 pr_warn("%s: Not a valid port id 0x%x ret %d\n",
5938 __func__, port_id, ret);
5939 return -EINVAL;
5940 }
5941
5942 mad_type = afe_port_get_mad_type(port_id);
5943 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
5944 mad_type);
5945 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
5946 pr_debug("%s: Turn off MAD\n", __func__);
5947 ret = afe_turn_onoff_hw_mad(mad_type, false);
5948 if (ret) {
5949 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
5950 __func__, ret);
5951 return ret;
5952 }
5953 } else {
5954 pr_debug("%s: Not a MAD port\n", __func__);
5955 }
5956
5957 port_index = afe_get_port_index(port_id);
5958 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
5959 this_afe.afe_sample_rates[port_index] = 0;
5960 this_afe.topology[port_index] = 0;
5961 this_afe.dev_acdb_id[port_index] = 0;
5962 } else {
5963 pr_err("%s: port %d\n", __func__, port_index);
5964 ret = -EINVAL;
5965 goto fail_cmd;
5966 }
5967
5968 if ((port_id == this_afe.aanc_info.aanc_tx_port) &&
5969 (this_afe.aanc_info.aanc_active)) {
5970 memset(&this_afe.aanc_info, 0x00, sizeof(this_afe.aanc_info));
5971 ret = afe_aanc_mod_enable(this_afe.apr, port_id, 0);
5972 if (ret)
5973 pr_err("%s: AFE mod disable failed %d\n",
5974 __func__, ret);
5975 }
5976
5977 /*
5978 * even if ramp down configuration failed it is not serious enough to
5979 * warrant bailaing out.
5980 */
5981 if (afe_spk_ramp_dn_cfg(port_id) < 0)
5982 pr_err("%s: ramp down configuration failed\n", __func__);
5983
5984 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5985 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5986 stop.hdr.pkt_size = sizeof(stop);
5987 stop.hdr.src_port = 0;
5988 stop.hdr.dest_port = 0;
5989 stop.hdr.token = index;
5990 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
5991 stop.port_id = q6audio_get_port_id(port_id);
5992 stop.reserved = 0;
5993
5994 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
5995 if (ret)
5996 pr_err("%s: AFE close failed %d\n", __func__, ret);
5997
5998fail_cmd:
5999 return ret;
6000}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306001EXPORT_SYMBOL(afe_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306002
6003int afe_set_digital_codec_core_clock(u16 port_id,
6004 struct afe_digital_clk_cfg *cfg)
6005{
6006 struct afe_lpass_digital_clk_config_command clk_cfg;
6007 int index = 0;
6008 int ret = 0;
6009
6010 if (!cfg) {
6011 pr_err("%s: clock cfg is NULL\n", __func__);
6012 ret = -EINVAL;
6013 return ret;
6014 }
6015
6016 ret = afe_q6_interface_prepare();
6017 if (ret != 0) {
6018 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6019 return ret;
6020 }
6021
6022 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6023 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6024 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6025 clk_cfg.hdr.src_port = 0;
6026 clk_cfg.hdr.dest_port = 0;
6027 clk_cfg.hdr.token = index;
6028
6029 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6030 /*default rx port is taken to enable the codec digital clock*/
6031 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6032 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6033 - sizeof(clk_cfg.param);
6034 clk_cfg.param.payload_address_lsw = 0x00;
6035 clk_cfg.param.payload_address_msw = 0x00;
6036 clk_cfg.param.mem_map_handle = 0x00;
6037 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6038 clk_cfg.pdata.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
6039 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6040 clk_cfg.clk_cfg = *cfg;
6041
6042 pr_debug("%s: Minor version =0x%x clk val = %d\n"
6043 "clk root = 0x%x resrv = 0x%x\n",
6044 __func__, cfg->i2s_cfg_minor_version,
6045 cfg->clk_val, cfg->clk_root, cfg->reserved);
6046
6047 atomic_set(&this_afe.state, 1);
6048 atomic_set(&this_afe.status, 0);
6049 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6050 if (ret < 0) {
6051 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6052 __func__, port_id, ret);
6053 ret = -EINVAL;
6054 goto fail_cmd;
6055 }
6056
6057 ret = wait_event_timeout(this_afe.wait[index],
6058 (atomic_read(&this_afe.state) == 0),
6059 msecs_to_jiffies(TIMEOUT_MS));
6060 if (!ret) {
6061 pr_err("%s: wait_event timeout\n", __func__);
6062 ret = -EINVAL;
6063 goto fail_cmd;
6064 }
6065 if (atomic_read(&this_afe.status) > 0) {
6066 pr_err("%s: config cmd failed [%s]\n",
6067 __func__, adsp_err_get_err_str(
6068 atomic_read(&this_afe.status)));
6069 ret = adsp_err_get_lnx_err_code(
6070 atomic_read(&this_afe.status));
6071 goto fail_cmd;
6072 }
6073
6074fail_cmd:
6075 return ret;
6076}
6077
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306078/**
6079 * afe_set_lpass_clock - Enable AFE lpass clock
6080 *
6081 * @port_id: AFE port id
6082 * @cfg: pointer to clk set struct
6083 *
6084 * Returns 0 on success, appropriate error code otherwise
6085 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306086int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg)
6087{
6088 struct afe_lpass_clk_config_command clk_cfg;
6089 int index = 0;
6090 int ret = 0;
6091
6092 if (!cfg) {
6093 pr_err("%s: clock cfg is NULL\n", __func__);
6094 ret = -EINVAL;
6095 return ret;
6096 }
6097 index = q6audio_get_port_index(port_id);
6098 if (index < 0 || index >= AFE_MAX_PORTS) {
6099 pr_err("%s: AFE port index[%d] invalid!\n",
6100 __func__, index);
6101 return -EINVAL;
6102 }
6103 ret = q6audio_is_digital_pcm_interface(port_id);
6104 if (ret < 0) {
6105 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6106 __func__, ret);
6107 return -EINVAL;
6108 }
6109
6110 ret = afe_q6_interface_prepare();
6111 if (ret != 0) {
6112 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6113 return ret;
6114 }
6115
6116 mutex_lock(&this_afe.afe_cmd_lock);
6117 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6118 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6119 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6120 clk_cfg.hdr.src_port = 0;
6121 clk_cfg.hdr.dest_port = 0;
6122 clk_cfg.hdr.token = index;
6123
6124 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6125 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6126 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6127 - sizeof(clk_cfg.param);
6128 clk_cfg.param.payload_address_lsw = 0x00;
6129 clk_cfg.param.payload_address_msw = 0x00;
6130 clk_cfg.param.mem_map_handle = 0x00;
6131 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6132 clk_cfg.pdata.param_id = AFE_PARAM_ID_LPAIF_CLK_CONFIG;
6133 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6134 clk_cfg.clk_cfg = *cfg;
6135
6136 pr_debug("%s: Minor version =0x%x clk val1 = %d\n"
6137 "clk val2 = %d, clk src = 0x%x\n"
6138 "clk root = 0x%x clk mode = 0x%x resrv = 0x%x\n"
6139 "port id = 0x%x\n",
6140 __func__, cfg->i2s_cfg_minor_version,
6141 cfg->clk_val1, cfg->clk_val2, cfg->clk_src,
6142 cfg->clk_root, cfg->clk_set_mode,
6143 cfg->reserved, q6audio_get_port_id(port_id));
6144
6145 atomic_set(&this_afe.state, 1);
6146 atomic_set(&this_afe.status, 0);
6147 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6148 if (ret < 0) {
6149 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6150 __func__, port_id, ret);
6151 ret = -EINVAL;
6152 goto fail_cmd;
6153 }
6154
6155 ret = wait_event_timeout(this_afe.wait[index],
6156 (atomic_read(&this_afe.state) == 0),
6157 msecs_to_jiffies(TIMEOUT_MS));
6158 if (!ret) {
6159 pr_err("%s: wait_event timeout\n", __func__);
6160 ret = -EINVAL;
6161 goto fail_cmd;
6162 }
6163 if (atomic_read(&this_afe.status) > 0) {
6164 pr_err("%s: config cmd failed [%s]\n",
6165 __func__, adsp_err_get_err_str(
6166 atomic_read(&this_afe.status)));
6167 ret = adsp_err_get_lnx_err_code(
6168 atomic_read(&this_afe.status));
6169 goto fail_cmd;
6170 }
6171
6172fail_cmd:
6173 mutex_unlock(&this_afe.afe_cmd_lock);
6174 return ret;
6175}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306176EXPORT_SYMBOL(afe_set_lpass_clock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306177
6178/**
6179 * afe_set_lpass_clk_cfg - Set AFE clk config
6180 *
6181 * @index: port index
6182 * @cfg: pointer to clk set struct
6183 *
6184 * Returns 0 on success, appropriate error code otherwise
6185 */
6186int afe_set_lpass_clk_cfg(int index, struct afe_clk_set *cfg)
6187{
6188 struct afe_lpass_clk_config_command_v2 clk_cfg;
6189 int ret = 0;
6190
6191 if (!cfg) {
6192 pr_err("%s: clock cfg is NULL\n", __func__);
6193 ret = -EINVAL;
6194 return ret;
6195 }
6196
6197 if (index < 0 || index >= AFE_MAX_PORTS) {
6198 pr_err("%s: index[%d] invalid!\n", __func__, index);
6199 return -EINVAL;
6200 }
6201
6202 ret = afe_q6_interface_prepare();
6203 if (ret != 0) {
6204 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6205 return ret;
6206 }
6207
6208 mutex_lock(&this_afe.afe_cmd_lock);
6209 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6210 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6211 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6212 clk_cfg.hdr.src_port = 0;
6213 clk_cfg.hdr.dest_port = 0;
6214 clk_cfg.hdr.token = index;
6215
6216 clk_cfg.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
6217 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6218 - sizeof(clk_cfg.param);
6219 clk_cfg.param.payload_address_lsw = 0x00;
6220 clk_cfg.param.payload_address_msw = 0x00;
6221 clk_cfg.param.mem_map_handle = 0x00;
6222 clk_cfg.pdata.module_id = AFE_MODULE_CLOCK_SET;
6223 clk_cfg.pdata.param_id = AFE_PARAM_ID_CLOCK_SET;
6224 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6225 clk_cfg.clk_cfg = *cfg;
6226
6227
6228 pr_debug("%s: Minor version =0x%x clk id = %d\n"
6229 "clk freq (Hz) = %d, clk attri = 0x%x\n"
6230 "clk root = 0x%x clk enable = 0x%x\n",
6231 __func__, cfg->clk_set_minor_version,
6232 cfg->clk_id, cfg->clk_freq_in_hz, cfg->clk_attri,
6233 cfg->clk_root, cfg->enable);
6234
6235 atomic_set(&this_afe.state, 1);
6236 atomic_set(&this_afe.status, 0);
6237 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6238 if (ret < 0) {
6239 pr_err("%s: AFE clk cfg failed with ret %d\n",
6240 __func__, ret);
6241 ret = -EINVAL;
6242 goto fail_cmd;
6243 }
6244
6245 ret = wait_event_timeout(this_afe.wait[index],
6246 (atomic_read(&this_afe.state) == 0),
6247 msecs_to_jiffies(TIMEOUT_MS));
6248 if (!ret) {
6249 pr_err("%s: wait_event timeout\n", __func__);
6250 ret = -EINVAL;
6251 goto fail_cmd;
6252 } else {
6253 /* set ret to 0 as no timeout happened */
6254 ret = 0;
6255 }
6256 if (atomic_read(&this_afe.status) != 0) {
6257 pr_err("%s: config cmd failed\n", __func__);
6258 ret = -EINVAL;
6259 goto fail_cmd;
6260 }
6261
6262fail_cmd:
6263 mutex_unlock(&this_afe.afe_cmd_lock);
6264 return ret;
6265}
6266EXPORT_SYMBOL(afe_set_lpass_clk_cfg);
6267
6268/**
6269 * afe_set_lpass_clock_v2 - Enable AFE lpass clock
6270 *
6271 * @port_id: AFE port id
6272 * @cfg: pointer to clk set struct
6273 *
6274 * Returns 0 on success, appropriate error code otherwise
6275 */
6276int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
6277{
6278 int index = 0;
6279 int ret = 0;
6280
6281 index = q6audio_get_port_index(port_id);
6282 if (index < 0 || index >= AFE_MAX_PORTS) {
6283 pr_err("%s: AFE port index[%d] invalid!\n",
6284 __func__, index);
6285 return -EINVAL;
6286 }
6287 ret = q6audio_is_digital_pcm_interface(port_id);
6288 if (ret < 0) {
6289 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6290 __func__, ret);
6291 return -EINVAL;
6292 }
6293
6294 ret = afe_set_lpass_clk_cfg(index, cfg);
6295 if (ret)
6296 pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
6297 __func__, ret);
6298
6299 return ret;
6300}
6301EXPORT_SYMBOL(afe_set_lpass_clock_v2);
6302
6303int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
6304 struct afe_digital_clk_cfg *cfg)
6305{
6306 struct afe_lpass_digital_clk_config_command clk_cfg;
6307 int index = 0;
6308 int ret = 0;
6309
6310 if (!cfg) {
6311 pr_err("%s: clock cfg is NULL\n", __func__);
6312 ret = -EINVAL;
6313 return ret;
6314 }
6315 index = q6audio_get_port_index(port_id);
6316 if (index < 0 || index >= AFE_MAX_PORTS) {
6317 pr_err("%s: AFE port index[%d] invalid!\n",
6318 __func__, index);
6319 return -EINVAL;
6320 }
6321 ret = q6audio_is_digital_pcm_interface(port_id);
6322 if (ret < 0) {
6323 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6324 __func__, ret);
6325 return -EINVAL;
6326 }
6327
6328 ret = afe_q6_interface_prepare();
6329 if (ret != 0) {
6330 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6331 return ret;
6332 }
6333
6334 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6335 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6336 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6337 clk_cfg.hdr.src_port = 0;
6338 clk_cfg.hdr.dest_port = 0;
6339 clk_cfg.hdr.token = index;
6340
6341 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6342 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6343 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6344 - sizeof(clk_cfg.param);
6345 clk_cfg.param.payload_address_lsw = 0x00;
6346 clk_cfg.param.payload_address_msw = 0x00;
6347 clk_cfg.param.mem_map_handle = 0x00;
6348 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6349 clk_cfg.pdata.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
6350 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6351 clk_cfg.clk_cfg = *cfg;
6352
6353 pr_debug("%s: Minor version =0x%x clk val = %d\n"
6354 "clk root = 0x%x resrv = 0x%x port id = 0x%x\n",
6355 __func__, cfg->i2s_cfg_minor_version,
6356 cfg->clk_val, cfg->clk_root, cfg->reserved,
6357 q6audio_get_port_id(port_id));
6358
6359 atomic_set(&this_afe.state, 1);
6360 atomic_set(&this_afe.status, 0);
6361 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6362 if (ret < 0) {
6363 pr_err("%s: AFE enable for port 0x0x%x ret %d\n",
6364 __func__, port_id, ret);
6365 ret = -EINVAL;
6366 goto fail_cmd;
6367 }
6368
6369 ret = wait_event_timeout(this_afe.wait[index],
6370 (atomic_read(&this_afe.state) == 0),
6371 msecs_to_jiffies(TIMEOUT_MS));
6372 if (!ret) {
6373 pr_err("%s: wait_event timeout\n", __func__);
6374 ret = -EINVAL;
6375 goto fail_cmd;
6376 }
6377 if (atomic_read(&this_afe.status) > 0) {
6378 pr_err("%s: config cmd failed [%s]\n",
6379 __func__, adsp_err_get_err_str(
6380 atomic_read(&this_afe.status)));
6381 ret = adsp_err_get_lnx_err_code(
6382 atomic_read(&this_afe.status));
6383 goto fail_cmd;
6384 }
6385
6386fail_cmd:
6387 return ret;
6388}
6389
6390int afe_enable_lpass_core_shared_clock(u16 port_id, u32 enable)
6391{
6392 struct afe_lpass_core_shared_clk_config_command clk_cfg;
6393 int index = 0;
6394 int ret = 0;
6395
6396 index = q6audio_get_port_index(port_id);
6397 if (index < 0 || index >= AFE_MAX_PORTS) {
6398 pr_err("%s: AFE port index[%d] invalid!\n",
6399 __func__, index);
6400 return -EINVAL;
6401 }
6402 ret = q6audio_is_digital_pcm_interface(port_id);
6403 if (ret < 0) {
6404 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6405 __func__, ret);
6406 return -EINVAL;
6407 }
6408
6409 ret = afe_q6_interface_prepare();
6410 if (ret != 0) {
6411 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6412 return ret;
6413 }
6414
6415 mutex_lock(&this_afe.afe_cmd_lock);
6416 clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6417 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6418 clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
6419 clk_cfg.hdr.src_port = 0;
6420 clk_cfg.hdr.dest_port = 0;
6421 clk_cfg.hdr.token = index;
6422
6423 clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
6424 clk_cfg.param.port_id = q6audio_get_port_id(port_id);
6425 clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
6426 - sizeof(clk_cfg.param);
6427 clk_cfg.param.payload_address_lsw = 0x00;
6428 clk_cfg.param.payload_address_msw = 0x00;
6429 clk_cfg.param.mem_map_handle = 0x00;
6430 clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6431 clk_cfg.pdata.param_id = AFE_PARAM_ID_LPASS_CORE_SHARED_CLOCK_CONFIG;
6432 clk_cfg.pdata.param_size = sizeof(clk_cfg.clk_cfg);
6433 clk_cfg.clk_cfg.lpass_core_shared_clk_cfg_minor_version =
6434 AFE_API_VERSION_LPASS_CORE_SHARED_CLK_CONFIG;
6435 clk_cfg.clk_cfg.enable = enable;
6436
6437 pr_debug("%s: port id = %d, enable = %d\n",
6438 __func__, q6audio_get_port_id(port_id), enable);
6439
6440 atomic_set(&this_afe.state, 1);
6441 atomic_set(&this_afe.status, 0);
6442 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
6443 if (ret < 0) {
6444 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6445 __func__, port_id, ret);
6446 ret = -EINVAL;
6447 goto fail_cmd;
6448 }
6449
6450 ret = wait_event_timeout(this_afe.wait[index],
6451 (atomic_read(&this_afe.state) == 0),
6452 msecs_to_jiffies(TIMEOUT_MS));
6453 if (!ret) {
6454 pr_err("%s: wait_event timeout\n", __func__);
6455 ret = -EINVAL;
6456 goto fail_cmd;
6457 }
6458 if (atomic_read(&this_afe.status) > 0) {
6459 pr_err("%s: config cmd failed [%s]\n",
6460 __func__, adsp_err_get_err_str(
6461 atomic_read(&this_afe.status)));
6462 ret = adsp_err_get_lnx_err_code(
6463 atomic_read(&this_afe.status));
6464 goto fail_cmd;
6465 }
6466
6467fail_cmd:
6468 mutex_unlock(&this_afe.afe_cmd_lock);
6469 return ret;
6470}
6471
6472int q6afe_check_osr_clk_freq(u32 freq)
6473{
6474 int ret = 0;
6475
6476 switch (freq) {
6477 case Q6AFE_LPASS_OSR_CLK_12_P288_MHZ:
6478 case Q6AFE_LPASS_OSR_CLK_8_P192_MHZ:
6479 case Q6AFE_LPASS_OSR_CLK_6_P144_MHZ:
6480 case Q6AFE_LPASS_OSR_CLK_4_P096_MHZ:
6481 case Q6AFE_LPASS_OSR_CLK_3_P072_MHZ:
6482 case Q6AFE_LPASS_OSR_CLK_2_P048_MHZ:
6483 case Q6AFE_LPASS_OSR_CLK_1_P536_MHZ:
6484 case Q6AFE_LPASS_OSR_CLK_1_P024_MHZ:
6485 case Q6AFE_LPASS_OSR_CLK_768_kHZ:
6486 case Q6AFE_LPASS_OSR_CLK_512_kHZ:
6487 break;
6488 default:
6489 pr_err("%s: deafault freq 0x%x\n",
6490 __func__, freq);
6491 ret = -EINVAL;
6492 }
6493 return ret;
6494}
6495
6496int afe_get_sp_th_vi_ftm_data(struct afe_sp_th_vi_get_param *th_vi)
6497{
6498 int ret = -EINVAL;
6499 int index = 0, port = SLIMBUS_4_TX;
6500
6501 if (!th_vi) {
6502 pr_err("%s: Invalid params\n", __func__);
6503 goto done;
6504 }
6505 if (this_afe.vi_tx_port != -1)
6506 port = this_afe.vi_tx_port;
6507
6508 ret = q6audio_validate_port(port);
6509 if (ret < 0) {
6510 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6511 goto done;
6512 }
6513 index = q6audio_get_port_index(port);
6514 if (index < 0) {
6515 pr_err("%s: invalid port 0x%x, index %d\n",
6516 __func__, port, index);
6517 ret = -EINVAL;
6518 goto done;
6519 }
6520 th_vi->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6521 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6522 th_vi->hdr.pkt_size = sizeof(*th_vi);
6523 th_vi->hdr.src_port = 0;
6524 th_vi->hdr.dest_port = 0;
6525 th_vi->hdr.token = index;
6526 th_vi->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6527 th_vi->get_param.mem_map_handle = 0;
6528 th_vi->get_param.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
6529 th_vi->get_param.param_id = AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS;
6530 th_vi->get_param.payload_address_lsw = 0;
6531 th_vi->get_param.payload_address_msw = 0;
6532 th_vi->get_param.payload_size = sizeof(*th_vi)
6533 - sizeof(th_vi->get_param) - sizeof(th_vi->hdr);
6534 th_vi->get_param.port_id = q6audio_get_port_id(port);
6535 th_vi->pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
6536 th_vi->pdata.param_id = AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS;
6537 th_vi->pdata.param_size = sizeof(th_vi->param);
6538 atomic_set(&this_afe.status, 0);
6539 atomic_set(&this_afe.state, 1);
6540 ret = apr_send_pkt(this_afe.apr, (uint32_t *)th_vi);
6541 if (ret < 0) {
6542 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
6543 __func__, port, th_vi->get_param.param_id, ret);
6544 goto done;
6545 }
6546 ret = wait_event_timeout(this_afe.wait[index],
6547 (atomic_read(&this_afe.state) == 0),
6548 msecs_to_jiffies(TIMEOUT_MS));
6549 if (!ret) {
6550 pr_err("%s: wait_event timeout\n", __func__);
6551 ret = -EINVAL;
6552 goto done;
6553 }
6554 if (atomic_read(&this_afe.status) > 0) {
6555 pr_err("%s: config cmd failed [%s]\n",
6556 __func__, adsp_err_get_err_str(
6557 atomic_read(&this_afe.status)));
6558 ret = adsp_err_get_lnx_err_code(atomic_read(&this_afe.status));
6559 goto done;
6560 }
6561 memcpy(&th_vi->param, &this_afe.th_vi_resp.param,
6562 sizeof(this_afe.th_vi_resp.param));
6563 pr_debug("%s: DC resistance %d %d temp %d %d status %d %d\n",
6564 __func__, th_vi->param.dc_res_q24[SP_V2_SPKR_1],
6565 th_vi->param.dc_res_q24[SP_V2_SPKR_2],
6566 th_vi->param.temp_q22[SP_V2_SPKR_1],
6567 th_vi->param.temp_q22[SP_V2_SPKR_2],
6568 th_vi->param.status[SP_V2_SPKR_1],
6569 th_vi->param.status[SP_V2_SPKR_2]);
6570 ret = 0;
6571done:
6572 return ret;
6573}
6574
6575int afe_get_sp_ex_vi_ftm_data(struct afe_sp_ex_vi_get_param *ex_vi)
6576{
6577 int ret = -EINVAL;
6578 int index = 0, port = SLIMBUS_4_TX;
6579
6580 if (!ex_vi) {
6581 pr_err("%s: Invalid params\n", __func__);
6582 goto done;
6583 }
6584 if (this_afe.vi_tx_port != -1)
6585 port = this_afe.vi_tx_port;
6586
6587 ret = q6audio_validate_port(port);
6588 if (ret < 0) {
6589 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6590 goto done;
6591 }
6592
6593 index = q6audio_get_port_index(port);
6594 if (index < 0) {
6595 pr_err("%s: invalid index %d port 0x%x\n", __func__,
6596 index, port);
6597 ret = -EINVAL;
6598 goto done;
6599 }
6600
6601 ex_vi->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6602 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6603 ex_vi->hdr.pkt_size = sizeof(*ex_vi);
6604 ex_vi->hdr.src_port = 0;
6605 ex_vi->hdr.dest_port = 0;
6606 ex_vi->hdr.token = index;
6607 ex_vi->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6608 ex_vi->get_param.mem_map_handle = 0;
6609 ex_vi->get_param.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
6610 ex_vi->get_param.param_id = AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS;
6611 ex_vi->get_param.payload_address_lsw = 0;
6612 ex_vi->get_param.payload_address_msw = 0;
6613 ex_vi->get_param.payload_size = sizeof(*ex_vi)
6614 - sizeof(ex_vi->get_param) - sizeof(ex_vi->hdr);
6615 ex_vi->get_param.port_id = q6audio_get_port_id(port);
6616 ex_vi->pdata.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
6617 ex_vi->pdata.param_id = AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS;
6618 ex_vi->pdata.param_size = sizeof(ex_vi->param);
6619 atomic_set(&this_afe.status, 0);
6620 atomic_set(&this_afe.state, 1);
6621 ret = apr_send_pkt(this_afe.apr, (uint32_t *)ex_vi);
6622 if (ret < 0) {
6623 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
6624 __func__, port, ex_vi->get_param.param_id, ret);
6625 goto done;
6626 }
6627 ret = wait_event_timeout(this_afe.wait[index],
6628 (atomic_read(&this_afe.state) == 0),
6629 msecs_to_jiffies(TIMEOUT_MS));
6630 if (!ret) {
6631 pr_err("%s: wait_event timeout\n", __func__);
6632 ret = -EINVAL;
6633 goto done;
6634 }
6635 if (atomic_read(&this_afe.status) > 0) {
6636 pr_err("%s: config cmd failed [%s]\n",
6637 __func__, adsp_err_get_err_str(
6638 atomic_read(&this_afe.status)));
6639 ret = adsp_err_get_lnx_err_code(atomic_read(&this_afe.status));
6640 goto done;
6641 }
6642 memcpy(&ex_vi->param, &this_afe.ex_vi_resp.param,
6643 sizeof(this_afe.ex_vi_resp.param));
6644 pr_debug("%s: freq %d %d resistance %d %d qfactor %d %d state %d %d\n",
6645 __func__, ex_vi->param.freq_q20[SP_V2_SPKR_1],
6646 ex_vi->param.freq_q20[SP_V2_SPKR_2],
6647 ex_vi->param.resis_q24[SP_V2_SPKR_1],
6648 ex_vi->param.resis_q24[SP_V2_SPKR_2],
6649 ex_vi->param.qmct_q24[SP_V2_SPKR_1],
6650 ex_vi->param.qmct_q24[SP_V2_SPKR_2],
6651 ex_vi->param.status[SP_V2_SPKR_1],
6652 ex_vi->param.status[SP_V2_SPKR_2]);
6653 ret = 0;
6654done:
6655 return ret;
6656}
6657
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306658/**
6659 * afe_get_av_dev_drift -
6660 * command to retrieve AV drift
6661 *
6662 * @timing_stats: timing stats to be updated with AV drift values
6663 * @port: AFE port ID
6664 *
6665 * Returns 0 on success or error on failure
6666 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306667int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
6668 u16 port)
6669{
6670 int ret = -EINVAL;
6671 int index = 0;
6672 struct afe_av_dev_drift_get_param av_dev_drift;
6673
6674 if (!timing_stats) {
6675 pr_err("%s: Invalid params\n", __func__);
6676 goto exit;
6677 }
6678
6679 ret = q6audio_validate_port(port);
6680 if (ret < 0) {
6681 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6682 ret = -EINVAL;
6683 goto exit;
6684 }
6685
6686 index = q6audio_get_port_index(port);
6687 if (index < 0 || index >= AFE_MAX_PORTS) {
6688 pr_err("%s: Invalid AFE port index[%d]\n",
6689 __func__, index);
6690 ret = -EINVAL;
6691 goto exit;
6692 }
6693
6694 memset(&av_dev_drift, 0, sizeof(struct afe_av_dev_drift_get_param));
6695
6696 av_dev_drift.hdr.hdr_field =
6697 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6698 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6699 av_dev_drift.hdr.pkt_size = sizeof(av_dev_drift);
6700 av_dev_drift.hdr.src_port = 0;
6701 av_dev_drift.hdr.dest_port = 0;
6702 av_dev_drift.hdr.token = index;
6703 av_dev_drift.hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6704 av_dev_drift.get_param.mem_map_handle = 0;
6705 av_dev_drift.get_param.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6706 av_dev_drift.get_param.param_id = AFE_PARAM_ID_DEV_TIMING_STATS;
6707 av_dev_drift.get_param.payload_address_lsw = 0;
6708 av_dev_drift.get_param.payload_address_msw = 0;
6709 av_dev_drift.get_param.payload_size = sizeof(av_dev_drift)
6710 - sizeof(av_dev_drift.get_param) - sizeof(av_dev_drift.hdr);
6711 av_dev_drift.get_param.port_id = q6audio_get_port_id(port);
6712 av_dev_drift.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6713 av_dev_drift.pdata.param_id = AFE_PARAM_ID_DEV_TIMING_STATS;
6714 av_dev_drift.pdata.param_size = sizeof(av_dev_drift.timing_stats);
6715 atomic_set(&this_afe.status, 0);
6716 atomic_set(&this_afe.state, 1);
6717 ret = apr_send_pkt(this_afe.apr, (uint32_t *)&av_dev_drift);
6718 if (ret < 0) {
6719 pr_err("%s: get param port 0x%x param id[0x%x] failed %d\n",
6720 __func__, port, av_dev_drift.get_param.param_id, ret);
6721 goto exit;
6722 }
6723
6724 ret = wait_event_timeout(this_afe.wait[index],
6725 (atomic_read(&this_afe.state) == 0),
6726 msecs_to_jiffies(TIMEOUT_MS));
6727 if (!ret) {
6728 pr_err("%s: wait_event timeout\n", __func__);
6729 ret = -EINVAL;
6730 goto exit;
6731 }
6732
6733 if (atomic_read(&this_afe.status) > 0) {
6734 pr_err("%s: config cmd failed [%s]\n",
6735 __func__, adsp_err_get_err_str(
6736 atomic_read(&this_afe.status)));
6737 ret = adsp_err_get_lnx_err_code(
6738 atomic_read(&this_afe.status));
6739 goto exit;
6740 }
6741
6742 memcpy(timing_stats, &this_afe.av_dev_drift_resp.timing_stats,
6743 sizeof(this_afe.av_dev_drift_resp.timing_stats));
6744 ret = 0;
6745exit:
6746 return ret;
6747}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306748EXPORT_SYMBOL(afe_get_av_dev_drift);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306749
6750int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp)
6751{
6752 int ret = -EINVAL;
6753 int index = 0, port = SLIMBUS_4_TX;
6754
6755 if (!calib_resp) {
6756 pr_err("%s: Invalid params\n", __func__);
6757 goto fail_cmd;
6758 }
6759 if (this_afe.vi_tx_port != -1)
6760 port = this_afe.vi_tx_port;
6761
6762 ret = q6audio_validate_port(port);
6763 if (ret < 0) {
6764 pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret);
6765 ret = -EINVAL;
6766 goto fail_cmd;
6767 }
6768 index = q6audio_get_port_index(port);
6769 if (index < 0 || index >= AFE_MAX_PORTS) {
6770 pr_err("%s: AFE port index[%d] invalid!\n",
6771 __func__, index);
6772 ret = -EINVAL;
6773 goto fail_cmd;
6774 }
6775 calib_resp->hdr.hdr_field =
6776 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6777 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6778 calib_resp->hdr.pkt_size = sizeof(*calib_resp);
6779 calib_resp->hdr.src_port = 0;
6780 calib_resp->hdr.dest_port = 0;
6781 calib_resp->hdr.token = index;
6782 calib_resp->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
6783 calib_resp->get_param.mem_map_handle = 0;
6784 calib_resp->get_param.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
6785 calib_resp->get_param.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2;
6786 calib_resp->get_param.payload_address_lsw = 0;
6787 calib_resp->get_param.payload_address_msw = 0;
6788 calib_resp->get_param.payload_size = sizeof(*calib_resp)
6789 - sizeof(calib_resp->get_param) - sizeof(calib_resp->hdr);
6790 calib_resp->get_param.port_id = q6audio_get_port_id(port);
6791 calib_resp->pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
6792 calib_resp->pdata.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2;
6793 calib_resp->pdata.param_size = sizeof(calib_resp->res_cfg);
6794 atomic_set(&this_afe.status, 0);
6795 atomic_set(&this_afe.state, 1);
6796 ret = apr_send_pkt(this_afe.apr, (uint32_t *)calib_resp);
6797 if (ret < 0) {
6798 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
6799 __func__, port, calib_resp->get_param.param_id, ret);
6800 goto fail_cmd;
6801 }
6802 ret = wait_event_timeout(this_afe.wait[index],
6803 (atomic_read(&this_afe.state) == 0),
6804 msecs_to_jiffies(TIMEOUT_MS));
6805 if (!ret) {
6806 pr_err("%s: wait_event timeout\n", __func__);
6807 ret = -EINVAL;
6808 goto fail_cmd;
6809 }
6810 if (atomic_read(&this_afe.status) > 0) {
6811 pr_err("%s: config cmd failed [%s]\n",
6812 __func__, adsp_err_get_err_str(
6813 atomic_read(&this_afe.status)));
6814 ret = adsp_err_get_lnx_err_code(
6815 atomic_read(&this_afe.status));
6816 goto fail_cmd;
6817 }
6818 memcpy(&calib_resp->res_cfg, &this_afe.calib_data.res_cfg,
6819 sizeof(this_afe.calib_data.res_cfg));
6820 pr_info("%s: state %s resistance %d %d\n", __func__,
6821 fbsp_state[calib_resp->res_cfg.th_vi_ca_state],
6822 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1],
6823 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]);
6824 ret = 0;
6825fail_cmd:
6826 return ret;
6827}
6828
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306829/**
6830 * afe_spk_prot_feed_back_cfg -
6831 * command to setup spk protection feedback config
6832 *
6833 * @src_port: source port id
6834 * @dst_port: destination port id
6835 * @l_ch: left speaker active or not
6836 * @r_ch: right speaker active or not
6837 * @enable: flag to enable or disable
6838 *
6839 * Returns 0 on success or error on failure
6840 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306841int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
6842 int l_ch, int r_ch, u32 enable)
6843{
6844 int ret = -EINVAL;
6845 union afe_spkr_prot_config prot_config;
6846 int index = 0;
6847
6848 if (!enable) {
6849 pr_debug("%s: Disable Feedback tx path", __func__);
6850 this_afe.vi_tx_port = -1;
6851 this_afe.vi_rx_port = -1;
6852 return 0;
6853 }
6854
6855 if ((q6audio_validate_port(src_port) < 0) ||
6856 (q6audio_validate_port(dst_port) < 0)) {
6857 pr_err("%s: invalid ports src 0x%x dst 0x%x",
6858 __func__, src_port, dst_port);
6859 goto fail_cmd;
6860 }
6861 if (!l_ch && !r_ch) {
6862 pr_err("%s: error ch values zero\n", __func__);
6863 goto fail_cmd;
6864 }
6865 pr_debug("%s: src_port 0x%x dst_port 0x%x l_ch %d r_ch %d\n",
6866 __func__, src_port, dst_port, l_ch, r_ch);
6867 memset(&prot_config, 0, sizeof(prot_config));
6868 prot_config.feedback_path_cfg.dst_portid =
6869 q6audio_get_port_id(dst_port);
6870 if (l_ch) {
6871 prot_config.feedback_path_cfg.chan_info[index++] = 1;
6872 prot_config.feedback_path_cfg.chan_info[index++] = 2;
6873 }
6874 if (r_ch) {
6875 prot_config.feedback_path_cfg.chan_info[index++] = 3;
6876 prot_config.feedback_path_cfg.chan_info[index++] = 4;
6877 }
6878 prot_config.feedback_path_cfg.num_channels = index;
6879 pr_debug("%s no of channels: %d\n", __func__, index);
6880 prot_config.feedback_path_cfg.minor_version = 1;
6881 ret = afe_spk_prot_prepare(src_port, dst_port,
6882 AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config);
6883fail_cmd:
6884 return ret;
6885}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306886EXPORT_SYMBOL(afe_spk_prot_feed_back_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306887
6888static int get_cal_type_index(int32_t cal_type)
6889{
6890 int ret = -EINVAL;
6891
6892 switch (cal_type) {
6893 case AFE_COMMON_RX_CAL_TYPE:
6894 ret = AFE_COMMON_RX_CAL;
6895 break;
6896 case AFE_COMMON_TX_CAL_TYPE:
6897 ret = AFE_COMMON_TX_CAL;
6898 break;
6899 case AFE_AANC_CAL_TYPE:
6900 ret = AFE_AANC_CAL;
6901 break;
6902 case AFE_HW_DELAY_CAL_TYPE:
6903 ret = AFE_HW_DELAY_CAL;
6904 break;
6905 case AFE_FB_SPKR_PROT_CAL_TYPE:
6906 ret = AFE_FB_SPKR_PROT_CAL;
6907 break;
6908 case AFE_SIDETONE_CAL_TYPE:
6909 ret = AFE_SIDETONE_CAL;
6910 break;
6911 case AFE_SIDETONE_IIR_CAL_TYPE:
6912 ret = AFE_SIDETONE_IIR_CAL;
6913 break;
6914 case AFE_TOPOLOGY_CAL_TYPE:
6915 ret = AFE_TOPOLOGY_CAL;
6916 break;
6917 case AFE_CUST_TOPOLOGY_CAL_TYPE:
6918 ret = AFE_CUST_TOPOLOGY_CAL;
6919 break;
6920 default:
6921 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
6922 }
6923 return ret;
6924}
6925
6926int afe_alloc_cal(int32_t cal_type, size_t data_size,
6927 void *data)
6928{
6929 int ret = 0;
6930 int cal_index;
6931
6932 cal_index = get_cal_type_index(cal_type);
6933 pr_debug("%s: cal_type = %d cal_index = %d\n",
6934 __func__, cal_type, cal_index);
6935
6936 if (cal_index < 0) {
6937 pr_err("%s: could not get cal index %d!\n",
6938 __func__, cal_index);
6939 ret = -EINVAL;
6940 goto done;
6941 }
6942
6943 ret = cal_utils_alloc_cal(data_size, data,
6944 this_afe.cal_data[cal_index], 0, NULL);
6945 if (ret < 0) {
6946 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
6947 __func__, ret, cal_type);
6948 ret = -EINVAL;
6949 goto done;
6950 }
6951done:
6952 return ret;
6953}
6954
6955static int afe_dealloc_cal(int32_t cal_type, size_t data_size,
6956 void *data)
6957{
6958 int ret = 0;
6959 int cal_index;
6960
6961 pr_debug("%s:\n", __func__);
6962
6963 cal_index = get_cal_type_index(cal_type);
6964 if (cal_index < 0) {
6965 pr_err("%s: could not get cal index %d!\n",
6966 __func__, cal_index);
6967 ret = -EINVAL;
6968 goto done;
6969 }
6970
6971 ret = cal_utils_dealloc_cal(data_size, data,
6972 this_afe.cal_data[cal_index]);
6973 if (ret < 0) {
6974 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
6975 __func__, ret, cal_type);
6976 ret = -EINVAL;
6977 goto done;
6978 }
6979done:
6980 return ret;
6981}
6982
6983static int afe_set_cal(int32_t cal_type, size_t data_size,
6984 void *data)
6985{
6986 int ret = 0;
6987 int cal_index;
6988
6989 pr_debug("%s:\n", __func__);
6990
6991 cal_index = get_cal_type_index(cal_type);
6992 if (cal_index < 0) {
6993 pr_err("%s: could not get cal index %d!\n",
6994 __func__, cal_index);
6995 ret = -EINVAL;
6996 goto done;
6997 }
6998
6999 ret = cal_utils_set_cal(data_size, data,
7000 this_afe.cal_data[cal_index], 0, NULL);
7001 if (ret < 0) {
7002 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
7003 __func__, ret, cal_type);
7004 ret = -EINVAL;
7005 goto done;
7006 }
7007
7008 if (cal_index == AFE_CUST_TOPOLOGY_CAL) {
7009 mutex_lock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
7010 this_afe.set_custom_topology = 1;
7011 pr_debug("%s:[AFE_CUSTOM_TOPOLOGY] ret = %d, cal type = %d!\n",
7012 __func__, ret, cal_type);
7013 mutex_unlock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
7014 }
7015
7016done:
7017 return ret;
7018}
7019
7020static struct cal_block_data *afe_find_hw_delay_by_path(
7021 struct cal_type_data *cal_type, int path)
7022{
7023 struct list_head *ptr, *next;
7024 struct cal_block_data *cal_block = NULL;
7025
7026 pr_debug("%s:\n", __func__);
7027
7028 list_for_each_safe(ptr, next,
7029 &cal_type->cal_blocks) {
7030
7031 cal_block = list_entry(ptr,
7032 struct cal_block_data, list);
7033
7034 if (((struct audio_cal_info_hw_delay *)cal_block->cal_info)
7035 ->path == path) {
7036 return cal_block;
7037 }
7038 }
7039 return NULL;
7040}
7041
7042static int afe_get_cal_hw_delay(int32_t path,
7043 struct audio_cal_hw_delay_entry *entry)
7044{
7045 int ret = 0;
7046 int i;
7047 struct cal_block_data *cal_block = NULL;
7048 struct audio_cal_hw_delay_data *hw_delay_info = NULL;
7049
7050 pr_debug("%s:\n", __func__);
7051
7052 if (this_afe.cal_data[AFE_HW_DELAY_CAL] == NULL) {
7053 pr_err("%s: AFE_HW_DELAY_CAL not initialized\n", __func__);
7054 ret = -EINVAL;
7055 goto done;
7056 }
7057 if (entry == NULL) {
7058 pr_err("%s: entry is NULL\n", __func__);
7059 ret = -EINVAL;
7060 goto done;
7061 }
7062 if ((path >= MAX_PATH_TYPE) || (path < 0)) {
7063 pr_err("%s: bad path: %d\n",
7064 __func__, path);
7065 ret = -EINVAL;
7066 goto done;
7067 }
7068
7069 mutex_lock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
7070 cal_block = afe_find_hw_delay_by_path(
7071 this_afe.cal_data[AFE_HW_DELAY_CAL], path);
7072 if (cal_block == NULL)
7073 goto unlock;
7074
7075 hw_delay_info = &((struct audio_cal_info_hw_delay *)
7076 cal_block->cal_info)->data;
7077 if (hw_delay_info->num_entries > MAX_HW_DELAY_ENTRIES) {
7078 pr_err("%s: invalid num entries: %d\n",
7079 __func__, hw_delay_info->num_entries);
7080 ret = -EINVAL;
7081 goto unlock;
7082 }
7083
7084 for (i = 0; i < hw_delay_info->num_entries; i++) {
7085 if (hw_delay_info->entry[i].sample_rate ==
7086 entry->sample_rate) {
7087 entry->delay_usec = hw_delay_info->entry[i].delay_usec;
7088 break;
7089 }
7090 }
7091 if (i == hw_delay_info->num_entries) {
7092 pr_err("%s: Unable to find delay for sample rate %d\n",
7093 __func__, entry->sample_rate);
7094 ret = -EFAULT;
7095 goto unlock;
7096 }
7097 pr_debug("%s: Path = %d samplerate = %u usec = %u status %d\n",
7098 __func__, path, entry->sample_rate, entry->delay_usec, ret);
7099unlock:
7100 mutex_unlock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
7101done:
7102 return ret;
7103}
7104
7105static int afe_set_cal_sp_th_vi_ftm_cfg(int32_t cal_type, size_t data_size,
7106 void *data)
7107{
7108 int ret = 0;
7109 struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data;
7110
7111 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
7112 cal_data == NULL ||
7113 data_size != sizeof(*cal_data))
7114 goto done;
7115
7116 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7117 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7118 memcpy(&this_afe.th_ftm_cfg, &cal_data->cal_info,
7119 sizeof(this_afe.th_ftm_cfg));
7120 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7121done:
7122 return ret;
7123}
7124
7125static int afe_set_cal_sp_ex_vi_ftm_cfg(int32_t cal_type, size_t data_size,
7126 void *data)
7127{
7128 int ret = 0;
7129 struct audio_cal_type_sp_ex_vi_ftm_cfg *cal_data = data;
7130
7131 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
7132 cal_data == NULL ||
7133 data_size != sizeof(*cal_data))
7134 goto done;
7135
7136 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7137 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7138 memcpy(&this_afe.ex_ftm_cfg, &cal_data->cal_info,
7139 sizeof(this_afe.ex_ftm_cfg));
7140 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7141done:
7142 return ret;
7143}
7144
7145static int afe_set_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
7146 void *data)
7147{
7148 int ret = 0;
7149 struct audio_cal_type_fb_spk_prot_cfg *cal_data = data;
7150
7151 pr_debug("%s:\n", __func__);
7152
7153 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
7154 goto done;
7155 if (cal_data == NULL)
7156 goto done;
7157 if (data_size != sizeof(*cal_data))
7158 goto done;
7159
7160 if (cal_data->cal_info.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
7161 __pm_wakeup_event(&wl.ws, jiffies_to_msecs(WAKELOCK_TIMEOUT));
7162 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7163 memcpy(&this_afe.prot_cfg, &cal_data->cal_info,
7164 sizeof(this_afe.prot_cfg));
7165 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7166done:
7167 return ret;
7168}
7169
7170static int afe_get_cal_sp_th_vi_ftm_param(int32_t cal_type, size_t data_size,
7171 void *data)
7172{
7173 int i, ret = 0;
7174 struct audio_cal_type_sp_th_vi_param *cal_data = data;
7175 struct afe_sp_th_vi_get_param th_vi;
7176
7177 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7178 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
7179 cal_data == NULL ||
7180 data_size != sizeof(*cal_data))
7181 goto done;
7182
7183 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7184 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7185 cal_data->cal_info.status[i] = -EINVAL;
7186 cal_data->cal_info.r_dc_q24[i] = -1;
7187 cal_data->cal_info.temp_q22[i] = -1;
7188 }
7189 if (!afe_get_sp_th_vi_ftm_data(&th_vi)) {
7190 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7191 pr_debug("%s: ftm param status = %d\n",
7192 __func__, th_vi.param.status[i]);
7193 if (th_vi.param.status[i] == FBSP_IN_PROGRESS) {
7194 cal_data->cal_info.status[i] = -EAGAIN;
7195 } else if (th_vi.param.status[i] == FBSP_SUCCESS) {
7196 cal_data->cal_info.status[i] = 0;
7197 cal_data->cal_info.r_dc_q24[i] =
7198 th_vi.param.dc_res_q24[i];
7199 cal_data->cal_info.temp_q22[i] =
7200 th_vi.param.temp_q22[i];
7201 }
7202 }
7203 }
7204 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7205done:
7206 return ret;
7207}
7208
7209static int afe_get_cal_sp_ex_vi_ftm_param(int32_t cal_type, size_t data_size,
7210 void *data)
7211{
7212 int i, ret = 0;
7213 struct audio_cal_type_sp_ex_vi_param *cal_data = data;
7214 struct afe_sp_ex_vi_get_param ex_vi;
7215
7216 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7217 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
7218 cal_data == NULL ||
7219 data_size != sizeof(*cal_data))
7220 goto done;
7221
7222 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7223 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7224 cal_data->cal_info.status[i] = -EINVAL;
7225 cal_data->cal_info.freq_q20[i] = -1;
7226 cal_data->cal_info.resis_q24[i] = -1;
7227 cal_data->cal_info.qmct_q24[i] = -1;
7228 }
7229 if (!afe_get_sp_ex_vi_ftm_data(&ex_vi)) {
7230 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7231 pr_debug("%s: ftm param status = %d\n",
7232 __func__, ex_vi.param.status[i]);
7233 if (ex_vi.param.status[i] == FBSP_IN_PROGRESS) {
7234 cal_data->cal_info.status[i] = -EAGAIN;
7235 } else if (ex_vi.param.status[i] == FBSP_SUCCESS) {
7236 cal_data->cal_info.status[i] = 0;
7237 cal_data->cal_info.freq_q20[i] =
7238 ex_vi.param.freq_q20[i];
7239 cal_data->cal_info.resis_q24[i] =
7240 ex_vi.param.resis_q24[i];
7241 cal_data->cal_info.qmct_q24[i] =
7242 ex_vi.param.qmct_q24[i];
7243 }
7244 }
7245 }
7246 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7247done:
7248 return ret;
7249}
7250
7251static int afe_get_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
7252 void *data)
7253{
7254 int ret = 0;
7255 struct audio_cal_type_fb_spk_prot_status *cal_data = data;
7256 struct afe_spkr_prot_get_vi_calib calib_resp;
7257
7258 pr_debug("%s:\n", __func__);
7259
7260 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
7261 goto done;
7262 if (cal_data == NULL)
7263 goto done;
7264 if (data_size != sizeof(*cal_data))
7265 goto done;
7266
7267 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7268 if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATED) {
7269 cal_data->cal_info.r0[SP_V2_SPKR_1] =
7270 this_afe.prot_cfg.r0[SP_V2_SPKR_1];
7271 cal_data->cal_info.r0[SP_V2_SPKR_2] =
7272 this_afe.prot_cfg.r0[SP_V2_SPKR_2];
7273 cal_data->cal_info.status = 0;
7274 } else if (this_afe.prot_cfg.mode ==
7275 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
7276 /*Call AFE to query the status*/
7277 cal_data->cal_info.status = -EINVAL;
7278 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
7279 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
7280 if (!afe_spk_prot_get_calib_data(&calib_resp)) {
7281 if (calib_resp.res_cfg.th_vi_ca_state ==
7282 FBSP_IN_PROGRESS)
7283 cal_data->cal_info.status = -EAGAIN;
7284 else if (calib_resp.res_cfg.th_vi_ca_state ==
7285 FBSP_SUCCESS) {
7286 cal_data->cal_info.status = 0;
7287 cal_data->cal_info.r0[SP_V2_SPKR_1] =
7288 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_1];
7289 cal_data->cal_info.r0[SP_V2_SPKR_2] =
7290 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_2];
7291 }
7292 }
7293 if (!cal_data->cal_info.status) {
7294 this_afe.prot_cfg.mode =
7295 MSM_SPKR_PROT_CALIBRATED;
7296 this_afe.prot_cfg.r0[SP_V2_SPKR_1] =
7297 cal_data->cal_info.r0[SP_V2_SPKR_1];
7298 this_afe.prot_cfg.r0[SP_V2_SPKR_2] =
7299 cal_data->cal_info.r0[SP_V2_SPKR_2];
7300 }
7301 } else {
7302 /*Indicates calibration data is invalid*/
7303 cal_data->cal_info.status = -EINVAL;
7304 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
7305 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
7306 }
7307 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7308 __pm_relax(&wl.ws);
7309done:
7310 return ret;
7311}
7312
7313static int afe_map_cal_data(int32_t cal_type,
7314 struct cal_block_data *cal_block)
7315{
7316 int ret = 0;
7317 int cal_index;
7318
7319 pr_debug("%s:\n", __func__);
7320
7321 cal_index = get_cal_type_index(cal_type);
7322 if (cal_index < 0) {
7323 pr_err("%s: could not get cal index %d!\n",
7324 __func__, cal_index);
7325 ret = -EINVAL;
7326 goto done;
7327 }
7328
7329
7330 mutex_lock(&this_afe.afe_cmd_lock);
7331 atomic_set(&this_afe.mem_map_cal_index, cal_index);
7332 ret = afe_cmd_memory_map(cal_block->cal_data.paddr,
7333 cal_block->map_data.map_size);
7334 atomic_set(&this_afe.mem_map_cal_index, -1);
7335 if (ret < 0) {
7336 pr_err("%s: mmap did not work! size = %zd ret %d\n",
7337 __func__,
7338 cal_block->map_data.map_size, ret);
7339 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
7340 __func__,
7341 &cal_block->cal_data.paddr,
7342 cal_block->map_data.map_size);
7343 mutex_unlock(&this_afe.afe_cmd_lock);
7344 goto done;
7345 }
7346 cal_block->map_data.q6map_handle = atomic_read(&this_afe.
7347 mem_map_cal_handles[cal_index]);
7348 mutex_unlock(&this_afe.afe_cmd_lock);
7349done:
7350 return ret;
7351}
7352
7353static int afe_unmap_cal_data(int32_t cal_type,
7354 struct cal_block_data *cal_block)
7355{
7356 int ret = 0;
7357 int cal_index;
7358
7359 pr_debug("%s:\n", __func__);
7360
7361 cal_index = get_cal_type_index(cal_type);
7362 if (cal_index < 0) {
7363 pr_err("%s: could not get cal index %d!\n",
7364 __func__, cal_index);
7365 ret = -EINVAL;
7366 goto done;
7367 }
7368
7369 if (cal_block == NULL) {
7370 pr_err("%s: Cal block is NULL!\n",
7371 __func__);
7372 goto done;
7373 }
7374
7375 if (cal_block->map_data.q6map_handle == 0) {
7376 pr_err("%s: Map handle is NULL, nothing to unmap\n",
7377 __func__);
7378 goto done;
7379 }
7380
7381 atomic_set(&this_afe.mem_map_cal_handles[cal_index],
7382 cal_block->map_data.q6map_handle);
7383 atomic_set(&this_afe.mem_map_cal_index, cal_index);
7384 ret = afe_cmd_memory_unmap_nowait(
7385 cal_block->map_data.q6map_handle);
7386 atomic_set(&this_afe.mem_map_cal_index, -1);
7387 if (ret < 0) {
7388 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
7389 __func__, cal_index, ret);
7390 }
7391 cal_block->map_data.q6map_handle = 0;
7392done:
7393 return ret;
7394}
7395
7396static void afe_delete_cal_data(void)
7397{
7398 pr_debug("%s:\n", __func__);
7399
7400 cal_utils_destroy_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data);
7401}
7402
7403static int afe_init_cal_data(void)
7404{
7405 int ret = 0;
7406 struct cal_type_info cal_type_info[] = {
7407 {{AFE_COMMON_RX_CAL_TYPE,
7408 {afe_alloc_cal, afe_dealloc_cal, NULL,
7409 afe_set_cal, NULL, NULL} },
7410 {afe_map_cal_data, afe_unmap_cal_data,
7411 cal_utils_match_buf_num} },
7412
7413 {{AFE_COMMON_TX_CAL_TYPE,
7414 {afe_alloc_cal, afe_dealloc_cal, NULL,
7415 afe_set_cal, NULL, NULL} },
7416 {afe_map_cal_data, afe_unmap_cal_data,
7417 cal_utils_match_buf_num} },
7418
7419 {{AFE_AANC_CAL_TYPE,
7420 {afe_alloc_cal, afe_dealloc_cal, NULL,
7421 afe_set_cal, NULL, NULL} },
7422 {afe_map_cal_data, afe_unmap_cal_data,
7423 cal_utils_match_buf_num} },
7424
7425 {{AFE_FB_SPKR_PROT_CAL_TYPE,
7426 {NULL, NULL, NULL, afe_set_cal_fb_spkr_prot,
7427 afe_get_cal_fb_spkr_prot, NULL} },
7428 {NULL, NULL, cal_utils_match_buf_num} },
7429
7430 {{AFE_HW_DELAY_CAL_TYPE,
7431 {NULL, NULL, NULL,
7432 afe_set_cal, NULL, NULL} },
7433 {NULL, NULL, cal_utils_match_buf_num} },
7434
7435 {{AFE_SIDETONE_CAL_TYPE,
7436 {NULL, NULL, NULL,
7437 afe_set_cal, NULL, NULL} },
7438 {NULL, NULL, cal_utils_match_buf_num} },
7439
7440 {{AFE_SIDETONE_IIR_CAL_TYPE,
7441 {NULL, NULL, NULL,
7442 afe_set_cal, NULL, NULL} },
7443 {NULL, NULL, cal_utils_match_buf_num} },
7444
7445 {{AFE_TOPOLOGY_CAL_TYPE,
7446 {NULL, NULL, NULL,
7447 afe_set_cal, NULL, NULL} },
7448 {NULL, NULL,
7449 cal_utils_match_buf_num} },
7450
7451 {{AFE_CUST_TOPOLOGY_CAL_TYPE,
7452 {afe_alloc_cal, afe_dealloc_cal, NULL,
7453 afe_set_cal, NULL, NULL} },
7454 {afe_map_cal_data, afe_unmap_cal_data,
7455 cal_utils_match_buf_num} },
7456
7457 {{AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE,
7458 {NULL, NULL, NULL, afe_set_cal_sp_th_vi_ftm_cfg,
7459 afe_get_cal_sp_th_vi_ftm_param, NULL} },
7460 {NULL, NULL, cal_utils_match_buf_num} },
7461
7462 {{AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE,
7463 {NULL, NULL, NULL, afe_set_cal_sp_ex_vi_ftm_cfg,
7464 afe_get_cal_sp_ex_vi_ftm_param, NULL} },
7465 {NULL, NULL, cal_utils_match_buf_num} },
7466 };
7467 pr_debug("%s:\n", __func__);
7468
7469 ret = cal_utils_create_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data,
7470 cal_type_info);
7471 if (ret < 0) {
7472 pr_err("%s: could not create cal type! %d\n",
7473 __func__, ret);
7474 ret = -EINVAL;
7475 goto err;
7476 }
7477
7478 return ret;
7479err:
7480 afe_delete_cal_data();
7481 return ret;
7482}
7483
7484int afe_map_rtac_block(struct rtac_cal_block_data *cal_block)
7485{
7486 int result = 0;
7487
7488 pr_debug("%s:\n", __func__);
7489
7490 if (cal_block == NULL) {
7491 pr_err("%s: cal_block is NULL!\n",
7492 __func__);
7493 result = -EINVAL;
7494 goto done;
7495 }
7496
7497 if (cal_block->cal_data.paddr == 0) {
7498 pr_debug("%s: No address to map!\n",
7499 __func__);
7500 result = -EINVAL;
7501 goto done;
7502 }
7503
7504 if (cal_block->map_data.map_size == 0) {
7505 pr_debug("%s: map size is 0!\n",
7506 __func__);
7507 result = -EINVAL;
7508 goto done;
7509 }
7510
7511 result = afe_cmd_memory_map(cal_block->cal_data.paddr,
7512 cal_block->map_data.map_size);
7513 if (result < 0) {
7514 pr_err("%s: afe_cmd_memory_map failed for addr = 0x%pK, size = %d, err %d\n",
7515 __func__, &cal_block->cal_data.paddr,
7516 cal_block->map_data.map_size, result);
7517 return result;
7518 }
7519 cal_block->map_data.map_handle = this_afe.mmap_handle;
7520
7521done:
7522 return result;
7523}
7524
7525int afe_unmap_rtac_block(uint32_t *mem_map_handle)
7526{
7527 int result = 0;
7528
7529 pr_debug("%s:\n", __func__);
7530
7531 if (mem_map_handle == NULL) {
7532 pr_err("%s: Map handle is NULL, nothing to unmap\n",
7533 __func__);
7534 goto done;
7535 }
7536
7537 if (*mem_map_handle == 0) {
7538 pr_debug("%s: Map handle is 0, nothing to unmap\n",
7539 __func__);
7540 goto done;
7541 }
7542
7543 result = afe_cmd_memory_unmap(*mem_map_handle);
7544 if (result) {
7545 pr_err("%s: AFE memory unmap failed %d, handle 0x%x\n",
7546 __func__, result, *mem_map_handle);
7547 goto done;
7548 } else {
7549 *mem_map_handle = 0;
7550 }
7551
7552done:
7553 return result;
7554}
7555
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307556int __init afe_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307557{
7558 int i = 0, ret;
7559
7560 atomic_set(&this_afe.state, 0);
7561 atomic_set(&this_afe.status, 0);
7562 atomic_set(&this_afe.mem_map_cal_index, -1);
7563 this_afe.apr = NULL;
7564 this_afe.dtmf_gen_rx_portid = -1;
7565 this_afe.mmap_handle = 0;
7566 this_afe.vi_tx_port = -1;
7567 this_afe.vi_rx_port = -1;
7568 this_afe.prot_cfg.mode = MSM_SPKR_PROT_DISABLED;
7569 this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
7570 this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
7571 mutex_init(&this_afe.afe_cmd_lock);
7572 for (i = 0; i < AFE_MAX_PORTS; i++) {
7573 this_afe.afe_cal_mode[i] = AFE_CAL_MODE_DEFAULT;
7574 this_afe.afe_sample_rates[i] = 0;
7575 this_afe.dev_acdb_id[i] = 0;
7576 init_waitqueue_head(&this_afe.wait[i]);
7577 }
7578 wakeup_source_init(&wl.ws, "spkr-prot");
7579 ret = afe_init_cal_data();
7580 if (ret)
7581 pr_err("%s: could not init cal data! %d\n", __func__, ret);
7582
7583 config_debug_fs_init();
7584 return 0;
7585}
7586
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307587void __exit afe_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307588{
7589 afe_delete_cal_data();
7590
7591 config_debug_fs_exit();
7592 mutex_destroy(&this_afe.afe_cmd_lock);
7593 wakeup_source_trash(&wl.ws);
7594}