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