blob: c813ad12bd4c0d91f59bf807c97cee1afcb02e48 [file] [log] [blame]
Banajit Goswami08bb7362017-11-03 22:48:23 -07001/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/slab.h>
13#include <linux/debugfs.h>
14#include <linux/kernel.h>
15#include <linux/kthread.h>
16#include <linux/uaccess.h>
17#include <linux/wait.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053018#include <linux/jiffies.h>
19#include <linux/sched.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053020#include <linux/delay.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053021#include <dsp/msm_audio_ion.h>
22#include <dsp/apr_audio-v2.h>
23#include <dsp/audio_cal_utils.h>
24#include <dsp/q6afe-v2.h>
25#include <dsp/q6audio-v2.h>
Vignesh Kulothungan85073c02018-01-26 10:27:56 -080026#include <dsp/q6common.h>
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -070027#include <dsp/q6core.h>
Vidyakumar Athota94bd8732018-02-28 17:13:35 -080028#include <dsp/msm-audio-event-notify.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053029#include <ipc/apr_tal.h>
30#include "adsp_err.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053031
32#define WAKELOCK_TIMEOUT 5000
33enum {
34 AFE_COMMON_RX_CAL = 0,
35 AFE_COMMON_TX_CAL,
Aditya Bavanari3889b4a2017-11-21 19:52:26 +053036 AFE_LSM_TX_CAL,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053037 AFE_AANC_CAL,
38 AFE_FB_SPKR_PROT_CAL,
39 AFE_HW_DELAY_CAL,
40 AFE_SIDETONE_CAL,
41 AFE_SIDETONE_IIR_CAL,
42 AFE_TOPOLOGY_CAL,
Aditya Bavanari3889b4a2017-11-21 19:52:26 +053043 AFE_LSM_TOPOLOGY_CAL,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053044 AFE_CUST_TOPOLOGY_CAL,
45 AFE_FB_SPKR_PROT_TH_VI_CAL,
46 AFE_FB_SPKR_PROT_EX_VI_CAL,
47 MAX_AFE_CAL_TYPES
48};
49
50enum fbsp_state {
51 FBSP_INCORRECT_OP_MODE,
52 FBSP_INACTIVE,
53 FBSP_WARMUP,
54 FBSP_IN_PROGRESS,
55 FBSP_SUCCESS,
56 FBSP_FAILED,
57 MAX_FBSP_STATE
58};
59
60static char fbsp_state[MAX_FBSP_STATE][50] = {
61 [FBSP_INCORRECT_OP_MODE] = "incorrect operation mode",
62 [FBSP_INACTIVE] = "port not started",
63 [FBSP_WARMUP] = "waiting for warmup",
64 [FBSP_IN_PROGRESS] = "in progress state",
65 [FBSP_SUCCESS] = "success",
66 [FBSP_FAILED] = "failed"
67};
68
69enum {
70 USE_CALIBRATED_R0TO,
71 USE_SAFE_R0TO
72};
73
74enum {
75 QUICK_CALIB_DISABLE,
76 QUICK_CALIB_ENABLE
77};
78
79enum {
80 Q6AFE_MSM_SPKR_PROCESSING = 0,
81 Q6AFE_MSM_SPKR_CALIBRATION,
82 Q6AFE_MSM_SPKR_FTM_MODE
83};
84
85struct wlock {
86 struct wakeup_source ws;
87};
88
89static struct wlock wl;
90
91struct afe_ctl {
92 void *apr;
93 atomic_t state;
94 atomic_t status;
95 wait_queue_head_t wait[AFE_MAX_PORTS];
96 struct task_struct *task;
97 void (*tx_cb)(uint32_t opcode,
98 uint32_t token, uint32_t *payload, void *priv);
99 void (*rx_cb)(uint32_t opcode,
100 uint32_t token, uint32_t *payload, void *priv);
101 void *tx_private_data;
102 void *rx_private_data;
103 uint32_t mmap_handle;
104
105 int topology[AFE_MAX_PORTS];
106 struct cal_type_data *cal_data[MAX_AFE_CAL_TYPES];
107
108 atomic_t mem_map_cal_handles[MAX_AFE_CAL_TYPES];
109 atomic_t mem_map_cal_index;
110 u32 afe_cal_mode[AFE_MAX_PORTS];
111
112 u16 dtmf_gen_rx_portid;
113 struct audio_cal_info_spk_prot_cfg prot_cfg;
114 struct afe_spkr_prot_calib_get_resp calib_data;
115 struct audio_cal_info_sp_th_vi_ftm_cfg th_ftm_cfg;
116 struct audio_cal_info_sp_ex_vi_ftm_cfg ex_ftm_cfg;
117 struct afe_sp_th_vi_get_param_resp th_vi_resp;
118 struct afe_sp_ex_vi_get_param_resp ex_vi_resp;
119 struct afe_av_dev_drift_get_param_resp av_dev_drift_resp;
120 int vi_tx_port;
121 int vi_rx_port;
122 uint32_t afe_sample_rates[AFE_MAX_PORTS];
123 struct aanc_data aanc_info;
124 struct mutex afe_cmd_lock;
125 int set_custom_topology;
126 int dev_acdb_id[AFE_MAX_PORTS];
127 routing_cb rt_cb;
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -0700128 struct audio_uevent_data *uevent_data;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530129};
130
131static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
132static unsigned long afe_configured_cmd;
133
134static struct afe_ctl this_afe;
135
136#define TIMEOUT_MS 1000
137#define Q6AFE_MAX_VOLUME 0x3FFF
138
139static int pcm_afe_instance[2];
140static int proxy_afe_instance[2];
141bool afe_close_done[2] = {true, true};
142
143#define SIZEOF_CFG_CMD(y) \
144 (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
145
146static int afe_get_cal_hw_delay(int32_t path,
147 struct audio_cal_hw_delay_entry *entry);
148static int remap_cal_data(struct cal_block_data *cal_block, int cal_index);
149
150int afe_get_topology(int port_id)
151{
152 int topology;
153 int port_index = afe_get_port_index(port_id);
154
155 if ((port_index < 0) || (port_index >= AFE_MAX_PORTS)) {
156 pr_err("%s: Invalid port index %d\n", __func__, port_index);
157 topology = -EINVAL;
158 goto done;
159 }
160
161 topology = this_afe.topology[port_index];
162done:
163 return topology;
164}
165
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530166/**
167 * afe_set_aanc_info -
168 * Update AFE AANC info
169 *
170 * @q6_aanc_info: AFE AANC info params
171 *
172 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530173void afe_set_aanc_info(struct aanc_data *q6_aanc_info)
174{
175 this_afe.aanc_info.aanc_active = q6_aanc_info->aanc_active;
176 this_afe.aanc_info.aanc_rx_port = q6_aanc_info->aanc_rx_port;
177 this_afe.aanc_info.aanc_tx_port = q6_aanc_info->aanc_tx_port;
178
179 pr_debug("%s: aanc active is %d rx port is 0x%x, tx port is 0x%x\n",
180 __func__,
181 this_afe.aanc_info.aanc_active,
182 this_afe.aanc_info.aanc_rx_port,
183 this_afe.aanc_info.aanc_tx_port);
184}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530185EXPORT_SYMBOL(afe_set_aanc_info);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530186
187static void afe_callback_debug_print(struct apr_client_data *data)
188{
189 uint32_t *payload;
190
191 payload = data->payload;
192
193 if (data->payload_size >= 8)
194 pr_debug("%s: code = 0x%x PL#0[0x%x], PL#1[0x%x], size = %d\n",
195 __func__, data->opcode, payload[0], payload[1],
196 data->payload_size);
197 else if (data->payload_size >= 4)
198 pr_debug("%s: code = 0x%x PL#0[0x%x], size = %d\n",
199 __func__, data->opcode, payload[0],
200 data->payload_size);
201 else
202 pr_debug("%s: code = 0x%x, size = %d\n",
203 __func__, data->opcode, data->payload_size);
204}
205
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800206static void av_dev_drift_afe_cb_handler(uint32_t opcode, uint32_t *payload,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530207 uint32_t payload_size)
208{
209 u32 param_id;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800210 size_t expected_size =
211 sizeof(u32) + sizeof(struct afe_param_id_dev_timing_stats);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530212
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800213 /* Get param ID depending on command type */
214 param_id = (opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) ? payload[3] :
215 payload[2];
216 if (param_id != AFE_PARAM_ID_DEV_TIMING_STATS) {
217 pr_err("%s: Unrecognized param ID %d\n", __func__, param_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530218 return;
219 }
220
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800221 switch (opcode) {
222 case AFE_PORT_CMDRSP_GET_PARAM_V2:
223 expected_size += sizeof(struct param_hdr_v1);
224 if (payload_size < expected_size) {
225 pr_err("%s: Error: received size %d, expected size %zu\n",
226 __func__, payload_size, expected_size);
227 return;
228 }
229 /* Repack response to add IID */
230 this_afe.av_dev_drift_resp.status = payload[0];
231 this_afe.av_dev_drift_resp.pdata.module_id = payload[1];
232 this_afe.av_dev_drift_resp.pdata.instance_id = INSTANCE_ID_0;
233 this_afe.av_dev_drift_resp.pdata.param_id = payload[2];
234 this_afe.av_dev_drift_resp.pdata.param_size = payload[3];
235 memcpy(&this_afe.av_dev_drift_resp.timing_stats, &payload[4],
236 sizeof(struct afe_param_id_dev_timing_stats));
237 break;
238 case AFE_PORT_CMDRSP_GET_PARAM_V3:
239 expected_size += sizeof(struct param_hdr_v3);
240 if (payload_size < expected_size) {
241 pr_err("%s: Error: received size %d, expected size %zu\n",
242 __func__, payload_size, expected_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530243 return;
244 }
245 memcpy(&this_afe.av_dev_drift_resp, payload,
246 sizeof(this_afe.av_dev_drift_resp));
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800247 break;
248 default:
249 pr_err("%s: Unrecognized command %d\n", __func__, opcode);
250 return;
251 }
252
253 if (!this_afe.av_dev_drift_resp.status) {
254 atomic_set(&this_afe.state, 0);
255 } else {
256 pr_debug("%s: av_dev_drift_resp status: %d", __func__,
257 this_afe.av_dev_drift_resp.status);
258 atomic_set(&this_afe.state, -1);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530259 }
260}
261
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800262static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
263 uint32_t payload_size)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530264{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800265 struct param_hdr_v3 param_hdr;
266 u32 *data_dest = NULL;
267 u32 *data_start = NULL;
268 size_t expected_size = sizeof(u32);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530269
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800270 memset(&param_hdr, 0, sizeof(param_hdr));
271
272 /* Set command specific details */
273 switch (opcode) {
274 case AFE_PORT_CMDRSP_GET_PARAM_V2:
275 expected_size += sizeof(struct param_hdr_v1);
276 param_hdr.module_id = payload[1];
277 param_hdr.instance_id = INSTANCE_ID_0;
278 param_hdr.param_id = payload[2];
279 param_hdr.param_size = payload[3];
280 data_start = &payload[4];
281 break;
282 case AFE_PORT_CMDRSP_GET_PARAM_V3:
283 expected_size += sizeof(struct param_hdr_v3);
284 memcpy(&param_hdr, &payload[1], sizeof(struct param_hdr_v3));
285 data_start = &payload[5];
286 break;
287 default:
288 pr_err("%s: Unrecognized command %d\n", __func__, opcode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530289 return -EINVAL;
290 }
291
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800292 switch (param_hdr.param_id) {
293 case AFE_PARAM_ID_CALIB_RES_CFG_V2:
294 expected_size += sizeof(struct asm_calib_res_cfg);
295 data_dest = (u32 *) &this_afe.calib_data;
296 break;
297 case AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS:
298 expected_size += sizeof(struct afe_sp_th_vi_ftm_params);
299 data_dest = (u32 *) &this_afe.th_vi_resp;
300 break;
301 case AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS:
302 expected_size += sizeof(struct afe_sp_ex_vi_ftm_params);
303 data_dest = (u32 *) &this_afe.ex_vi_resp;
304 break;
305 default:
306 pr_err("%s: Unrecognized param ID %d\n", __func__,
307 param_hdr.param_id);
308 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530309 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800310
311 if (payload_size < expected_size) {
312 pr_err("%s: Error: received size %d, expected size %zu for param %d\n",
313 __func__, payload_size, expected_size,
314 param_hdr.param_id);
315 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530316 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800317
318 data_dest[0] = payload[0];
319 memcpy(&data_dest[1], &param_hdr, sizeof(struct param_hdr_v3));
320 memcpy(&data_dest[5], data_start, param_hdr.param_size);
321
322 if (!data_dest[0]) {
323 atomic_set(&this_afe.state, 0);
324 } else {
325 pr_debug("%s: status: %d", __func__, data_dest[0]);
326 atomic_set(&this_afe.state, -1);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530327 }
328
329 return 0;
330}
331
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800332static void afe_notify_dc_presence(void)
333{
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -0700334 int ret = 0;
335 char event[] = "DC_PRESENCE=TRUE";
336
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800337 msm_aud_evt_notifier_call_chain(MSM_AUD_DC_EVENT, NULL);
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -0700338
339 ret = q6core_send_uevent(this_afe.uevent_data, event);
340 if (ret)
341 pr_err("%s: Send UEvent %s failed :%d\n", __func__, event, ret);
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800342}
343
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530344static int32_t afe_callback(struct apr_client_data *data, void *priv)
345{
346 if (!data) {
347 pr_err("%s: Invalid param data\n", __func__);
348 return -EINVAL;
349 }
350 if (data->opcode == RESET_EVENTS) {
351 pr_debug("%s: reset event = %d %d apr[%pK]\n",
352 __func__,
353 data->reset_event, data->reset_proc, this_afe.apr);
354
355 cal_utils_clear_cal_block_q6maps(MAX_AFE_CAL_TYPES,
356 this_afe.cal_data);
357
358 /* Reset the custom topology mode: to resend again to AFE. */
359 mutex_lock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
360 this_afe.set_custom_topology = 1;
361 mutex_unlock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
362 rtac_clear_mapping(AFE_RTAC_CAL);
363
364 if (this_afe.apr) {
365 apr_reset(this_afe.apr);
366 atomic_set(&this_afe.state, 0);
367 this_afe.apr = NULL;
368 rtac_set_afe_handle(this_afe.apr);
369 }
370 /* send info to user */
371 if (this_afe.task == NULL)
372 this_afe.task = current;
373 pr_debug("%s: task_name = %s pid = %d\n",
374 __func__,
375 this_afe.task->comm, this_afe.task->pid);
376
377 /*
378 * Pass reset events to proxy driver, if cb is registered
379 */
380 if (this_afe.tx_cb) {
381 this_afe.tx_cb(data->opcode, data->token,
382 data->payload,
383 this_afe.tx_private_data);
384 this_afe.tx_cb = NULL;
385 }
386 if (this_afe.rx_cb) {
387 this_afe.rx_cb(data->opcode, data->token,
388 data->payload,
389 this_afe.rx_private_data);
390 this_afe.rx_cb = NULL;
391 }
392
393 return 0;
394 }
395 afe_callback_debug_print(data);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800396 if (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V2 ||
397 data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530398 uint32_t *payload = data->payload;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800399 uint32_t param_id;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530400
401 if (!payload || (data->token >= AFE_MAX_PORTS)) {
402 pr_err("%s: Error: size %d payload %pK token %d\n",
403 __func__, data->payload_size,
404 payload, data->token);
405 return -EINVAL;
406 }
407
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800408 param_id = (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) ?
409 payload[3] :
410 payload[2];
411 if (param_id == AFE_PARAM_ID_DEV_TIMING_STATS) {
412 av_dev_drift_afe_cb_handler(data->opcode, data->payload,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530413 data->payload_size);
414 } else {
415 if (rtac_make_afe_callback(data->payload,
416 data->payload_size))
417 return 0;
418
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800419 if (sp_make_afe_callback(data->opcode, data->payload,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530420 data->payload_size))
421 return -EINVAL;
422 }
423 wake_up(&this_afe.wait[data->token]);
424 } else if (data->payload_size) {
425 uint32_t *payload;
426 uint16_t port_id = 0;
427
428 payload = data->payload;
429 if (data->opcode == APR_BASIC_RSP_RESULT) {
430 pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x token=%d\n",
431 __func__, data->opcode,
432 payload[0], payload[1], data->token);
433 /* payload[1] contains the error status for response */
434 if (payload[1] != 0) {
435 atomic_set(&this_afe.status, payload[1]);
436 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
437 __func__, payload[0], payload[1]);
438 }
439 switch (payload[0]) {
440 case AFE_PORT_CMD_SET_PARAM_V2:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800441 case AFE_PORT_CMD_SET_PARAM_V3:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530442 if (rtac_make_afe_callback(payload,
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800443 data->payload_size))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530444 return 0;
445 case AFE_PORT_CMD_DEVICE_STOP:
446 case AFE_PORT_CMD_DEVICE_START:
447 case AFE_PSEUDOPORT_CMD_START:
448 case AFE_PSEUDOPORT_CMD_STOP:
449 case AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS:
450 case AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS:
451 case AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER:
452 case AFE_PORTS_CMD_DTMF_CTL:
453 case AFE_SVC_CMD_SET_PARAM:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800454 case AFE_SVC_CMD_SET_PARAM_V2:
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800455 case AFE_PORT_CMD_MOD_EVENT_CFG:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530456 atomic_set(&this_afe.state, 0);
457 wake_up(&this_afe.wait[data->token]);
458 break;
459 case AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER:
460 break;
461 case AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2:
462 port_id = RT_PROXY_PORT_001_TX;
463 break;
464 case AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2:
465 port_id = RT_PROXY_PORT_001_RX;
466 break;
467 case AFE_CMD_ADD_TOPOLOGIES:
468 atomic_set(&this_afe.state, 0);
469 wake_up(&this_afe.wait[data->token]);
470 pr_debug("%s: AFE_CMD_ADD_TOPOLOGIES cmd 0x%x\n",
471 __func__, payload[1]);
472 break;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800473 case AFE_PORT_CMD_GET_PARAM_V2:
474 case AFE_PORT_CMD_GET_PARAM_V3:
475 /*
476 * Should only come here if there is an APR
477 * error or malformed APR packet. Otherwise
478 * response will be returned as
479 * AFE_PORT_CMDRSP_GET_PARAM_V2/3
480 */
481 pr_debug("%s: AFE Get Param opcode 0x%x token 0x%x src %d dest %d\n",
482 __func__, data->opcode, data->token,
483 data->src_port, data->dest_port);
484 if (payload[1] != 0) {
485 pr_err("%s: AFE Get Param failed with error %d\n",
486 __func__, payload[1]);
487 if (rtac_make_afe_callback(
488 payload,
489 data->payload_size))
490 return 0;
491 }
492 atomic_set(&this_afe.state, payload[1]);
493 wake_up(&this_afe.wait[data->token]);
494 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530495 default:
496 pr_err("%s: Unknown cmd 0x%x\n", __func__,
497 payload[0]);
498 break;
499 }
500 } else if (data->opcode ==
501 AFE_SERVICE_CMDRSP_SHARED_MEM_MAP_REGIONS) {
502 pr_debug("%s: mmap_handle: 0x%x, cal index %d\n",
503 __func__, payload[0],
504 atomic_read(&this_afe.mem_map_cal_index));
505 if (atomic_read(&this_afe.mem_map_cal_index) != -1)
506 atomic_set(&this_afe.mem_map_cal_handles[
507 atomic_read(
508 &this_afe.mem_map_cal_index)],
509 (uint32_t)payload[0]);
510 else
511 this_afe.mmap_handle = payload[0];
512 atomic_set(&this_afe.state, 0);
513 wake_up(&this_afe.wait[data->token]);
514 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
515 port_id = (uint16_t)(0x0000FFFF & payload[0]);
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800516 } else if (data->opcode == AFE_PORT_MOD_EVENT) {
517 u32 flag_dc_presence[2];
518 uint32_t *payload = data->payload;
519 struct afe_port_mod_evt_rsp_hdr *evt_pl =
520 (struct afe_port_mod_evt_rsp_hdr *)payload;
521
522 if (!payload || (data->token >= AFE_MAX_PORTS)) {
523 pr_err("%s: Error: size %d payload %pK token %d\n",
524 __func__, data->payload_size,
525 payload, data->token);
526 return -EINVAL;
527 }
528 if ((evt_pl->module_id == AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI) &&
529 (evt_pl->event_id == AFE_PORT_SP_DC_DETECTION_EVENT) &&
530 (evt_pl->payload_size == sizeof(flag_dc_presence))) {
531
532 memcpy(&flag_dc_presence,
533 payload +
534 sizeof(struct afe_port_mod_evt_rsp_hdr),
535 evt_pl->payload_size);
536 if (flag_dc_presence[0] == 1 ||
537 flag_dc_presence[1] == 1) {
538 afe_notify_dc_presence();
539 }
540 } else {
541 pr_debug("%s: mod ID = 0x%x event_id = 0x%x\n",
542 __func__, evt_pl->module_id,
543 evt_pl->event_id);
544 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530545 }
546 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
547 switch (port_id) {
548 case RT_PROXY_PORT_001_TX: {
549 if (this_afe.tx_cb) {
550 this_afe.tx_cb(data->opcode, data->token,
551 data->payload,
552 this_afe.tx_private_data);
553 }
554 break;
555 }
556 case RT_PROXY_PORT_001_RX: {
557 if (this_afe.rx_cb) {
558 this_afe.rx_cb(data->opcode, data->token,
559 data->payload,
560 this_afe.rx_private_data);
561 }
562 break;
563 }
564 default:
565 pr_debug("%s: default case 0x%x\n", __func__, port_id);
566 break;
567 }
568 }
569 return 0;
570}
571
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530572/**
573 * afe_get_port_type -
574 * Retrieve AFE port type whether RX or TX
575 *
576 * @port_id: AFE Port ID number
577 *
578 * Returns RX/TX type on success or -EINVAL on failure.
579 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530580int afe_get_port_type(u16 port_id)
581{
582 int ret;
583
584 switch (port_id) {
585 case PRIMARY_I2S_RX:
586 case SECONDARY_I2S_RX:
587 case MI2S_RX:
588 case HDMI_RX:
589 case DISPLAY_PORT_RX:
590 case AFE_PORT_ID_SPDIF_RX:
591 case SLIMBUS_0_RX:
592 case SLIMBUS_1_RX:
593 case SLIMBUS_2_RX:
594 case SLIMBUS_3_RX:
595 case SLIMBUS_4_RX:
596 case SLIMBUS_5_RX:
597 case SLIMBUS_6_RX:
598 case SLIMBUS_7_RX:
599 case SLIMBUS_8_RX:
600 case INT_BT_SCO_RX:
601 case INT_BT_A2DP_RX:
602 case INT_FM_RX:
603 case VOICE_PLAYBACK_TX:
604 case VOICE2_PLAYBACK_TX:
605 case RT_PROXY_PORT_001_RX:
606 case AUDIO_PORT_ID_I2S_RX:
607 case AFE_PORT_ID_PRIMARY_MI2S_RX:
608 case AFE_PORT_ID_SECONDARY_MI2S_RX:
609 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
610 case AFE_PORT_ID_TERTIARY_MI2S_RX:
611 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
612 case AFE_PORT_ID_QUINARY_MI2S_RX:
613 case AFE_PORT_ID_PRIMARY_PCM_RX:
614 case AFE_PORT_ID_SECONDARY_PCM_RX:
615 case AFE_PORT_ID_TERTIARY_PCM_RX:
616 case AFE_PORT_ID_QUATERNARY_PCM_RX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530617 case AFE_PORT_ID_QUINARY_PCM_RX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530618 case AFE_PORT_ID_PRIMARY_TDM_RX:
619 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
620 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
621 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
622 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
623 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
624 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
625 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
626 case AFE_PORT_ID_SECONDARY_TDM_RX:
627 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
628 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
629 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
630 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
631 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
632 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
633 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
634 case AFE_PORT_ID_TERTIARY_TDM_RX:
635 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
636 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
637 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
638 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
639 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
640 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
641 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
642 case AFE_PORT_ID_QUATERNARY_TDM_RX:
643 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
644 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
645 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
646 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
647 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
648 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
649 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530650 case AFE_PORT_ID_QUINARY_TDM_RX:
651 case AFE_PORT_ID_QUINARY_TDM_RX_1:
652 case AFE_PORT_ID_QUINARY_TDM_RX_2:
653 case AFE_PORT_ID_QUINARY_TDM_RX_3:
654 case AFE_PORT_ID_QUINARY_TDM_RX_4:
655 case AFE_PORT_ID_QUINARY_TDM_RX_5:
656 case AFE_PORT_ID_QUINARY_TDM_RX_6:
657 case AFE_PORT_ID_QUINARY_TDM_RX_7:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530658 case AFE_PORT_ID_USB_RX:
659 case AFE_PORT_ID_INT0_MI2S_RX:
660 case AFE_PORT_ID_INT1_MI2S_RX:
661 case AFE_PORT_ID_INT2_MI2S_RX:
662 case AFE_PORT_ID_INT3_MI2S_RX:
663 case AFE_PORT_ID_INT4_MI2S_RX:
664 case AFE_PORT_ID_INT5_MI2S_RX:
665 case AFE_PORT_ID_INT6_MI2S_RX:
666 ret = MSM_AFE_PORT_TYPE_RX;
667 break;
668
669 case PRIMARY_I2S_TX:
670 case SECONDARY_I2S_TX:
671 case MI2S_TX:
672 case DIGI_MIC_TX:
673 case VOICE_RECORD_TX:
674 case SLIMBUS_0_TX:
675 case SLIMBUS_1_TX:
676 case SLIMBUS_2_TX:
677 case SLIMBUS_3_TX:
678 case SLIMBUS_4_TX:
679 case SLIMBUS_5_TX:
680 case SLIMBUS_6_TX:
681 case SLIMBUS_7_TX:
682 case SLIMBUS_8_TX:
683 case INT_FM_TX:
684 case VOICE_RECORD_RX:
685 case INT_BT_SCO_TX:
686 case RT_PROXY_PORT_001_TX:
687 case AFE_PORT_ID_PRIMARY_MI2S_TX:
688 case AFE_PORT_ID_SECONDARY_MI2S_TX:
689 case AFE_PORT_ID_TERTIARY_MI2S_TX:
690 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
691 case AFE_PORT_ID_QUINARY_MI2S_TX:
692 case AFE_PORT_ID_SENARY_MI2S_TX:
693 case AFE_PORT_ID_PRIMARY_PCM_TX:
694 case AFE_PORT_ID_SECONDARY_PCM_TX:
695 case AFE_PORT_ID_TERTIARY_PCM_TX:
696 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530697 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530698 case AFE_PORT_ID_PRIMARY_TDM_TX:
699 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
700 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
701 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
702 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
703 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
704 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
705 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
706 case AFE_PORT_ID_SECONDARY_TDM_TX:
707 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
708 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
709 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
710 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
711 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
712 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
713 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
714 case AFE_PORT_ID_TERTIARY_TDM_TX:
715 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
716 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
717 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
718 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
719 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
720 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
721 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
722 case AFE_PORT_ID_QUATERNARY_TDM_TX:
723 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
724 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
725 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
726 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
727 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
728 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
729 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530730 case AFE_PORT_ID_QUINARY_TDM_TX:
731 case AFE_PORT_ID_QUINARY_TDM_TX_1:
732 case AFE_PORT_ID_QUINARY_TDM_TX_2:
733 case AFE_PORT_ID_QUINARY_TDM_TX_3:
734 case AFE_PORT_ID_QUINARY_TDM_TX_4:
735 case AFE_PORT_ID_QUINARY_TDM_TX_5:
736 case AFE_PORT_ID_QUINARY_TDM_TX_6:
737 case AFE_PORT_ID_QUINARY_TDM_TX_7:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530738 case AFE_PORT_ID_USB_TX:
739 case AFE_PORT_ID_INT0_MI2S_TX:
740 case AFE_PORT_ID_INT1_MI2S_TX:
741 case AFE_PORT_ID_INT2_MI2S_TX:
742 case AFE_PORT_ID_INT3_MI2S_TX:
743 case AFE_PORT_ID_INT4_MI2S_TX:
744 case AFE_PORT_ID_INT5_MI2S_TX:
745 case AFE_PORT_ID_INT6_MI2S_TX:
746 ret = MSM_AFE_PORT_TYPE_TX;
747 break;
748
749 default:
750 WARN_ON(1);
751 pr_err("%s: Invalid port id = 0x%x\n",
752 __func__, port_id);
753 ret = -EINVAL;
754 }
755
756 return ret;
757}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530758EXPORT_SYMBOL(afe_get_port_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530759
760int afe_sizeof_cfg_cmd(u16 port_id)
761{
762 int ret_size;
763
764 switch (port_id) {
765 case PRIMARY_I2S_RX:
766 case PRIMARY_I2S_TX:
767 case SECONDARY_I2S_RX:
768 case SECONDARY_I2S_TX:
769 case MI2S_RX:
770 case MI2S_TX:
771 case AFE_PORT_ID_PRIMARY_MI2S_RX:
772 case AFE_PORT_ID_PRIMARY_MI2S_TX:
773 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
774 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
775 case AFE_PORT_ID_QUINARY_MI2S_RX:
776 case AFE_PORT_ID_QUINARY_MI2S_TX:
777 ret_size = SIZEOF_CFG_CMD(afe_param_id_i2s_cfg);
778 break;
779 case HDMI_RX:
780 case DISPLAY_PORT_RX:
781 ret_size =
782 SIZEOF_CFG_CMD(afe_param_id_hdmi_multi_chan_audio_cfg);
783 break;
784 case SLIMBUS_0_RX:
785 case SLIMBUS_0_TX:
786 case SLIMBUS_1_RX:
787 case SLIMBUS_1_TX:
788 case SLIMBUS_2_RX:
789 case SLIMBUS_2_TX:
790 case SLIMBUS_3_RX:
791 case SLIMBUS_3_TX:
792 case SLIMBUS_4_RX:
793 case SLIMBUS_4_TX:
794 case SLIMBUS_5_RX:
795 case SLIMBUS_5_TX:
796 case SLIMBUS_6_RX:
797 case SLIMBUS_6_TX:
798 case SLIMBUS_7_RX:
799 case SLIMBUS_7_TX:
800 case SLIMBUS_8_RX:
801 case SLIMBUS_8_TX:
802 ret_size = SIZEOF_CFG_CMD(afe_param_id_slimbus_cfg);
803 break;
804 case VOICE_PLAYBACK_TX:
805 case VOICE2_PLAYBACK_TX:
806 case VOICE_RECORD_RX:
807 case VOICE_RECORD_TX:
808 ret_size = SIZEOF_CFG_CMD(afe_param_id_pseudo_port_cfg);
809 break;
810 case RT_PROXY_PORT_001_RX:
811 case RT_PROXY_PORT_001_TX:
812 ret_size = SIZEOF_CFG_CMD(afe_param_id_rt_proxy_port_cfg);
813 break;
814 case AFE_PORT_ID_USB_RX:
815 case AFE_PORT_ID_USB_TX:
816 ret_size = SIZEOF_CFG_CMD(afe_param_id_usb_audio_cfg);
817 break;
818 case AFE_PORT_ID_PRIMARY_PCM_RX:
819 case AFE_PORT_ID_PRIMARY_PCM_TX:
820 case AFE_PORT_ID_SECONDARY_PCM_RX:
821 case AFE_PORT_ID_SECONDARY_PCM_TX:
822 case AFE_PORT_ID_TERTIARY_PCM_RX:
823 case AFE_PORT_ID_TERTIARY_PCM_TX:
824 case AFE_PORT_ID_QUATERNARY_PCM_RX:
825 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530826 case AFE_PORT_ID_QUINARY_PCM_RX:
827 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530828 default:
829 pr_debug("%s: default case 0x%x\n", __func__, port_id);
830 ret_size = SIZEOF_CFG_CMD(afe_param_id_pcm_cfg);
831 break;
832 }
833 return ret_size;
834}
835
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530836/**
837 * afe_q6_interface_prepare -
838 * wrapper API to check Q6 AFE registered to APR otherwise registers
839 *
840 * Returns 0 on success or error on failure.
841 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530842int afe_q6_interface_prepare(void)
843{
844 int ret = 0;
845
846 pr_debug("%s:\n", __func__);
847
848 if (this_afe.apr == NULL) {
849 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
850 0xFFFFFFFF, &this_afe);
851 if (this_afe.apr == NULL) {
852 pr_err("%s: Unable to register AFE\n", __func__);
853 ret = -ENODEV;
854 }
855 rtac_set_afe_handle(this_afe.apr);
856 }
857 return ret;
858}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530859EXPORT_SYMBOL(afe_q6_interface_prepare);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530860
861/*
862 * afe_apr_send_pkt : returns 0 on success, negative otherwise.
863 */
864static int afe_apr_send_pkt(void *data, wait_queue_head_t *wait)
865{
866 int ret;
867
868 if (wait)
869 atomic_set(&this_afe.state, 1);
870 atomic_set(&this_afe.status, 0);
871 ret = apr_send_pkt(this_afe.apr, data);
872 if (ret > 0) {
873 if (wait) {
874 ret = wait_event_timeout(*wait,
875 (atomic_read(&this_afe.state) == 0),
876 msecs_to_jiffies(TIMEOUT_MS));
877 if (!ret) {
878 ret = -ETIMEDOUT;
879 } else if (atomic_read(&this_afe.status) > 0) {
880 pr_err("%s: DSP returned error[%s]\n", __func__,
881 adsp_err_get_err_str(atomic_read(
882 &this_afe.status)));
883 ret = adsp_err_get_lnx_err_code(
884 atomic_read(&this_afe.status));
885 } else {
886 ret = 0;
887 }
888 } else {
889 ret = 0;
890 }
891 } else if (ret == 0) {
892 pr_err("%s: packet not transmitted\n", __func__);
893 /* apr_send_pkt can return 0 when nothing is transmitted */
894 ret = -EINVAL;
895 }
896
897 pr_debug("%s: leave %d\n", __func__, ret);
898 return ret;
899}
900
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800901/* This function shouldn't be called directly. Instead call q6afe_set_params. */
902static int q6afe_set_params_v2(u16 port_id, int index,
903 struct mem_mapping_hdr *mem_hdr,
904 u8 *packed_param_data, u32 packed_data_size)
905{
906 struct afe_port_cmd_set_param_v2 *set_param = NULL;
907 uint32_t size = sizeof(struct afe_port_cmd_set_param_v2);
908 int rc = 0;
909
910 if (packed_param_data != NULL)
911 size += packed_data_size;
912 set_param = kzalloc(size, GFP_KERNEL);
913 if (set_param == NULL)
914 return -ENOMEM;
915
916 set_param->apr_hdr.hdr_field =
917 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
918 APR_PKT_VER);
919 set_param->apr_hdr.pkt_size = size;
920 set_param->apr_hdr.src_port = 0;
921 set_param->apr_hdr.dest_port = 0;
922 set_param->apr_hdr.token = index;
923 set_param->apr_hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
924 set_param->port_id = port_id;
925 if (packed_data_size > U16_MAX) {
926 pr_err("%s: Invalid data size for set params V2 %d\n", __func__,
927 packed_data_size);
928 rc = -EINVAL;
929 goto done;
930 }
931 set_param->payload_size = packed_data_size;
932 if (mem_hdr != NULL) {
933 set_param->mem_hdr = *mem_hdr;
934 } else if (packed_param_data != NULL) {
935 memcpy(&set_param->param_data, packed_param_data,
936 packed_data_size);
937 } else {
938 pr_err("%s: Both memory header and param data are NULL\n",
939 __func__);
940 rc = -EINVAL;
941 goto done;
942 }
943
944 rc = afe_apr_send_pkt(set_param, &this_afe.wait[index]);
945done:
946 kfree(set_param);
947 return rc;
948}
949
950/* This function shouldn't be called directly. Instead call q6afe_set_params. */
951static int q6afe_set_params_v3(u16 port_id, int index,
952 struct mem_mapping_hdr *mem_hdr,
953 u8 *packed_param_data, u32 packed_data_size)
954{
955 struct afe_port_cmd_set_param_v3 *set_param = NULL;
956 uint32_t size = sizeof(struct afe_port_cmd_set_param_v3);
957 int rc = 0;
958
959 if (packed_param_data != NULL)
960 size += packed_data_size;
961 set_param = kzalloc(size, GFP_KERNEL);
962 if (set_param == NULL)
963 return -ENOMEM;
964
965 set_param->apr_hdr.hdr_field =
966 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
967 APR_PKT_VER);
968 set_param->apr_hdr.pkt_size = size;
969 set_param->apr_hdr.src_port = 0;
970 set_param->apr_hdr.dest_port = 0;
971 set_param->apr_hdr.token = index;
972 set_param->apr_hdr.opcode = AFE_PORT_CMD_SET_PARAM_V3;
973 set_param->port_id = port_id;
974 set_param->payload_size = packed_data_size;
975 if (mem_hdr != NULL) {
976 set_param->mem_hdr = *mem_hdr;
977 } else if (packed_param_data != NULL) {
978 memcpy(&set_param->param_data, packed_param_data,
979 packed_data_size);
980 } else {
981 pr_err("%s: Both memory header and param data are NULL\n",
982 __func__);
983 rc = -EINVAL;
984 goto done;
985 }
986
987 rc = afe_apr_send_pkt(set_param, &this_afe.wait[index]);
988done:
989 kfree(set_param);
990 return rc;
991}
992
993static int q6afe_set_params(u16 port_id, int index,
994 struct mem_mapping_hdr *mem_hdr,
995 u8 *packed_param_data, u32 packed_data_size)
996{
997 int ret = 0;
998
999 ret = afe_q6_interface_prepare();
1000 if (ret != 0) {
1001 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
1002 return ret;
1003 }
1004
1005 port_id = q6audio_get_port_id(port_id);
1006 ret = q6audio_validate_port(port_id);
1007 if (ret < 0) {
1008 pr_err("%s: Not a valid port id = 0x%x ret %d\n", __func__,
1009 port_id, ret);
1010 return -EINVAL;
1011 }
1012
1013 if (index < 0 || index >= AFE_MAX_PORTS) {
1014 pr_err("%s: AFE port index[%d] invalid\n", __func__, index);
1015 return -EINVAL;
1016 }
1017
1018 if (q6common_is_instance_id_supported())
1019 return q6afe_set_params_v3(port_id, index, mem_hdr,
1020 packed_param_data, packed_data_size);
1021 else
1022 return q6afe_set_params_v2(port_id, index, mem_hdr,
1023 packed_param_data, packed_data_size);
1024}
1025
1026static int q6afe_pack_and_set_param_in_band(u16 port_id, int index,
1027 struct param_hdr_v3 param_hdr,
1028 u8 *param_data)
1029{
1030 u8 *packed_param_data = NULL;
1031 int packed_data_size = sizeof(union param_hdrs) + param_hdr.param_size;
1032 int ret;
1033
1034 packed_param_data = kzalloc(packed_data_size, GFP_KERNEL);
1035 if (packed_param_data == NULL)
1036 return -ENOMEM;
1037
1038 ret = q6common_pack_pp_params(packed_param_data, &param_hdr, param_data,
1039 &packed_data_size);
1040 if (ret) {
1041 pr_err("%s: Failed to pack param header and data, error %d\n",
1042 __func__, ret);
1043 goto fail_cmd;
1044 }
1045
1046 ret = q6afe_set_params(port_id, index, NULL, packed_param_data,
1047 packed_data_size);
1048
1049fail_cmd:
1050 kfree(packed_param_data);
1051 return ret;
1052}
1053
1054/* This function shouldn't be called directly. Instead call q6afe_get_param. */
1055static int q6afe_get_params_v2(u16 port_id, int index,
1056 struct mem_mapping_hdr *mem_hdr,
1057 struct param_hdr_v3 *param_hdr)
1058{
1059 struct afe_port_cmd_get_param_v2 afe_get_param;
1060 u32 param_size = param_hdr->param_size;
1061
1062 memset(&afe_get_param, 0, sizeof(afe_get_param));
1063 afe_get_param.apr_hdr.hdr_field =
1064 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1065 APR_PKT_VER);
1066 afe_get_param.apr_hdr.pkt_size = sizeof(afe_get_param) + param_size;
1067 afe_get_param.apr_hdr.src_port = 0;
1068 afe_get_param.apr_hdr.dest_port = 0;
1069 afe_get_param.apr_hdr.token = index;
1070 afe_get_param.apr_hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
1071 afe_get_param.port_id = port_id;
1072 afe_get_param.payload_size = sizeof(struct param_hdr_v1) + param_size;
1073 if (mem_hdr != NULL)
1074 afe_get_param.mem_hdr = *mem_hdr;
1075 /* Set MID and PID in command */
1076 afe_get_param.module_id = param_hdr->module_id;
1077 afe_get_param.param_id = param_hdr->param_id;
1078 /* Set param header in payload */
1079 afe_get_param.param_hdr.module_id = param_hdr->module_id;
1080 afe_get_param.param_hdr.param_id = param_hdr->param_id;
1081 afe_get_param.param_hdr.param_size = param_size;
1082
1083 return afe_apr_send_pkt(&afe_get_param, &this_afe.wait[index]);
1084}
1085
1086/* This function shouldn't be called directly. Instead call q6afe_get_param. */
1087static int q6afe_get_params_v3(u16 port_id, int index,
1088 struct mem_mapping_hdr *mem_hdr,
1089 struct param_hdr_v3 *param_hdr)
1090{
1091 struct afe_port_cmd_get_param_v3 afe_get_param;
1092
1093 memset(&afe_get_param, 0, sizeof(afe_get_param));
1094 afe_get_param.apr_hdr.hdr_field =
1095 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1096 APR_PKT_VER);
1097 afe_get_param.apr_hdr.pkt_size = sizeof(afe_get_param);
1098 afe_get_param.apr_hdr.src_port = 0;
1099 afe_get_param.apr_hdr.dest_port = 0;
1100 afe_get_param.apr_hdr.token = index;
1101 afe_get_param.apr_hdr.opcode = AFE_PORT_CMD_GET_PARAM_V3;
1102 afe_get_param.port_id = port_id;
1103 if (mem_hdr != NULL)
1104 afe_get_param.mem_hdr = *mem_hdr;
1105 /* Set param header in command, no payload in V3 */
1106 afe_get_param.param_hdr = *param_hdr;
1107
1108 return afe_apr_send_pkt(&afe_get_param, &this_afe.wait[index]);
1109}
1110
1111/*
1112 * Calling functions copy param data directly from this_afe. Do not copy data
1113 * back to caller here.
1114 */
1115static int q6afe_get_params(u16 port_id, struct mem_mapping_hdr *mem_hdr,
1116 struct param_hdr_v3 *param_hdr)
1117{
1118 int index;
1119 int ret;
1120
1121 ret = afe_q6_interface_prepare();
1122 if (ret != 0) {
1123 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
1124 return ret;
1125 }
1126
1127 port_id = q6audio_get_port_id(port_id);
1128 ret = q6audio_validate_port(port_id);
1129 if (ret < 0) {
1130 pr_err("%s: Not a valid port id = 0x%x ret %d\n", __func__,
1131 port_id, ret);
1132 return -EINVAL;
1133 }
1134
1135 index = q6audio_get_port_index(port_id);
1136 if (index < 0 || index >= AFE_MAX_PORTS) {
1137 pr_err("%s: AFE port index[%d] invalid\n", __func__, index);
1138 return -EINVAL;
1139 }
1140
1141 if (q6common_is_instance_id_supported())
1142 return q6afe_get_params_v3(port_id, index, NULL, param_hdr);
1143 else
1144 return q6afe_get_params_v2(port_id, index, NULL, param_hdr);
1145}
1146
1147/*
1148 * This function shouldn't be called directly. Instead call
1149 * q6afe_svc_set_params.
1150 */
1151static int q6afe_svc_set_params_v1(int index, struct mem_mapping_hdr *mem_hdr,
1152 u8 *packed_param_data, u32 packed_data_size)
1153{
1154 struct afe_svc_cmd_set_param_v1 *svc_set_param = NULL;
1155 uint32_t size = sizeof(struct afe_svc_cmd_set_param_v1);
1156 int rc = 0;
1157
1158 if (packed_param_data != NULL)
1159 size += packed_data_size;
1160 svc_set_param = kzalloc(size, GFP_KERNEL);
1161 if (svc_set_param == NULL)
1162 return -ENOMEM;
1163
1164 svc_set_param->apr_hdr.hdr_field =
1165 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1166 APR_PKT_VER);
1167 svc_set_param->apr_hdr.pkt_size = size;
1168 svc_set_param->apr_hdr.src_port = 0;
1169 svc_set_param->apr_hdr.dest_port = 0;
Vignesh Kulothungan87f926a2018-03-04 22:47:50 -08001170 svc_set_param->apr_hdr.token = index;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001171 svc_set_param->apr_hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1172 svc_set_param->payload_size = packed_data_size;
1173
1174 if (mem_hdr != NULL) {
1175 /* Out of band case. */
1176 svc_set_param->mem_hdr = *mem_hdr;
1177 } else if (packed_param_data != NULL) {
1178 /* In band case. */
1179 memcpy(&svc_set_param->param_data, packed_param_data,
1180 packed_data_size);
1181 } else {
1182 pr_err("%s: Both memory header and param data are NULL\n",
1183 __func__);
1184 rc = -EINVAL;
1185 goto done;
1186 }
1187
1188 rc = afe_apr_send_pkt(svc_set_param, &this_afe.wait[index]);
1189done:
1190 kfree(svc_set_param);
1191 return rc;
1192}
1193
1194/*
1195 * This function shouldn't be called directly. Instead call
1196 * q6afe_svc_set_params.
1197 */
1198static int q6afe_svc_set_params_v2(int index, struct mem_mapping_hdr *mem_hdr,
1199 u8 *packed_param_data, u32 packed_data_size)
1200{
1201 struct afe_svc_cmd_set_param_v2 *svc_set_param = NULL;
1202 uint16_t size = sizeof(struct afe_svc_cmd_set_param_v2);
1203 int rc = 0;
1204
1205 if (packed_param_data != NULL)
1206 size += packed_data_size;
1207 svc_set_param = kzalloc(size, GFP_KERNEL);
1208 if (svc_set_param == NULL)
1209 return -ENOMEM;
1210
1211 svc_set_param->apr_hdr.hdr_field =
1212 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1213 APR_PKT_VER);
1214 svc_set_param->apr_hdr.pkt_size = size;
1215 svc_set_param->apr_hdr.src_port = 0;
1216 svc_set_param->apr_hdr.dest_port = 0;
Vignesh Kulothungan87f926a2018-03-04 22:47:50 -08001217 svc_set_param->apr_hdr.token = index;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001218 svc_set_param->apr_hdr.opcode = AFE_SVC_CMD_SET_PARAM_V2;
1219 svc_set_param->payload_size = packed_data_size;
1220
1221 if (mem_hdr != NULL) {
1222 /* Out of band case. */
1223 svc_set_param->mem_hdr = *mem_hdr;
1224 } else if (packed_param_data != NULL) {
1225 /* In band case. */
1226 memcpy(&svc_set_param->param_data, packed_param_data,
1227 packed_data_size);
1228 } else {
1229 pr_err("%s: Both memory header and param data are NULL\n",
1230 __func__);
1231 rc = -EINVAL;
1232 goto done;
1233 }
1234
1235 rc = afe_apr_send_pkt(svc_set_param, &this_afe.wait[index]);
1236done:
1237 kfree(svc_set_param);
1238 return rc;
1239}
1240
1241static int q6afe_svc_set_params(int index, struct mem_mapping_hdr *mem_hdr,
1242 u8 *packed_param_data, u32 packed_data_size)
1243{
1244 int ret;
1245
1246 ret = afe_q6_interface_prepare();
1247 if (ret != 0) {
1248 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
1249 return ret;
1250 }
1251
1252 if (q6common_is_instance_id_supported())
1253 return q6afe_svc_set_params_v2(index, mem_hdr,
1254 packed_param_data,
1255 packed_data_size);
1256 else
1257 return q6afe_svc_set_params_v1(index, mem_hdr,
1258 packed_param_data,
1259 packed_data_size);
1260}
1261
1262static int q6afe_svc_pack_and_set_param_in_band(int index,
1263 struct param_hdr_v3 param_hdr,
1264 u8 *param_data)
1265{
1266 u8 *packed_param_data = NULL;
1267 u32 packed_data_size =
1268 sizeof(struct param_hdr_v3) + param_hdr.param_size;
1269 int ret = 0;
1270
1271 packed_param_data = kzalloc(packed_data_size, GFP_KERNEL);
1272 if (!packed_param_data)
1273 return -ENOMEM;
1274
1275 ret = q6common_pack_pp_params(packed_param_data, &param_hdr, param_data,
1276 &packed_data_size);
1277 if (ret) {
1278 pr_err("%s: Failed to pack parameter header and data, error %d\n",
1279 __func__, ret);
1280 goto done;
1281 }
1282
1283 ret = q6afe_svc_set_params(index, NULL, packed_param_data,
1284 packed_data_size);
1285
1286done:
1287 kfree(packed_param_data);
1288 return ret;
1289}
1290
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301291static int afe_send_cal_block(u16 port_id, struct cal_block_data *cal_block)
1292{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001293 struct mem_mapping_hdr mem_hdr;
1294 int payload_size = 0;
1295 int result = 0;
1296
1297 memset(&mem_hdr, 0, sizeof(mem_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301298
1299 if (!cal_block) {
1300 pr_debug("%s: No AFE cal to send!\n", __func__);
1301 result = -EINVAL;
1302 goto done;
1303 }
1304 if (cal_block->cal_data.size <= 0) {
1305 pr_debug("%s: AFE cal has invalid size!\n", __func__);
1306 result = -EINVAL;
1307 goto done;
1308 }
1309
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001310 payload_size = cal_block->cal_data.size;
1311 mem_hdr.data_payload_addr_lsw =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301312 lower_32_bits(cal_block->cal_data.paddr);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001313 mem_hdr.data_payload_addr_msw =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301314 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001315 mem_hdr.mem_map_handle = cal_block->map_data.q6map_handle;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301316
1317 pr_debug("%s: AFE cal sent for device port = 0x%x, cal size = %zd, cal addr = 0x%pK\n",
1318 __func__, port_id,
1319 cal_block->cal_data.size, &cal_block->cal_data.paddr);
1320
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001321 result = q6afe_set_params(port_id, q6audio_get_port_index(port_id),
1322 &mem_hdr, NULL, payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301323 if (result)
1324 pr_err("%s: AFE cal for port 0x%x failed %d\n",
1325 __func__, port_id, result);
1326
1327done:
1328 return result;
1329}
1330
1331
1332static int afe_send_custom_topology_block(struct cal_block_data *cal_block)
1333{
1334 int result = 0;
1335 int index = 0;
1336 struct cmd_set_topologies afe_cal;
1337
1338 if (!cal_block) {
1339 pr_err("%s: No AFE SVC cal to send!\n", __func__);
1340 return -EINVAL;
1341 }
1342 if (cal_block->cal_data.size <= 0) {
1343 pr_err("%s: AFE SVC cal has invalid size: %zd!\n",
1344 __func__, cal_block->cal_data.size);
1345 return -EINVAL;
1346 }
1347
1348 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1349 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1350 afe_cal.hdr.pkt_size = sizeof(afe_cal);
1351 afe_cal.hdr.src_port = 0;
1352 afe_cal.hdr.dest_port = 0;
1353 afe_cal.hdr.token = index;
1354 afe_cal.hdr.opcode = AFE_CMD_ADD_TOPOLOGIES;
1355
1356 afe_cal.payload_size = cal_block->cal_data.size;
1357 afe_cal.payload_addr_lsw =
1358 lower_32_bits(cal_block->cal_data.paddr);
1359 afe_cal.payload_addr_msw =
1360 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
1361 afe_cal.mem_map_handle = cal_block->map_data.q6map_handle;
1362
1363 pr_debug("%s:cmd_id:0x%x calsize:%zd memmap_hdl:0x%x caladdr:0x%pK",
1364 __func__, AFE_CMD_ADD_TOPOLOGIES, cal_block->cal_data.size,
1365 afe_cal.mem_map_handle, &cal_block->cal_data.paddr);
1366
1367 result = afe_apr_send_pkt(&afe_cal, &this_afe.wait[index]);
1368 if (result)
1369 pr_err("%s: AFE send topology for command 0x%x failed %d\n",
1370 __func__, AFE_CMD_ADD_TOPOLOGIES, result);
1371
1372 return result;
1373}
1374
1375static void afe_send_custom_topology(void)
1376{
1377 struct cal_block_data *cal_block = NULL;
1378 int cal_index = AFE_CUST_TOPOLOGY_CAL;
1379 int ret;
1380
1381 if (this_afe.cal_data[cal_index] == NULL) {
1382 pr_err("%s: cal_index %d not allocated!\n",
1383 __func__, cal_index);
1384 return;
1385 }
1386 mutex_lock(&this_afe.cal_data[cal_index]->lock);
1387
1388 if (!this_afe.set_custom_topology)
1389 goto unlock;
1390 this_afe.set_custom_topology = 0;
1391 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07001392 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301393 pr_err("%s cal_block not found!!\n", __func__);
1394 goto unlock;
1395 }
1396
1397 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
1398
1399 ret = remap_cal_data(cal_block, cal_index);
1400 if (ret) {
1401 pr_err("%s: Remap_cal_data failed for cal %d!\n",
1402 __func__, cal_index);
1403 goto unlock;
1404 }
1405 ret = afe_send_custom_topology_block(cal_block);
1406 if (ret < 0) {
1407 pr_err("%s: No cal sent for cal_index %d! ret %d\n",
1408 __func__, cal_index, ret);
1409 goto unlock;
1410 }
1411 pr_debug("%s:sent custom topology for AFE\n", __func__);
1412unlock:
1413 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
1414}
1415
1416static int afe_spk_ramp_dn_cfg(int port)
1417{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001418 struct param_hdr_v3 param_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301419 int ret = -EINVAL;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001420
1421 memset(&param_info, 0, sizeof(param_info));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301422
1423 if (afe_get_port_type(port) != MSM_AFE_PORT_TYPE_RX) {
1424 pr_debug("%s: port doesn't match 0x%x\n", __func__, port);
1425 return 0;
1426 }
1427 if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_DISABLED ||
1428 (this_afe.vi_rx_port != port)) {
1429 pr_debug("%s: spkr protection disabled port 0x%x %d 0x%x\n",
1430 __func__, port, ret, this_afe.vi_rx_port);
1431 return 0;
1432 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001433 param_info.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
1434 param_info.instance_id = INSTANCE_ID_0;
1435 param_info.param_id = AFE_PARAM_ID_FBSP_PTONE_RAMP_CFG;
1436 param_info.param_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301437
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001438 ret = q6afe_pack_and_set_param_in_band(port,
1439 q6audio_get_port_index(port),
1440 param_info, NULL);
1441 if (ret) {
1442 pr_err("%s: Failed to set speaker ramp duration param, err %d\n",
1443 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301444 goto fail_cmd;
1445 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001446
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301447 /* dsp needs atleast 15ms to ramp down pilot tone*/
1448 usleep_range(15000, 15010);
1449 ret = 0;
1450fail_cmd:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001451 pr_debug("%s: config.pdata.param_id 0x%x status %d\n", __func__,
1452 param_info.param_id, ret);
1453 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301454}
1455
1456static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id,
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001457 union afe_spkr_prot_config *prot_config)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301458{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001459 struct param_hdr_v3 param_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301460 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301461
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001462 memset(&param_info, 0, sizeof(param_info));
1463
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301464 ret = q6audio_validate_port(src_port);
1465 if (ret < 0) {
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001466 pr_err("%s: Invalid src port 0x%x ret %d", __func__, src_port,
1467 ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301468 ret = -EINVAL;
1469 goto fail_cmd;
1470 }
1471 ret = q6audio_validate_port(dst_port);
1472 if (ret < 0) {
1473 pr_err("%s: Invalid dst port 0x%x ret %d", __func__,
1474 dst_port, ret);
1475 ret = -EINVAL;
1476 goto fail_cmd;
1477 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001478
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301479 switch (param_id) {
1480 case AFE_PARAM_ID_FBSP_MODE_RX_CFG:
Xiaojun Sang12120ab2017-09-28 18:21:21 +08001481 case AFE_PARAM_ID_SP_RX_LIMITER_TH:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001482 param_info.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301483 break;
1484 case AFE_PARAM_ID_FEEDBACK_PATH_CFG:
1485 this_afe.vi_tx_port = src_port;
1486 this_afe.vi_rx_port = dst_port;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001487 param_info.module_id = AFE_MODULE_FEEDBACK;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301488 break;
1489 /*
1490 * AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2 is same as
1491 * AFE_PARAM_ID_SP_V2_TH_VI_MODE_CFG
1492 */
1493 case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2:
1494 case AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001495 param_info.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301496 break;
1497 case AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG:
1498 case AFE_PARAM_ID_SP_V2_EX_VI_FTM_CFG:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001499 param_info.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301500 break;
1501 default:
1502 pr_err("%s: default case 0x%x\n", __func__, param_id);
1503 goto fail_cmd;
1504 }
1505
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001506 param_info.instance_id = INSTANCE_ID_0;
1507 param_info.param_id = param_id;
1508 param_info.param_size = sizeof(union afe_spkr_prot_config);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301509
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001510 ret = q6afe_pack_and_set_param_in_band(src_port,
1511 q6audio_get_port_index(src_port),
1512 param_info, (u8 *) prot_config);
1513 if (ret)
1514 pr_err("%s: port = 0x%x param = 0x%x failed %d\n", __func__,
1515 src_port, param_id, ret);
1516
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301517fail_cmd:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001518 pr_debug("%s: config.pdata.param_id 0x%x status %d 0x%x\n", __func__,
1519 param_info.param_id, ret, src_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301520 return ret;
1521}
1522
Vidyakumar Athota94bd8732018-02-28 17:13:35 -08001523static int afe_spkr_prot_reg_event_cfg(u16 port_id)
1524{
1525 struct afe_port_cmd_event_cfg *config;
1526 struct afe_port_cmd_mod_evt_cfg_payload pl;
1527 int index;
1528 int ret;
1529 int num_events = 1;
1530 int cmd_size = sizeof(struct afe_port_cmd_event_cfg) +
1531 (num_events * sizeof(struct afe_port_cmd_mod_evt_cfg_payload));
1532
1533 config = kzalloc(cmd_size, GFP_KERNEL);
1534 if (!config)
1535 return -ENOMEM;
1536
1537 index = q6audio_get_port_index(port_id);
1538 if (index < 0) {
1539 pr_err("%s: Invalid index number: %d\n", __func__, index);
1540 ret = -EINVAL;
1541 goto fail_idx;
1542 }
1543
1544 memset(&pl, 0, sizeof(pl));
1545 pl.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
1546 pl.event_id = AFE_PORT_SP_DC_DETECTION_EVENT;
1547 pl.reg_flag = AFE_MODULE_REGISTER_EVENT_FLAG;
1548
1549
1550 config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1551 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1552 config->hdr.pkt_size = cmd_size;
1553 config->hdr.src_port = 0;
1554 config->hdr.dest_port = 0;
1555 config->hdr.token = index;
1556
1557 config->hdr.opcode = AFE_PORT_CMD_MOD_EVENT_CFG;
1558 config->port_id = q6audio_get_port_id(port_id);
1559 config->num_events = num_events;
1560 config->version = 1;
1561 memcpy(config->payload, &pl, sizeof(pl));
1562 atomic_set(&this_afe.state, 1);
1563 atomic_set(&this_afe.status, 0);
1564 ret = apr_send_pkt(this_afe.apr, (uint32_t *) config);
1565 if (ret < 0) {
1566 pr_err("%s: port = 0x%x failed %d\n",
1567 __func__, port_id, ret);
1568 goto fail_cmd;
1569 }
1570 ret = wait_event_timeout(this_afe.wait[index],
1571 (atomic_read(&this_afe.state) == 0),
1572 msecs_to_jiffies(TIMEOUT_MS));
1573 if (!ret) {
1574 pr_err("%s: wait_event timeout\n", __func__);
1575 ret = -EINVAL;
1576 goto fail_cmd;
1577 }
1578 if (atomic_read(&this_afe.status) > 0) {
1579 pr_err("%s: config cmd failed [%s]\n",
1580 __func__, adsp_err_get_err_str(
1581 atomic_read(&this_afe.status)));
1582 ret = adsp_err_get_lnx_err_code(
1583 atomic_read(&this_afe.status));
1584 goto fail_idx;
1585 }
1586 ret = 0;
1587fail_cmd:
1588 pr_debug("%s: config.opcode 0x%x status %d\n",
1589 __func__, config->hdr.opcode, ret);
1590
1591fail_idx:
1592 kfree(config);
1593 return ret;
1594}
1595
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301596static void afe_send_cal_spkr_prot_tx(int port_id)
1597{
1598 union afe_spkr_prot_config afe_spk_config;
1599
1600 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL ||
1601 this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
1602 this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL)
1603 return;
1604
1605 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1606 if ((this_afe.prot_cfg.mode != MSM_SPKR_PROT_DISABLED) &&
1607 (this_afe.vi_tx_port == port_id)) {
1608 if (this_afe.prot_cfg.mode ==
1609 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
1610 afe_spk_config.vi_proc_cfg.operation_mode =
1611 Q6AFE_MSM_SPKR_CALIBRATION;
1612 afe_spk_config.vi_proc_cfg.quick_calib_flag =
1613 this_afe.prot_cfg.quick_calib_flag;
1614 } else {
1615 afe_spk_config.vi_proc_cfg.operation_mode =
1616 Q6AFE_MSM_SPKR_PROCESSING;
1617 }
1618
1619 if (this_afe.th_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE)
1620 afe_spk_config.vi_proc_cfg.operation_mode =
1621 Q6AFE_MSM_SPKR_FTM_MODE;
1622 afe_spk_config.vi_proc_cfg.minor_version = 1;
1623 afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_1] =
1624 (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1];
1625 afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_2] =
1626 (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_2];
1627 afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_1] =
1628 (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_1];
1629 afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_2] =
1630 (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_2];
1631 if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_NOT_CALIBRATED) {
1632 struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg;
1633
1634 vi_proc_cfg = &afe_spk_config.vi_proc_cfg;
1635 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] =
1636 USE_CALIBRATED_R0TO;
1637 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] =
1638 USE_CALIBRATED_R0TO;
1639 } else {
1640 struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg;
1641
1642 vi_proc_cfg = &afe_spk_config.vi_proc_cfg;
1643 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] =
1644 USE_SAFE_R0TO;
1645 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] =
1646 USE_SAFE_R0TO;
1647 }
1648 if (afe_spk_prot_prepare(port_id, 0,
1649 AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2,
1650 &afe_spk_config))
1651 pr_err("%s: SPKR_CALIB_VI_PROC_CFG failed\n",
1652 __func__);
1653 }
1654 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1655
1656 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
1657 if ((this_afe.th_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE) &&
1658 (this_afe.vi_tx_port == port_id)) {
1659 afe_spk_config.th_vi_ftm_cfg.minor_version = 1;
1660 afe_spk_config.th_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_1] =
1661 this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_1];
1662 afe_spk_config.th_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_2] =
1663 this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_2];
1664 afe_spk_config.th_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_1] =
1665 this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_1];
1666 afe_spk_config.th_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_2] =
1667 this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_2];
1668
1669 if (afe_spk_prot_prepare(port_id, 0,
1670 AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG,
1671 &afe_spk_config))
1672 pr_err("%s: th vi ftm cfg failed\n", __func__);
1673 this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
1674 }
1675 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
1676
1677 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
1678 if ((this_afe.ex_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE) &&
1679 (this_afe.vi_tx_port == port_id)) {
1680 afe_spk_config.ex_vi_mode_cfg.minor_version = 1;
1681 afe_spk_config.ex_vi_mode_cfg.operation_mode =
1682 Q6AFE_MSM_SPKR_FTM_MODE;
1683 if (afe_spk_prot_prepare(port_id, 0,
1684 AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG,
1685 &afe_spk_config))
1686 pr_err("%s: ex vi mode cfg failed\n", __func__);
1687
1688 afe_spk_config.ex_vi_ftm_cfg.minor_version = 1;
1689 afe_spk_config.ex_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_1] =
1690 this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_1];
1691 afe_spk_config.ex_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_2] =
1692 this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_2];
1693 afe_spk_config.ex_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_1] =
1694 this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_1];
1695 afe_spk_config.ex_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_2] =
1696 this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_2];
1697
1698 if (afe_spk_prot_prepare(port_id, 0,
1699 AFE_PARAM_ID_SP_V2_EX_VI_FTM_CFG,
1700 &afe_spk_config))
1701 pr_err("%s: ex vi ftm cfg failed\n", __func__);
1702 this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
1703 }
1704 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
1705
Vidyakumar Athota94bd8732018-02-28 17:13:35 -08001706 /* Register for DC detection event */
1707 afe_spkr_prot_reg_event_cfg(port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301708}
1709
1710static void afe_send_cal_spkr_prot_rx(int port_id)
1711{
1712 union afe_spkr_prot_config afe_spk_config;
Xiaojun Sang12120ab2017-09-28 18:21:21 +08001713 union afe_spkr_prot_config afe_spk_limiter_config;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301714
1715 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
1716 goto done;
1717
1718 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1719
1720 if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_DISABLED &&
1721 (this_afe.vi_rx_port == port_id)) {
1722 if (this_afe.prot_cfg.mode ==
1723 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
1724 afe_spk_config.mode_rx_cfg.mode =
1725 Q6AFE_MSM_SPKR_CALIBRATION;
1726 else
1727 afe_spk_config.mode_rx_cfg.mode =
1728 Q6AFE_MSM_SPKR_PROCESSING;
1729 afe_spk_config.mode_rx_cfg.minor_version = 1;
1730 if (afe_spk_prot_prepare(port_id, 0,
1731 AFE_PARAM_ID_FBSP_MODE_RX_CFG,
1732 &afe_spk_config))
1733 pr_err("%s: RX MODE_VI_PROC_CFG failed\n",
1734 __func__);
Xiaojun Sang12120ab2017-09-28 18:21:21 +08001735
1736 if (afe_spk_config.mode_rx_cfg.mode ==
1737 Q6AFE_MSM_SPKR_PROCESSING) {
1738 if (this_afe.prot_cfg.sp_version >=
1739 AFE_API_VERSION_SUPPORT_SPV3) {
1740 afe_spk_limiter_config.limiter_th_cfg.
1741 minor_version = 1;
1742 afe_spk_limiter_config.limiter_th_cfg.
1743 lim_thr_per_calib_q27[SP_V2_SPKR_1] =
1744 this_afe.prot_cfg.limiter_th[SP_V2_SPKR_1];
1745 afe_spk_limiter_config.limiter_th_cfg.
1746 lim_thr_per_calib_q27[SP_V2_SPKR_2] =
1747 this_afe.prot_cfg.limiter_th[SP_V2_SPKR_2];
1748 if (afe_spk_prot_prepare(port_id, 0,
1749 AFE_PARAM_ID_SP_RX_LIMITER_TH,
1750 &afe_spk_limiter_config))
1751 pr_err("%s: SP_RX_LIMITER_TH failed.\n",
1752 __func__);
1753 } else {
1754 pr_debug("%s: SPv3 failed to apply on AFE API version=%d.\n",
1755 __func__,
1756 this_afe.prot_cfg.sp_version);
1757 }
1758 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301759 }
1760 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1761done:
1762 return;
1763}
1764
1765static int afe_send_hw_delay(u16 port_id, u32 rate)
1766{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001767 struct audio_cal_hw_delay_entry delay_entry;
1768 struct afe_param_id_device_hw_delay_cfg hw_delay;
1769 struct param_hdr_v3 param_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301770 int ret = -EINVAL;
1771
1772 pr_debug("%s:\n", __func__);
1773
1774 memset(&delay_entry, 0, sizeof(delay_entry));
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001775 memset(&param_info, 0, sizeof(param_info));
1776
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301777 delay_entry.sample_rate = rate;
1778 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
1779 ret = afe_get_cal_hw_delay(TX_DEVICE, &delay_entry);
1780 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
1781 ret = afe_get_cal_hw_delay(RX_DEVICE, &delay_entry);
1782
1783 /*
1784 * HW delay is only used for IMS calls to sync audio with video
1785 * It is only needed for devices & sample rates used for IMS video
1786 * calls. Values are received from ACDB calbration files
1787 */
1788 if (ret != 0) {
1789 pr_debug("%s: debug: HW delay info not available %d\n",
1790 __func__, ret);
1791 goto fail_cmd;
1792 }
1793
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001794 param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
1795 param_info.instance_id = INSTANCE_ID_0;
1796 param_info.param_id = AFE_PARAM_ID_DEVICE_HW_DELAY;
1797 param_info.param_size = sizeof(hw_delay);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301798
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001799 hw_delay.delay_in_us = delay_entry.delay_usec;
1800 hw_delay.device_hw_delay_minor_version =
1801 AFE_API_VERSION_DEVICE_HW_DELAY;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301802
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001803 ret = q6afe_pack_and_set_param_in_band(port_id,
1804 q6audio_get_port_index(port_id),
1805 param_info, (u8 *) &hw_delay);
1806 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301807 pr_err("%s: AFE hw delay for port 0x%x failed %d\n",
1808 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301809
1810fail_cmd:
1811 pr_debug("%s: port_id 0x%x rate %u delay_usec %d status %d\n",
1812 __func__, port_id, rate, delay_entry.delay_usec, ret);
1813 return ret;
1814}
1815
1816static struct cal_block_data *afe_find_cal_topo_id_by_port(
1817 struct cal_type_data *cal_type, u16 port_id)
1818{
1819 struct list_head *ptr, *next;
1820 struct cal_block_data *cal_block = NULL;
1821 int32_t path;
1822 struct audio_cal_info_afe_top *afe_top;
1823 int afe_port_index = q6audio_get_port_index(port_id);
1824
1825 if (afe_port_index < 0)
1826 goto err_exit;
1827
1828 list_for_each_safe(ptr, next,
1829 &cal_type->cal_blocks) {
1830 cal_block = list_entry(ptr,
1831 struct cal_block_data, list);
Vikram Panduranga770b8382017-09-27 12:17:36 -07001832 /* Skip cal_block if it is already marked stale */
1833 if (cal_utils_is_cal_stale(cal_block))
1834 continue;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301835 path = ((afe_get_port_type(port_id) ==
1836 MSM_AFE_PORT_TYPE_TX)?(TX_DEVICE):(RX_DEVICE));
1837 afe_top =
1838 (struct audio_cal_info_afe_top *)cal_block->cal_info;
1839 if (afe_top->path == path) {
1840 if (this_afe.dev_acdb_id[afe_port_index] > 0) {
1841 if (afe_top->acdb_id ==
1842 this_afe.dev_acdb_id[afe_port_index]) {
1843 pr_debug("%s: top_id:%x acdb_id:%d afe_port_id:%d\n",
1844 __func__, afe_top->topology,
1845 afe_top->acdb_id,
1846 q6audio_get_port_id(port_id));
1847 return cal_block;
1848 }
1849 } else {
1850 pr_debug("%s: top_id:%x acdb_id:%d afe_port:%d\n",
1851 __func__, afe_top->topology, afe_top->acdb_id,
1852 q6audio_get_port_id(port_id));
1853 return cal_block;
1854 }
1855 }
1856 }
1857
1858err_exit:
1859 return NULL;
1860}
1861
Vikram Panduranga770b8382017-09-27 12:17:36 -07001862/*
1863 * Retrieving cal_block will mark cal_block as stale.
1864 * Hence it cannot be reused or resent unless the flag
1865 * is reset.
1866 */
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301867static int afe_get_cal_topology_id(u16 port_id, u32 *topology_id,
1868 int cal_type_index)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301869{
1870 int ret = 0;
1871
1872 struct cal_block_data *cal_block = NULL;
1873 struct audio_cal_info_afe_top *afe_top_info = NULL;
1874
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301875 if (this_afe.cal_data[cal_type_index] == NULL) {
Vikram Panduranga770b8382017-09-27 12:17:36 -07001876 pr_err("%s: cal_type %d not initialized\n", __func__,
1877 cal_type_index);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301878 return -EINVAL;
1879 }
1880 if (topology_id == NULL) {
1881 pr_err("%s: topology_id is NULL\n", __func__);
1882 return -EINVAL;
1883 }
1884 *topology_id = 0;
1885
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301886 mutex_lock(&this_afe.cal_data[cal_type_index]->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301887 cal_block = afe_find_cal_topo_id_by_port(
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301888 this_afe.cal_data[cal_type_index], port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301889 if (cal_block == NULL) {
Vikram Panduranga770b8382017-09-27 12:17:36 -07001890 pr_err("%s: cal_type %d not initialized for this port %d\n",
1891 __func__, cal_type_index, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301892 ret = -EINVAL;
1893 goto unlock;
1894 }
1895
1896 afe_top_info = ((struct audio_cal_info_afe_top *)
1897 cal_block->cal_info);
1898 if (!afe_top_info->topology) {
1899 pr_err("%s: invalid topology id : [%d, %d]\n",
1900 __func__, afe_top_info->acdb_id, afe_top_info->topology);
1901 ret = -EINVAL;
1902 goto unlock;
1903 }
1904 *topology_id = (u32)afe_top_info->topology;
Vikram Panduranga770b8382017-09-27 12:17:36 -07001905 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301906
1907 pr_debug("%s: port_id = %u acdb_id = %d topology_id = %u ret=%d\n",
1908 __func__, port_id, afe_top_info->acdb_id,
1909 afe_top_info->topology, ret);
1910unlock:
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301911 mutex_unlock(&this_afe.cal_data[cal_type_index]->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301912 return ret;
1913}
1914
1915static int afe_send_port_topology_id(u16 port_id)
1916{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001917 struct afe_param_id_set_topology_cfg topology;
1918 struct param_hdr_v3 param_info;
1919 u32 topology_id = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301920 int index = 0;
1921 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301922
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001923 memset(&topology, 0, sizeof(topology));
1924 memset(&param_info, 0, sizeof(param_info));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301925 index = q6audio_get_port_index(port_id);
1926 if (index < 0 || index >= AFE_MAX_PORTS) {
1927 pr_err("%s: AFE port index[%d] invalid!\n",
1928 __func__, index);
1929 return -EINVAL;
1930 }
1931
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05301932 ret = afe_get_cal_topology_id(port_id, &topology_id, AFE_TOPOLOGY_CAL);
1933 if (ret < 0) {
1934 pr_debug("%s: Check for LSM topology\n", __func__);
1935 ret = afe_get_cal_topology_id(port_id, &topology_id,
1936 AFE_LSM_TOPOLOGY_CAL);
1937 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301938 if (ret || !topology_id) {
1939 pr_debug("%s: AFE port[%d] get_cal_topology[%d] invalid!\n",
1940 __func__, port_id, topology_id);
1941 goto done;
1942 }
1943
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001944 param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
1945 param_info.instance_id = INSTANCE_ID_0;
1946 param_info.param_id = AFE_PARAM_ID_SET_TOPOLOGY;
1947 param_info.param_size = sizeof(topology);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301948
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001949 topology.minor_version = AFE_API_VERSION_TOPOLOGY_V1;
1950 topology.topology_id = topology_id;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301951
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001952 ret = q6afe_pack_and_set_param_in_band(port_id,
1953 q6audio_get_port_index(port_id),
1954 param_info, (u8 *) &topology);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301955 if (ret) {
1956 pr_err("%s: AFE set topology id enable for port 0x%x failed %d\n",
1957 __func__, port_id, ret);
1958 goto done;
1959 }
1960
1961 this_afe.topology[index] = topology_id;
1962 rtac_update_afe_topology(port_id);
1963done:
1964 pr_debug("%s: AFE set topology id 0x%x enable for port 0x%x ret %d\n",
1965 __func__, topology_id, port_id, ret);
1966 return ret;
1967
1968}
1969
1970static int remap_cal_data(struct cal_block_data *cal_block, int cal_index)
1971{
1972 int ret = 0;
1973
Banajit Goswami08bb7362017-11-03 22:48:23 -07001974 if (cal_block->map_data.dma_buf == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301975 pr_err("%s: No ION allocation for cal index %d!\n",
1976 __func__, cal_index);
1977 ret = -EINVAL;
1978 goto done;
1979 }
1980
1981 if ((cal_block->map_data.map_size > 0) &&
1982 (cal_block->map_data.q6map_handle == 0)) {
1983 atomic_set(&this_afe.mem_map_cal_index, cal_index);
1984 ret = afe_cmd_memory_map(cal_block->cal_data.paddr,
1985 cal_block->map_data.map_size);
1986 atomic_set(&this_afe.mem_map_cal_index, -1);
1987 if (ret < 0) {
1988 pr_err("%s: mmap did not work! size = %zd ret %d\n",
1989 __func__,
1990 cal_block->map_data.map_size, ret);
1991 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
1992 __func__,
1993 &cal_block->cal_data.paddr,
1994 cal_block->map_data.map_size);
1995 goto done;
1996 }
1997 cal_block->map_data.q6map_handle = atomic_read(&this_afe.
1998 mem_map_cal_handles[cal_index]);
1999 }
2000done:
2001 return ret;
2002}
2003
2004static struct cal_block_data *afe_find_cal(int cal_index, int port_id)
2005{
2006 struct list_head *ptr, *next;
2007 struct cal_block_data *cal_block = NULL;
2008 struct audio_cal_info_afe *afe_cal_info = NULL;
2009 int afe_port_index = q6audio_get_port_index(port_id);
2010
2011 pr_debug("%s: cal_index %d port_id %d port_index %d\n", __func__,
2012 cal_index, port_id, afe_port_index);
2013 if (afe_port_index < 0) {
2014 pr_err("%s: Error getting AFE port index %d\n",
2015 __func__, afe_port_index);
2016 goto exit;
2017 }
2018
2019 list_for_each_safe(ptr, next,
2020 &this_afe.cal_data[cal_index]->cal_blocks) {
2021 cal_block = list_entry(ptr, struct cal_block_data, list);
2022 afe_cal_info = cal_block->cal_info;
2023 if ((afe_cal_info->acdb_id ==
2024 this_afe.dev_acdb_id[afe_port_index]) &&
2025 (afe_cal_info->sample_rate ==
2026 this_afe.afe_sample_rates[afe_port_index])) {
2027 pr_debug("%s: cal block is a match, size is %zd\n",
2028 __func__, cal_block->cal_data.size);
2029 goto exit;
2030 }
2031 }
2032 pr_err("%s: no matching cal_block found\n", __func__);
2033 cal_block = NULL;
2034
2035exit:
2036 return cal_block;
2037}
2038
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302039static int send_afe_cal_type(int cal_index, int port_id)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302040{
2041 struct cal_block_data *cal_block = NULL;
2042 int ret;
2043 int afe_port_index = q6audio_get_port_index(port_id);
2044
2045 pr_debug("%s:\n", __func__);
2046
2047 if (this_afe.cal_data[cal_index] == NULL) {
2048 pr_warn("%s: cal_index %d not allocated!\n",
2049 __func__, cal_index);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302050 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302051 goto done;
2052 }
2053
2054 if (afe_port_index < 0) {
2055 pr_err("%s: Error getting AFE port index %d\n",
2056 __func__, afe_port_index);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302057 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302058 goto done;
2059 }
2060
2061 mutex_lock(&this_afe.cal_data[cal_index]->lock);
2062
2063 if (((cal_index == AFE_COMMON_RX_CAL) ||
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302064 (cal_index == AFE_COMMON_TX_CAL) ||
2065 (cal_index == AFE_LSM_TX_CAL)) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302066 (this_afe.dev_acdb_id[afe_port_index] > 0))
2067 cal_block = afe_find_cal(cal_index, port_id);
2068 else
2069 cal_block = cal_utils_get_only_cal_block(
2070 this_afe.cal_data[cal_index]);
2071
Vikram Panduranga770b8382017-09-27 12:17:36 -07002072 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302073 pr_err("%s cal_block not found!!\n", __func__);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302074 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302075 goto unlock;
2076 }
2077
2078 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
2079
2080 ret = remap_cal_data(cal_block, cal_index);
2081 if (ret) {
2082 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2083 __func__, cal_index);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302084 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302085 goto unlock;
2086 }
2087 ret = afe_send_cal_block(port_id, cal_block);
2088 if (ret < 0)
2089 pr_debug("%s: No cal sent for cal_index %d, port_id = 0x%x! ret %d\n",
2090 __func__, cal_index, port_id, ret);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002091
2092 cal_utils_mark_cal_used(cal_block);
2093
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302094unlock:
2095 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
2096done:
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302097 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302098}
2099
2100void afe_send_cal(u16 port_id)
2101{
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302102 int ret;
2103
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302104 pr_debug("%s: port_id=0x%x\n", __func__, port_id);
2105
2106 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) {
2107 afe_send_cal_spkr_prot_tx(port_id);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302108 ret = send_afe_cal_type(AFE_COMMON_TX_CAL, port_id);
2109 if (ret < 0)
2110 send_afe_cal_type(AFE_LSM_TX_CAL, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302111 } else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302112 send_afe_cal_type(AFE_COMMON_RX_CAL, port_id);
Xiaojun Sang092e0ed2017-12-11 16:13:32 +08002113 afe_send_cal_spkr_prot_rx(port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302114 }
2115}
2116
2117int afe_turn_onoff_hw_mad(u16 mad_type, u16 enable)
2118{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002119 struct afe_param_hw_mad_ctrl mad_enable_param;
2120 struct param_hdr_v3 param_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302121 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302122
2123 pr_debug("%s: enter\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302124
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002125 memset(&mad_enable_param, 0, sizeof(mad_enable_param));
2126 memset(&param_info, 0, sizeof(param_info));
2127 param_info.module_id = AFE_MODULE_HW_MAD;
2128 param_info.instance_id = INSTANCE_ID_0;
2129 param_info.param_id = AFE_PARAM_ID_HW_MAD_CTRL;
2130 param_info.param_size = sizeof(mad_enable_param);
2131
2132 mad_enable_param.minor_version = 1;
2133 mad_enable_param.mad_type = mad_type;
2134 mad_enable_param.mad_enable = enable;
2135
2136 ret = q6afe_pack_and_set_param_in_band(SLIMBUS_5_TX, IDX_GLOBAL_CFG,
2137 param_info,
2138 (u8 *) &mad_enable_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302139 if (ret)
2140 pr_err("%s: AFE_PARAM_ID_HW_MAD_CTRL failed %d\n", __func__,
2141 ret);
2142 return ret;
2143}
2144
2145static int afe_send_slimbus_slave_cfg(
2146 struct afe_param_cdc_slimbus_slave_cfg *sb_slave_cfg)
2147{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002148 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302149 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302150
2151 pr_debug("%s: enter\n", __func__);
2152
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002153 memset(&param_hdr, 0, sizeof(param_hdr));
2154 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2155 param_hdr.instance_id = INSTANCE_ID_0;
2156 param_hdr.param_id = AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG;
2157 param_hdr.param_size = sizeof(struct afe_param_cdc_slimbus_slave_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302158
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002159 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
2160 (u8 *) sb_slave_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302161 if (ret)
2162 pr_err("%s: AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG failed %d\n",
2163 __func__, ret);
2164
2165 pr_debug("%s: leave %d\n", __func__, ret);
2166 return ret;
2167}
2168
2169static int afe_send_codec_reg_page_config(
2170 struct afe_param_cdc_reg_page_cfg *cdc_reg_page_cfg)
2171{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002172 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302173 int ret;
2174
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002175 memset(&param_hdr, 0, sizeof(param_hdr));
2176 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2177 param_hdr.instance_id = INSTANCE_ID_0;
2178 param_hdr.param_id = AFE_PARAM_ID_CDC_REG_PAGE_CFG;
2179 param_hdr.param_size = sizeof(struct afe_param_cdc_reg_page_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302180
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002181 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
2182 (u8 *) cdc_reg_page_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302183 if (ret)
2184 pr_err("%s: AFE_PARAM_ID_CDC_REG_PAGE_CFG failed %d\n",
2185 __func__, ret);
2186
2187 return ret;
2188}
2189
2190static int afe_send_codec_reg_config(
2191 struct afe_param_cdc_reg_cfg_data *cdc_reg_cfg)
2192{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002193 u8 *packed_param_data = NULL;
2194 u32 packed_data_size = 0;
2195 u32 single_param_size = 0;
2196 u32 max_data_size = 0;
2197 u32 max_single_param = 0;
2198 struct param_hdr_v3 param_hdr;
2199 int idx = 0;
2200 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302201
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002202 memset(&param_hdr, 0, sizeof(param_hdr));
2203 max_single_param = sizeof(struct param_hdr_v3) +
2204 sizeof(struct afe_param_cdc_reg_cfg);
2205 max_data_size = APR_MAX_BUF - sizeof(struct afe_svc_cmd_set_param_v2);
2206 packed_param_data = kzalloc(max_data_size, GFP_KERNEL);
2207 if (!packed_param_data)
2208 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302209
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002210 /* param_hdr is the same for all params sent, set once at top */
2211 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2212 param_hdr.instance_id = INSTANCE_ID_0;
2213 param_hdr.param_id = AFE_PARAM_ID_CDC_REG_CFG;
2214 param_hdr.param_size = sizeof(struct afe_param_cdc_reg_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302215
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002216 while (idx < cdc_reg_cfg->num_registers) {
2217 memset(packed_param_data, 0, max_data_size);
2218 packed_data_size = 0;
2219 single_param_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302220
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002221 while (packed_data_size + max_single_param < max_data_size &&
2222 idx < cdc_reg_cfg->num_registers) {
2223 ret = q6common_pack_pp_params(
2224 packed_param_data + packed_data_size,
2225 &param_hdr, (u8 *) &cdc_reg_cfg->reg_data[idx],
2226 &single_param_size);
2227 if (ret) {
2228 pr_err("%s: Failed to pack parameters with error %d\n",
2229 __func__, ret);
2230 goto done;
2231 }
2232 packed_data_size += single_param_size;
2233 idx++;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302234 }
2235
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002236 ret = q6afe_svc_set_params(IDX_GLOBAL_CFG, NULL,
2237 packed_param_data, packed_data_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302238 if (ret) {
2239 pr_err("%s: AFE_PARAM_ID_CDC_REG_CFG failed %d\n",
2240 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302241 break;
2242 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302243 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002244done:
2245 kfree(packed_param_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302246 return ret;
2247}
2248
2249static int afe_init_cdc_reg_config(void)
2250{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002251 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302252 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302253
2254 pr_debug("%s: enter\n", __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002255 memset(&param_hdr, 0, sizeof(param_hdr));
2256 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2257 param_hdr.instance_id = INSTANCE_ID_0;
2258 param_hdr.param_id = AFE_PARAM_ID_CDC_REG_CFG_INIT;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302259
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002260 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
2261 NULL);
2262 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302263 pr_err("%s: AFE_PARAM_ID_CDC_INIT_REG_CFG failed %d\n",
2264 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302265
2266 return ret;
2267}
2268
2269static int afe_send_slimbus_slave_port_cfg(
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002270 struct afe_param_slimbus_slave_port_cfg *slim_slave_config, u16 port_id)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302271{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002272 struct param_hdr_v3 param_hdr;
2273 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302274
2275 pr_debug("%s: enter, port_id = 0x%x\n", __func__, port_id);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002276 memset(&param_hdr, 0, sizeof(param_hdr));
2277 param_hdr.module_id = AFE_MODULE_HW_MAD;
2278 param_hdr.instance_id = INSTANCE_ID_0;
2279 param_hdr.reserved = 0;
2280 param_hdr.param_id = AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG;
2281 param_hdr.param_size = sizeof(struct afe_param_slimbus_slave_port_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302282
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002283 ret = q6afe_pack_and_set_param_in_band(port_id,
2284 q6audio_get_port_index(port_id),
2285 param_hdr,
2286 (u8 *) slim_slave_config);
2287 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302288 pr_err("%s: AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG failed %d\n",
2289 __func__, ret);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002290
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302291 pr_debug("%s: leave %d\n", __func__, ret);
2292 return ret;
2293}
2294static int afe_aanc_port_cfg(void *apr, uint16_t tx_port, uint16_t rx_port)
2295{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002296 struct afe_param_aanc_port_cfg aanc_port_cfg;
2297 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302298 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302299
2300 pr_debug("%s: tx_port 0x%x, rx_port 0x%x\n",
2301 __func__, tx_port, rx_port);
2302
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002303 pr_debug("%s: AANC sample rate tx rate: %d rx rate %d\n", __func__,
2304 this_afe.aanc_info.aanc_tx_port_sample_rate,
2305 this_afe.aanc_info.aanc_rx_port_sample_rate);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302306
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002307 memset(&aanc_port_cfg, 0, sizeof(aanc_port_cfg));
2308 memset(&param_hdr, 0, sizeof(param_hdr));
2309
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302310 /*
2311 * If aanc tx sample rate or rx sample rate is zero, skip aanc
2312 * configuration as AFE resampler will fail for invalid sample
2313 * rates.
2314 */
2315 if (!this_afe.aanc_info.aanc_tx_port_sample_rate ||
2316 !this_afe.aanc_info.aanc_rx_port_sample_rate) {
2317 return -EINVAL;
2318 }
2319
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002320 param_hdr.module_id = AFE_MODULE_AANC;
2321 param_hdr.instance_id = INSTANCE_ID_0;
2322 param_hdr.param_id = AFE_PARAM_ID_AANC_PORT_CONFIG;
2323 param_hdr.param_size = sizeof(struct afe_param_aanc_port_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302324
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002325 aanc_port_cfg.aanc_port_cfg_minor_version =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302326 AFE_API_VERSION_AANC_PORT_CONFIG;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002327 aanc_port_cfg.tx_port_sample_rate =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302328 this_afe.aanc_info.aanc_tx_port_sample_rate;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002329 aanc_port_cfg.tx_port_channel_map[0] = AANC_TX_VOICE_MIC;
2330 aanc_port_cfg.tx_port_channel_map[1] = AANC_TX_NOISE_MIC;
2331 aanc_port_cfg.tx_port_channel_map[2] = AANC_TX_ERROR_MIC;
2332 aanc_port_cfg.tx_port_channel_map[3] = AANC_TX_MIC_UNUSED;
2333 aanc_port_cfg.tx_port_channel_map[4] = AANC_TX_MIC_UNUSED;
2334 aanc_port_cfg.tx_port_channel_map[5] = AANC_TX_MIC_UNUSED;
2335 aanc_port_cfg.tx_port_channel_map[6] = AANC_TX_MIC_UNUSED;
2336 aanc_port_cfg.tx_port_channel_map[7] = AANC_TX_MIC_UNUSED;
2337 aanc_port_cfg.tx_port_num_channels = 3;
2338 aanc_port_cfg.rx_path_ref_port_id = rx_port;
2339 aanc_port_cfg.ref_port_sample_rate =
2340 this_afe.aanc_info.aanc_rx_port_sample_rate;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302341
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002342 ret = q6afe_pack_and_set_param_in_band(tx_port,
2343 q6audio_get_port_index(tx_port),
2344 param_hdr,
2345 (u8 *) &aanc_port_cfg);
2346 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302347 pr_err("%s: AFE AANC port config failed for tx_port 0x%x, rx_port 0x%x ret %d\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002348 __func__, tx_port, rx_port, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302349
2350 return ret;
2351}
2352
2353static int afe_aanc_mod_enable(void *apr, uint16_t tx_port, uint16_t enable)
2354{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002355 struct afe_mod_enable_param mod_enable;
2356 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302357 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302358
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002359 pr_debug("%s: tx_port 0x%x\n", __func__, tx_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302360
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002361 memset(&mod_enable, 0, sizeof(mod_enable));
2362 memset(&param_hdr, 0, sizeof(param_hdr));
2363 param_hdr.module_id = AFE_MODULE_AANC;
2364 param_hdr.instance_id = INSTANCE_ID_0;
2365 param_hdr.param_id = AFE_PARAM_ID_ENABLE;
2366 param_hdr.param_size = sizeof(struct afe_mod_enable_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302367
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002368 mod_enable.enable = enable;
2369 mod_enable.reserved = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302370
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002371 ret = q6afe_pack_and_set_param_in_band(tx_port,
2372 q6audio_get_port_index(tx_port),
2373 param_hdr, (u8 *) &mod_enable);
2374 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302375 pr_err("%s: AFE AANC enable failed for tx_port 0x%x ret %d\n",
2376 __func__, tx_port, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302377 return ret;
2378}
2379
2380static int afe_send_bank_selection_clip(
2381 struct afe_param_id_clip_bank_sel *param)
2382{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002383 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302384 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302385
2386 if (!param) {
2387 pr_err("%s: Invalid params", __func__);
2388 return -EINVAL;
2389 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002390 memset(&param_hdr, 0, sizeof(param_hdr));
2391 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2392 param_hdr.instance_id = INSTANCE_ID_0;
2393 param_hdr.param_id = AFE_PARAM_ID_CLIP_BANK_SEL_CFG;
2394 param_hdr.param_size = sizeof(struct afe_param_id_clip_bank_sel);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302395
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002396 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
2397 (u8 *) param);
2398 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302399 pr_err("%s: AFE_PARAM_ID_CLIP_BANK_SEL_CFG failed %d\n",
2400 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302401 return ret;
2402}
2403int afe_send_aanc_version(
2404 struct afe_param_id_cdc_aanc_version *version_cfg)
2405{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002406 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302407 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302408
2409 pr_debug("%s: enter\n", __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002410 memset(&param_hdr, 0, sizeof(param_hdr));
2411 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2412 param_hdr.instance_id = INSTANCE_ID_0;
2413 param_hdr.param_id = AFE_PARAM_ID_CDC_AANC_VERSION;
2414 param_hdr.param_size = sizeof(struct afe_param_id_cdc_aanc_version);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302415
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002416 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
2417 (u8 *) version_cfg);
2418 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302419 pr_err("%s: AFE_PARAM_ID_CDC_AANC_VERSION failed %d\n",
2420 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302421 return ret;
2422}
2423
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302424/**
2425 * afe_port_set_mad_type -
2426 * to update mad type
2427 *
2428 * @port_id: AFE port id number
2429 * @mad_type: MAD type enum value
2430 *
2431 * Returns 0 on success or error on failure.
2432 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302433int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type)
2434{
2435 int i;
2436
2437 if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
2438 port_id == AFE_PORT_ID_INT3_MI2S_TX) {
2439 mad_type = MAD_SW_AUDIO;
2440 return 0;
2441 }
2442
2443 i = port_id - SLIMBUS_0_RX;
2444 if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
2445 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2446 return -EINVAL;
2447 }
2448 atomic_set(&afe_ports_mad_type[i], mad_type);
2449 return 0;
2450}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302451EXPORT_SYMBOL(afe_port_set_mad_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302452
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302453/**
2454 * afe_port_get_mad_type -
2455 * to retrieve mad type
2456 *
2457 * @port_id: AFE port id number
2458 *
2459 * Returns valid enum value on success or MAD_HW_NONE on failure.
2460 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302461enum afe_mad_type afe_port_get_mad_type(u16 port_id)
2462{
2463 int i;
2464
2465 if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
2466 port_id == AFE_PORT_ID_INT3_MI2S_TX)
2467 return MAD_SW_AUDIO;
2468
2469 i = port_id - SLIMBUS_0_RX;
2470 if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
2471 pr_debug("%s: Non Slimbus port_id 0x%x\n", __func__, port_id);
2472 return MAD_HW_NONE;
2473 }
2474 return (enum afe_mad_type) atomic_read(&afe_ports_mad_type[i]);
2475}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302476EXPORT_SYMBOL(afe_port_get_mad_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302477
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302478/**
2479 * afe_set_config -
2480 * to configure AFE session with
2481 * specified configuration for given config type
2482 *
2483 * @config_type: config type
2484 * @config_data: configuration to pass to AFE session
2485 * @arg: argument used in specific config types
2486 *
2487 * Returns 0 on success or error value on port start failure.
2488 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302489int afe_set_config(enum afe_config_type config_type, void *config_data, int arg)
2490{
2491 int ret;
2492
2493 pr_debug("%s: enter config_type %d\n", __func__, config_type);
2494 ret = afe_q6_interface_prepare();
2495 if (ret) {
2496 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2497 return ret;
2498 }
2499
2500 switch (config_type) {
2501 case AFE_SLIMBUS_SLAVE_CONFIG:
2502 ret = afe_send_slimbus_slave_cfg(config_data);
2503 if (!ret)
2504 ret = afe_init_cdc_reg_config();
2505 else
2506 pr_err("%s: Sending slimbus slave config failed %d\n",
2507 __func__, ret);
2508 break;
2509 case AFE_CDC_REGISTERS_CONFIG:
2510 ret = afe_send_codec_reg_config(config_data);
2511 break;
2512 case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
2513 ret = afe_send_slimbus_slave_port_cfg(config_data, arg);
2514 break;
2515 case AFE_AANC_VERSION:
2516 ret = afe_send_aanc_version(config_data);
2517 break;
2518 case AFE_CLIP_BANK_SEL:
2519 ret = afe_send_bank_selection_clip(config_data);
2520 break;
2521 case AFE_CDC_CLIP_REGISTERS_CONFIG:
2522 ret = afe_send_codec_reg_config(config_data);
2523 break;
2524 case AFE_CDC_REGISTER_PAGE_CONFIG:
2525 ret = afe_send_codec_reg_page_config(config_data);
2526 break;
2527 default:
2528 pr_err("%s: unknown configuration type %d",
2529 __func__, config_type);
2530 ret = -EINVAL;
2531 }
2532
2533 if (!ret)
2534 set_bit(config_type, &afe_configured_cmd);
2535
2536 return ret;
2537}
2538EXPORT_SYMBOL(afe_set_config);
2539
2540/*
2541 * afe_clear_config - If SSR happens ADSP loses AFE configs, let AFE driver know
2542 * about the state so client driver can wait until AFE is
2543 * reconfigured.
2544 */
2545void afe_clear_config(enum afe_config_type config)
2546{
2547 clear_bit(config, &afe_configured_cmd);
2548}
2549EXPORT_SYMBOL(afe_clear_config);
2550
2551bool afe_has_config(enum afe_config_type config)
2552{
2553 return !!test_bit(config, &afe_configured_cmd);
2554}
2555
2556int afe_send_spdif_clk_cfg(struct afe_param_id_spdif_clk_cfg *cfg,
2557 u16 port_id)
2558{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002559 struct afe_param_id_spdif_clk_cfg clk_cfg;
2560 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302561 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302562
2563 if (!cfg) {
2564 pr_err("%s: Error, no configuration data\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302565 return -EINVAL;
2566 }
2567
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002568 memset(&clk_cfg, 0, sizeof(clk_cfg));
2569 memset(&param_hdr, 0, sizeof(param_hdr));
2570 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2571 param_hdr.instance_id = INSTANCE_ID_0;
2572 param_hdr.param_id = AFE_PARAM_ID_SPDIF_CLK_CONFIG;
2573 param_hdr.param_size = sizeof(struct afe_param_id_spdif_clk_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302574
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002575 pr_debug("%s: Minor version = 0x%x clk val = %d clk root = 0x%x port id = 0x%x\n",
2576 __func__, clk_cfg.clk_cfg_minor_version, clk_cfg.clk_value,
2577 clk_cfg.clk_root, q6audio_get_port_id(port_id));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302578
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002579 ret = q6afe_pack_and_set_param_in_band(port_id,
2580 q6audio_get_port_index(port_id),
2581 param_hdr, (u8 *) &clk_cfg);
2582 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302583 pr_err("%s: AFE send clock config for port 0x%x failed ret = %d\n",
2584 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302585 return ret;
2586}
2587
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302588/**
2589 * afe_send_spdif_ch_status_cfg -
2590 * to configure AFE session with
2591 * specified channel status configuration
2592 *
2593 * @ch_status_cfg: channel status configutation
2594 * @port_id: AFE port id number
2595 *
2596 * Returns 0 on success or error value on port start failure.
2597 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302598int afe_send_spdif_ch_status_cfg(struct afe_param_id_spdif_ch_status_cfg
2599 *ch_status_cfg, u16 port_id)
2600{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002601 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302602 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302603
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002604 if (!ch_status_cfg)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302605 pr_err("%s: Error, no configuration data\n", __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002606 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302607
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002608 memset(&param_hdr, 0, sizeof(param_hdr));
2609 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2610 param_hdr.instance_id = INSTANCE_ID_0;
2611 param_hdr.param_id = AFE_PARAM_ID_SPDIF_CLK_CONFIG;
2612 param_hdr.param_size = sizeof(struct afe_param_id_spdif_ch_status_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302613
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002614 ret = q6afe_pack_and_set_param_in_band(port_id,
2615 q6audio_get_port_index(port_id),
2616 param_hdr, (u8 *) ch_status_cfg);
2617 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302618 pr_err("%s: AFE send channel status for port 0x%x failed ret = %d\n",
2619 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302620 return ret;
2621}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302622EXPORT_SYMBOL(afe_send_spdif_ch_status_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302623
2624static int afe_send_cmd_port_start(u16 port_id)
2625{
2626 struct afe_port_cmd_device_start start;
2627 int ret, index;
2628
2629 pr_debug("%s: enter\n", __func__);
2630 index = q6audio_get_port_index(port_id);
2631 if (index < 0 || index >= AFE_MAX_PORTS) {
2632 pr_err("%s: AFE port index[%d] invalid!\n",
2633 __func__, index);
2634 return -EINVAL;
2635 }
2636 ret = q6audio_validate_port(port_id);
2637 if (ret < 0) {
2638 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2639 return -EINVAL;
2640 }
2641
2642 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2643 APR_HDR_LEN(APR_HDR_SIZE),
2644 APR_PKT_VER);
2645 start.hdr.pkt_size = sizeof(start);
2646 start.hdr.src_port = 0;
2647 start.hdr.dest_port = 0;
2648 start.hdr.token = index;
2649 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
2650 start.port_id = q6audio_get_port_id(port_id);
2651 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
2652 __func__, start.hdr.opcode, start.port_id);
2653
2654 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
2655 if (ret) {
2656 pr_err("%s: AFE enable for port 0x%x failed %d\n", __func__,
2657 port_id, ret);
2658 } else if (this_afe.task != current) {
2659 this_afe.task = current;
2660 pr_debug("task_name = %s pid = %d\n",
2661 this_afe.task->comm, this_afe.task->pid);
2662 }
2663
2664 return ret;
2665}
2666
2667static int afe_aanc_start(uint16_t tx_port_id, uint16_t rx_port_id)
2668{
2669 int ret;
2670
2671 pr_debug("%s: Tx port is 0x%x, Rx port is 0x%x\n",
2672 __func__, tx_port_id, rx_port_id);
2673 ret = afe_aanc_port_cfg(this_afe.apr, tx_port_id, rx_port_id);
2674 if (ret) {
2675 pr_err("%s: Send AANC Port Config failed %d\n",
2676 __func__, ret);
2677 goto fail_cmd;
2678 }
2679 send_afe_cal_type(AFE_AANC_CAL, tx_port_id);
2680
2681fail_cmd:
2682 return ret;
2683}
2684
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302685/**
2686 * afe_spdif_port_start - to configure AFE session with
2687 * specified port configuration
2688 *
2689 * @port_id: AFE port id number
2690 * @spdif_port: spdif port configutation
2691 * @rate: sampling rate of port
2692 *
2693 * Returns 0 on success or error value on port start failure.
2694 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302695int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port,
2696 u32 rate)
2697{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002698 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302699 uint16_t port_index;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002700 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302701
2702 if (!spdif_port) {
2703 pr_err("%s: Error, no configuration data\n", __func__);
2704 ret = -EINVAL;
2705 return ret;
2706 }
2707
2708 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2709
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002710 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302711 ret = q6audio_validate_port(port_id);
2712 if (ret < 0) {
2713 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2714 return -EINVAL;
2715 }
2716
2717 afe_send_cal(port_id);
2718 afe_send_hw_delay(port_id, rate);
2719
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002720 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2721 param_hdr.instance_id = INSTANCE_ID_0;
2722 param_hdr.param_id = AFE_PARAM_ID_SPDIF_CONFIG;
2723 param_hdr.param_size = sizeof(struct afe_spdif_port_config);
2724
2725 ret = q6afe_pack_and_set_param_in_band(port_id,
2726 q6audio_get_port_index(port_id),
2727 param_hdr, (u8 *) spdif_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302728 if (ret) {
2729 pr_err("%s: AFE enable for port 0x%x failed ret = %d\n",
2730 __func__, port_id, ret);
2731 goto fail_cmd;
2732 }
2733
2734 port_index = afe_get_port_index(port_id);
2735 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
2736 this_afe.afe_sample_rates[port_index] = rate;
2737 } else {
2738 pr_err("%s: Invalid port index %d\n", __func__, port_index);
2739 ret = -EINVAL;
2740 goto fail_cmd;
2741 }
2742
2743 ret = afe_send_spdif_ch_status_cfg(&spdif_port->ch_status, port_id);
2744 if (ret < 0) {
2745 pr_err("%s: afe send failed %d\n", __func__, ret);
2746 goto fail_cmd;
2747 }
2748
2749 return afe_send_cmd_port_start(port_id);
2750
2751fail_cmd:
2752 return ret;
2753}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302754EXPORT_SYMBOL(afe_spdif_port_start);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302755
2756int afe_send_slot_mapping_cfg(
2757 struct afe_param_id_slot_mapping_cfg *slot_mapping_cfg,
2758 u16 port_id)
2759{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002760 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302761 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302762
2763 if (!slot_mapping_cfg) {
2764 pr_err("%s: Error, no configuration data\n", __func__);
2765 return -EINVAL;
2766 }
2767
2768 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2769
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002770 memset(&param_hdr, 0, sizeof(param_hdr));
2771 param_hdr.module_id = AFE_MODULE_TDM;
2772 param_hdr.instance_id = INSTANCE_ID_0;
2773 param_hdr.param_id = AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG;
2774 param_hdr.param_size = sizeof(struct afe_param_id_slot_mapping_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302775
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002776 ret = q6afe_pack_and_set_param_in_band(port_id,
2777 q6audio_get_port_index(port_id),
2778 param_hdr,
2779 (u8 *) slot_mapping_cfg);
2780 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302781 pr_err("%s: AFE send slot mapping for port 0x%x failed ret = %d\n",
2782 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302783 return ret;
2784}
2785
2786int afe_send_custom_tdm_header_cfg(
2787 struct afe_param_id_custom_tdm_header_cfg *custom_tdm_header_cfg,
2788 u16 port_id)
2789{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002790 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302791 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302792
2793 if (!custom_tdm_header_cfg) {
2794 pr_err("%s: Error, no configuration data\n", __func__);
2795 return -EINVAL;
2796 }
2797
2798 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2799
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002800 memset(&param_hdr, 0, sizeof(param_hdr));
2801 param_hdr.module_id = AFE_MODULE_TDM;
2802 param_hdr.instance_id = INSTANCE_ID_0;
2803 param_hdr.param_id = AFE_PARAM_ID_CUSTOM_TDM_HEADER_CONFIG;
2804 param_hdr.param_size =
2805 sizeof(struct afe_param_id_custom_tdm_header_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302806
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002807 ret = q6afe_pack_and_set_param_in_band(port_id,
2808 q6audio_get_port_index(port_id),
2809 param_hdr,
2810 (u8 *) custom_tdm_header_cfg);
2811 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302812 pr_err("%s: AFE send custom tdm header for port 0x%x failed ret = %d\n",
2813 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302814 return ret;
2815}
2816
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302817/**
2818 * afe_tdm_port_start - to configure AFE session with
2819 * specified port configuration
2820 *
2821 * @port_id: AFE port id number
2822 * @tdm_port: TDM port configutation
2823 * @rate: sampling rate of port
2824 * @num_groups: number of TDM groups
2825 *
2826 * Returns 0 on success or error value on port start failure.
2827 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302828int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
2829 u32 rate, u16 num_groups)
2830{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002831 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302832 int index = 0;
2833 uint16_t port_index = 0;
2834 enum afe_mad_type mad_type = MAD_HW_NONE;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002835 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302836
2837 if (!tdm_port) {
2838 pr_err("%s: Error, no configuration data\n", __func__);
2839 return -EINVAL;
2840 }
2841
2842 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
2843
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002844 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302845 index = q6audio_get_port_index(port_id);
2846 if (index < 0 || index >= AFE_MAX_PORTS) {
2847 pr_err("%s: AFE port index[%d] invalid!\n",
2848 __func__, index);
2849 return -EINVAL;
2850 }
2851 ret = q6audio_validate_port(port_id);
2852 if (ret < 0) {
2853 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
2854 return -EINVAL;
2855 }
2856
2857 ret = afe_q6_interface_prepare();
2858 if (ret != 0) {
2859 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2860 return ret;
2861 }
2862
2863 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
2864 this_afe.afe_sample_rates[index] = rate;
2865
2866 if (this_afe.rt_cb)
2867 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
2868 }
2869
Xiaoyu Ye13da4822017-09-18 17:46:30 -07002870 /* Also send the topology id here: */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302871 port_index = afe_get_port_index(port_id);
Xiaoyu Ye13da4822017-09-18 17:46:30 -07002872 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302873 /* One time call: only for first time */
2874 afe_send_custom_topology();
2875 afe_send_port_topology_id(port_id);
2876 afe_send_cal(port_id);
2877 afe_send_hw_delay(port_id, rate);
2878 }
2879
2880 /* Start SW MAD module */
2881 mad_type = afe_port_get_mad_type(port_id);
2882 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
2883 mad_type);
2884 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
2885 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
2886 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
2887 pr_err("%s: AFE isn't configured yet for\n"
2888 "HW MAD try Again\n", __func__);
2889 ret = -EAGAIN;
2890 goto fail_cmd;
2891 }
2892 ret = afe_turn_onoff_hw_mad(mad_type, true);
2893 if (ret) {
2894 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
2895 __func__, ret);
2896 goto fail_cmd;
2897 }
2898 }
2899
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002900 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2901 param_hdr.instance_id = INSTANCE_ID_0;
2902 param_hdr.param_id = AFE_PARAM_ID_TDM_CONFIG;
2903 param_hdr.param_size = sizeof(struct afe_param_id_tdm_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302904
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002905 ret = q6afe_pack_and_set_param_in_band(port_id,
2906 q6audio_get_port_index(port_id),
2907 param_hdr,
2908 (u8 *) &tdm_port->tdm);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302909 if (ret) {
2910 pr_err("%s: AFE enable for port 0x%x failed ret = %d\n",
2911 __func__, port_id, ret);
2912 goto fail_cmd;
2913 }
2914
2915 port_index = afe_get_port_index(port_id);
2916 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
2917 this_afe.afe_sample_rates[port_index] = rate;
2918 } else {
2919 pr_err("%s: Invalid port index %d\n", __func__, port_index);
2920 ret = -EINVAL;
2921 goto fail_cmd;
2922 }
Xiaoyu Ye13da4822017-09-18 17:46:30 -07002923
2924 ret = afe_send_slot_mapping_cfg(&tdm_port->slot_mapping,
2925 port_id);
2926 if (ret < 0) {
2927 pr_err("%s: afe send failed %d\n", __func__, ret);
2928 goto fail_cmd;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302929 }
2930
2931 if (tdm_port->custom_tdm_header.header_type) {
2932 ret = afe_send_custom_tdm_header_cfg(
2933 &tdm_port->custom_tdm_header, port_id);
2934 if (ret < 0) {
2935 pr_err("%s: afe send failed %d\n", __func__, ret);
2936 goto fail_cmd;
2937 }
2938 }
2939
2940 ret = afe_send_cmd_port_start(port_id);
2941
2942fail_cmd:
2943 return ret;
2944}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302945EXPORT_SYMBOL(afe_tdm_port_start);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302946
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302947/**
2948 * afe_set_cal_mode -
2949 * set cal mode for AFE calibration
2950 *
2951 * @port_id: AFE port id number
2952 * @afe_cal_mode: AFE calib mode
2953 *
2954 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302955void afe_set_cal_mode(u16 port_id, enum afe_cal_mode afe_cal_mode)
2956{
2957 uint16_t port_index;
2958
2959 port_index = afe_get_port_index(port_id);
2960 this_afe.afe_cal_mode[port_index] = afe_cal_mode;
2961}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302962EXPORT_SYMBOL(afe_set_cal_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302963
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302964/**
2965 * afe_set_routing_callback -
2966 * Update callback function for routing
2967 *
2968 * @cb: callback function to update with
2969 *
2970 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302971void afe_set_routing_callback(routing_cb cb)
2972{
2973 this_afe.rt_cb = cb;
2974}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302975EXPORT_SYMBOL(afe_set_routing_callback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302976
2977int afe_port_send_usb_dev_param(u16 port_id, union afe_port_config *afe_config)
2978{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002979 struct afe_param_id_usb_audio_dev_params usb_dev;
2980 struct afe_param_id_usb_audio_dev_lpcm_fmt lpcm_fmt;
Garmond Leung6b3f4182018-05-11 12:29:34 -07002981 struct afe_param_id_usb_audio_svc_interval svc_int;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002982 struct param_hdr_v3 param_hdr;
Garmond Leung6b3f4182018-05-11 12:29:34 -07002983 int ret = 0, index = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302984
2985 if (!afe_config) {
2986 pr_err("%s: Error, no configuration data\n", __func__);
2987 ret = -EINVAL;
2988 goto exit;
2989 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302990
Garmond Leung6b3f4182018-05-11 12:29:34 -07002991 index = q6audio_get_port_index(port_id);
2992
2993 if (index < 0 || index >= AFE_MAX_PORTS) {
2994 pr_err("%s: AFE port index[%d] invalid!\n",
2995 __func__, index);
2996 return -EINVAL;
2997 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002998 memset(&usb_dev, 0, sizeof(usb_dev));
2999 memset(&lpcm_fmt, 0, sizeof(lpcm_fmt));
3000 memset(&param_hdr, 0, sizeof(param_hdr));
3001 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3002 param_hdr.instance_id = INSTANCE_ID_0;
3003
3004 param_hdr.param_id = AFE_PARAM_ID_USB_AUDIO_DEV_PARAMS;
3005 param_hdr.param_size = sizeof(usb_dev);
Garmond Leung6b3f4182018-05-11 12:29:34 -07003006 usb_dev.cfg_minor_version = AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003007 usb_dev.dev_token = afe_config->usb_audio.dev_token;
3008
3009 ret = q6afe_pack_and_set_param_in_band(port_id,
3010 q6audio_get_port_index(port_id),
3011 param_hdr, (u8 *) &usb_dev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303012 if (ret) {
3013 pr_err("%s: AFE device param cmd failed %d\n",
3014 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303015 goto exit;
3016 }
3017
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003018 param_hdr.param_id = AFE_PARAM_ID_USB_AUDIO_DEV_LPCM_FMT;
3019 param_hdr.param_size = sizeof(lpcm_fmt);
Garmond Leung6b3f4182018-05-11 12:29:34 -07003020 lpcm_fmt.cfg_minor_version = AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003021 lpcm_fmt.endian = afe_config->usb_audio.endian;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303022
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003023 ret = q6afe_pack_and_set_param_in_band(port_id,
3024 q6audio_get_port_index(port_id),
3025 param_hdr, (u8 *) &lpcm_fmt);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303026 if (ret) {
3027 pr_err("%s: AFE device param cmd LPCM_FMT failed %d\n",
3028 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303029 goto exit;
3030 }
Garmond Leung6b3f4182018-05-11 12:29:34 -07003031 param_hdr.param_id = AFE_PARAM_ID_USB_AUDIO_SVC_INTERVAL;
3032 param_hdr.param_size = sizeof(svc_int);
3033 svc_int.cfg_minor_version =
3034 AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG;
3035 svc_int.svc_interval = afe_config->usb_audio.service_interval;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303036
Garmond Leung6b3f4182018-05-11 12:29:34 -07003037 pr_debug("%s: AFE device param cmd sending SVC_INTERVAL %d\n",
3038 __func__, svc_int.svc_interval);
3039
3040 ret = q6afe_pack_and_set_param_in_band(port_id,
3041 q6audio_get_port_index(port_id),
3042 param_hdr, (u8 *) &svc_int);
3043
3044 if (ret) {
3045 pr_err("%s: AFE device param cmd svc_interval failed %d\n",
3046 __func__, ret);
3047 ret = -EINVAL;
3048 goto exit;
3049 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303050exit:
3051 return ret;
3052}
3053
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003054static int q6afe_send_dec_config(u16 port_id,
3055 union afe_port_config afe_config,
3056 struct afe_dec_config *cfg)
3057{
3058 struct avs_dec_depacketizer_id_param_t dec_depkt_id_param;
3059 struct afe_enc_dec_imc_info_param_t imc_info_param;
3060 struct afe_port_media_type_t media_type;
3061 struct param_hdr_v3 param_hdr;
3062 int ret;
3063
3064 memset(&dec_depkt_id_param, 0, sizeof(dec_depkt_id_param));
3065 memset(&imc_info_param, 0, sizeof(imc_info_param));
3066 memset(&media_type, 0, sizeof(media_type));
3067 memset(&param_hdr, 0, sizeof(param_hdr));
3068
3069 param_hdr.module_id = AFE_MODULE_ID_DECODER;
3070 param_hdr.instance_id = INSTANCE_ID_0;
3071
3072 pr_debug("%s: sending AFE_DECODER_PARAM_ID_DEPACKETIZER to DSP payload\n",
3073 __func__);
3074 param_hdr.param_id = AFE_DECODER_PARAM_ID_DEPACKETIZER_ID;
3075 param_hdr.param_size = sizeof(struct avs_dec_depacketizer_id_param_t);
3076 dec_depkt_id_param.dec_depacketizer_id =
3077 AFE_MODULE_ID_DEPACKETIZER_COP;
3078 ret = q6afe_pack_and_set_param_in_band(port_id,
3079 q6audio_get_port_index(port_id),
3080 param_hdr,
3081 (u8 *) &dec_depkt_id_param);
3082 if (ret) {
3083 pr_err("%s: AFE_DECODER_PARAM_ID_DEPACKETIZER for port 0x%x failed %d\n",
3084 __func__, port_id, ret);
3085 goto exit;
3086 }
3087
3088 pr_debug("%s:sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload\n",
3089 __func__);
3090 param_hdr.param_id = AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION;
3091 param_hdr.param_size = sizeof(struct afe_enc_dec_imc_info_param_t);
3092 imc_info_param.imc_info = cfg->abr_dec_cfg.imc_info;
3093 ret = q6afe_pack_and_set_param_in_band(port_id,
3094 q6audio_get_port_index(port_id),
3095 param_hdr,
3096 (u8 *) &imc_info_param);
3097 if (ret) {
3098 pr_err("%s: AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION for port 0x%x failed %d\n",
3099 __func__, port_id, ret);
3100 goto exit;
3101 }
3102
3103 pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP", __func__);
3104 param_hdr.module_id = AFE_MODULE_PORT;
3105 param_hdr.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
3106 param_hdr.param_size = sizeof(struct afe_port_media_type_t);
3107 media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
3108 media_type.sample_rate = afe_config.slim_sch.sample_rate;
3109 media_type.bit_width = afe_config.slim_sch.bit_width;
3110 media_type.num_channels = afe_config.slim_sch.num_channels;
3111 media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
3112 media_type.reserved = 0;
3113
3114 ret = q6afe_pack_and_set_param_in_band(port_id,
3115 q6audio_get_port_index(port_id),
3116 param_hdr, (u8 *) &media_type);
3117 if (ret) {
3118 pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
3119 __func__, port_id, ret);
3120 goto exit;
3121 }
3122
3123exit:
3124 return ret;
3125}
3126
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303127static int q6afe_send_enc_config(u16 port_id,
3128 union afe_enc_config_data *cfg, u32 format,
3129 union afe_port_config afe_config,
Preetam Singh Ranawatf746a872017-10-20 18:13:14 +05303130 u16 afe_in_channels, u16 afe_in_bit_width,
3131 u32 scrambler_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303132{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003133 u32 enc_fmt;
3134 struct afe_enc_cfg_blk_param_t enc_blk_param;
3135 struct afe_param_id_aptx_sync_mode sync_mode_param;
3136 struct avs_enc_packetizer_id_param_t enc_pkt_id_param;
3137 struct avs_enc_set_scrambler_param_t enc_set_scrambler_param;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003138 struct afe_enc_level_to_bitrate_map_param_t map_param;
3139 struct afe_enc_dec_imc_info_param_t imc_info_param;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003140 struct afe_port_media_type_t media_type;
3141 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303142 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303143
3144 pr_debug("%s:update DSP for enc format = %d\n", __func__, format);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003145
3146 memset(&enc_blk_param, 0, sizeof(enc_blk_param));
3147 memset(&sync_mode_param, 0, sizeof(sync_mode_param));
3148 memset(&enc_pkt_id_param, 0, sizeof(enc_pkt_id_param));
3149 memset(&enc_set_scrambler_param, 0, sizeof(enc_set_scrambler_param));
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003150 memset(&map_param, 0, sizeof(map_param));
3151 memset(&imc_info_param, 0, sizeof(imc_info_param));
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003152 memset(&media_type, 0, sizeof(media_type));
3153 memset(&param_hdr, 0, sizeof(param_hdr));
3154
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303155 if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 &&
Preetam Singh Ranawat54028492017-09-04 11:42:26 +05303156 format != ASM_MEDIA_FMT_APTX && format != ASM_MEDIA_FMT_APTX_HD &&
Preetam Singh Ranawat0a087af2017-10-25 15:02:28 +05303157 format != ASM_MEDIA_FMT_CELT && format != ASM_MEDIA_FMT_LDAC) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303158 pr_err("%s:Unsuppported format Ignore AFE config\n", __func__);
3159 return 0;
3160 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303161
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003162 param_hdr.module_id = AFE_MODULE_ID_ENCODER;
3163 param_hdr.instance_id = INSTANCE_ID_0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303164
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003165 param_hdr.param_id = AFE_ENCODER_PARAM_ID_ENC_FMT_ID;
3166 param_hdr.param_size = sizeof(enc_fmt);
3167 enc_fmt = format;
3168 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENC_FMT_ID payload\n",
3169 __func__);
3170 ret = q6afe_pack_and_set_param_in_band(port_id,
3171 q6audio_get_port_index(port_id),
3172 param_hdr, (u8 *) &enc_fmt);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303173 if (ret) {
3174 pr_err("%s:unable to send AFE_ENCODER_PARAM_ID_ENC_FMT_ID",
3175 __func__);
3176 goto exit;
3177 }
3178
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003179 if (format == ASM_MEDIA_FMT_LDAC) {
3180 param_hdr.param_size = sizeof(struct afe_enc_cfg_blk_param_t)
3181 - sizeof(struct afe_abr_enc_cfg_t);
3182 enc_blk_param.enc_cfg_blk_size =
3183 sizeof(union afe_enc_config_data)
3184 - sizeof(struct afe_abr_enc_cfg_t);
3185 } else {
3186 param_hdr.param_size = sizeof(struct afe_enc_cfg_blk_param_t);
3187 enc_blk_param.enc_cfg_blk_size =
3188 sizeof(union afe_enc_config_data);
3189 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003190 pr_debug("%s:send AFE_ENCODER_PARAM_ID_ENC_CFG_BLK to DSP payloadn",
3191 __func__);
3192 param_hdr.param_id = AFE_ENCODER_PARAM_ID_ENC_CFG_BLK;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003193 enc_blk_param.enc_blk_config = *cfg;
3194 ret = q6afe_pack_and_set_param_in_band(port_id,
3195 q6audio_get_port_index(port_id),
3196 param_hdr,
3197 (u8 *) &enc_blk_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303198 if (ret) {
3199 pr_err("%s: AFE_ENCODER_PARAM_ID_ENC_CFG_BLK for port 0x%x failed %d\n",
3200 __func__, port_id, ret);
3201 goto exit;
3202 }
3203
Preetam Singh Ranawat899b78b2017-09-07 12:36:06 -07003204 if (format == ASM_MEDIA_FMT_APTX) {
Preetam Singh Ranawat899b78b2017-09-07 12:36:06 -07003205 pr_debug("%s: sending AFE_PARAM_ID_APTX_SYNC_MODE to DSP",
3206 __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003207 param_hdr.param_id = AFE_PARAM_ID_APTX_SYNC_MODE;
3208 param_hdr.param_size =
3209 sizeof(struct afe_param_id_aptx_sync_mode);
3210 sync_mode_param.sync_mode =
3211 enc_blk_param.enc_blk_config.aptx_config.
Preetam Singh Ranawat899b78b2017-09-07 12:36:06 -07003212 aptx_v2_cfg.sync_mode;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003213 ret = q6afe_pack_and_set_param_in_band(port_id,
3214 q6audio_get_port_index(port_id),
3215 param_hdr,
3216 (u8 *) &sync_mode_param);
Preetam Singh Ranawat899b78b2017-09-07 12:36:06 -07003217 if (ret) {
3218 pr_err("%s: AFE_PARAM_ID_APTX_SYNC_MODE for port 0x%x failed %d\n",
3219 __func__, port_id, ret);
3220 goto exit;
3221 }
3222 }
3223
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003224 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_PACKETIZER to DSP\n",
3225 __func__);
3226 param_hdr.param_id = AFE_ENCODER_PARAM_ID_PACKETIZER_ID;
3227 param_hdr.param_size = sizeof(struct avs_enc_packetizer_id_param_t);
3228 enc_pkt_id_param.enc_packetizer_id = AFE_MODULE_ID_PACKETIZER_COP;
3229 ret = q6afe_pack_and_set_param_in_band(port_id,
3230 q6audio_get_port_index(port_id),
3231 param_hdr,
3232 (u8 *) &enc_pkt_id_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303233 if (ret) {
3234 pr_err("%s: AFE_ENCODER_PARAM_ID_PACKETIZER for port 0x%x failed %d\n",
3235 __func__, port_id, ret);
3236 goto exit;
3237 }
3238
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003239 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING mode= %d to DSP payload\n",
3240 __func__, scrambler_mode);
3241 param_hdr.param_id = AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING;
3242 param_hdr.param_size = sizeof(struct avs_enc_set_scrambler_param_t);
3243 enc_set_scrambler_param.enable_scrambler = scrambler_mode;
3244 ret = q6afe_pack_and_set_param_in_band(port_id,
3245 q6audio_get_port_index(port_id),
3246 param_hdr,
3247 (u8 *) &enc_set_scrambler_param);
Preetam Singh Ranawatf746a872017-10-20 18:13:14 +05303248 if (ret) {
3249 pr_err("%s: AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING for port 0x%x failed %d\n",
3250 __func__, port_id, ret);
3251 goto exit;
3252 }
3253
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003254 if (format == ASM_MEDIA_FMT_LDAC) {
3255 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP to DSP payload",
3256 __func__);
3257 param_hdr.param_id = AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP;
3258 param_hdr.param_size =
3259 sizeof(struct afe_enc_level_to_bitrate_map_param_t);
3260 map_param.mapping_table =
3261 cfg->ldac_config.abr_config.mapping_info;
3262 ret = q6afe_pack_and_set_param_in_band(port_id,
3263 q6audio_get_port_index(port_id),
3264 param_hdr,
3265 (u8 *) &map_param);
3266 if (ret) {
3267 pr_err("%s: AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP for port 0x%x failed %d\n",
3268 __func__, port_id, ret);
3269 goto exit;
3270 }
3271
3272 pr_debug("%s: sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload",
3273 __func__);
3274 param_hdr.param_id =
3275 AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION;
3276 param_hdr.param_size =
3277 sizeof(struct afe_enc_dec_imc_info_param_t);
3278 imc_info_param.imc_info =
3279 cfg->ldac_config.abr_config.imc_info;
3280 ret = q6afe_pack_and_set_param_in_band(port_id,
3281 q6audio_get_port_index(port_id),
3282 param_hdr,
3283 (u8 *) &imc_info_param);
3284 if (ret) {
3285 pr_err("%s: AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION for port 0x%x failed %d\n",
3286 __func__, port_id, ret);
3287 goto exit;
3288 }
3289 }
3290
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303291 pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP", __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003292 param_hdr.module_id = AFE_MODULE_PORT;
3293 param_hdr.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
3294 param_hdr.param_size = sizeof(struct afe_port_media_type_t);
3295 media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003296 if (format == ASM_MEDIA_FMT_LDAC)
3297 media_type.sample_rate =
3298 cfg->ldac_config.custom_config.sample_rate;
3299 else
3300 media_type.sample_rate =
3301 afe_config.slim_sch.sample_rate;
3302
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303303 if (afe_in_bit_width)
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003304 media_type.bit_width = afe_in_bit_width;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303305 else
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003306 media_type.bit_width = afe_config.slim_sch.bit_width;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303307
3308 if (afe_in_channels)
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003309 media_type.num_channels = afe_in_channels;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303310 else
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003311 media_type.num_channels = afe_config.slim_sch.num_channels;
3312 media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
3313 media_type.reserved = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303314
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003315 ret = q6afe_pack_and_set_param_in_band(port_id,
3316 q6audio_get_port_index(port_id),
3317 param_hdr, (u8 *) &media_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303318 if (ret) {
3319 pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
3320 __func__, port_id, ret);
3321 goto exit;
3322 }
3323
3324exit:
3325 return ret;
3326}
3327
3328static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
3329 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003330 union afe_enc_config_data *enc_cfg,
3331 u32 codec_format, u32 scrambler_mode,
3332 struct afe_dec_config *dec_cfg)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303333{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003334 union afe_port_config port_cfg;
3335 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303336 int ret = 0;
3337 int cfg_type;
3338 int index = 0;
3339 enum afe_mad_type mad_type;
3340 uint16_t port_index;
3341
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003342 memset(&param_hdr, 0, sizeof(param_hdr));
3343 memset(&port_cfg, 0, sizeof(port_cfg));
3344
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303345 if (!afe_config) {
3346 pr_err("%s: Error, no configuration data\n", __func__);
3347 ret = -EINVAL;
3348 return ret;
3349 }
3350
3351 if ((port_id == RT_PROXY_DAI_001_RX) ||
3352 (port_id == RT_PROXY_DAI_002_TX)) {
3353 pr_debug("%s: before incrementing pcm_afe_instance %d port_id 0x%x\n",
3354 __func__,
3355 pcm_afe_instance[port_id & 0x1], port_id);
3356 port_id = VIRTUAL_ID_TO_PORTID(port_id);
3357 pcm_afe_instance[port_id & 0x1]++;
3358 return 0;
3359 }
3360 if ((port_id == RT_PROXY_DAI_002_RX) ||
3361 (port_id == RT_PROXY_DAI_001_TX)) {
3362 pr_debug("%s: before incrementing proxy_afe_instance %d port_id 0x%x\n",
3363 __func__,
3364 proxy_afe_instance[port_id & 0x1], port_id);
3365
3366 if (!afe_close_done[port_id & 0x1]) {
3367 /*close pcm dai corresponding to the proxy dai*/
3368 afe_close(port_id - 0x10);
3369 pcm_afe_instance[port_id & 0x1]++;
3370 pr_debug("%s: reconfigure afe port again\n", __func__);
3371 }
3372 proxy_afe_instance[port_id & 0x1]++;
3373 afe_close_done[port_id & 0x1] = false;
3374 port_id = VIRTUAL_ID_TO_PORTID(port_id);
3375 }
3376
3377 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
3378
3379 index = q6audio_get_port_index(port_id);
3380 if (index < 0 || index >= AFE_MAX_PORTS) {
3381 pr_err("%s: AFE port index[%d] invalid!\n",
3382 __func__, index);
3383 return -EINVAL;
3384 }
3385 ret = q6audio_validate_port(port_id);
3386 if (ret < 0) {
3387 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
3388 return -EINVAL;
3389 }
3390
3391 ret = afe_q6_interface_prepare();
3392 if (ret != 0) {
3393 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3394 return ret;
3395 }
3396
3397 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
3398 this_afe.afe_sample_rates[index] = rate;
3399
3400 if (this_afe.rt_cb)
3401 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
3402 }
3403
3404 mutex_lock(&this_afe.afe_cmd_lock);
3405 /* Also send the topology id here: */
3406 port_index = afe_get_port_index(port_id);
3407 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
3408 /* One time call: only for first time */
3409 afe_send_custom_topology();
3410 afe_send_port_topology_id(port_id);
3411 afe_send_cal(port_id);
3412 afe_send_hw_delay(port_id, rate);
3413 }
3414
3415 /* Start SW MAD module */
3416 mad_type = afe_port_get_mad_type(port_id);
3417 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
3418 mad_type);
3419 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
3420 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
3421 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
3422 pr_err("%s: AFE isn't configured yet for\n"
3423 "HW MAD try Again\n", __func__);
3424 ret = -EAGAIN;
3425 goto fail_cmd;
3426 }
3427 ret = afe_turn_onoff_hw_mad(mad_type, true);
3428 if (ret) {
3429 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
3430 __func__, ret);
3431 goto fail_cmd;
3432 }
3433 }
3434
3435 if ((this_afe.aanc_info.aanc_active) &&
3436 (this_afe.aanc_info.aanc_tx_port == port_id)) {
3437 this_afe.aanc_info.aanc_tx_port_sample_rate = rate;
3438 port_index =
3439 afe_get_port_index(this_afe.aanc_info.aanc_rx_port);
3440 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3441 this_afe.aanc_info.aanc_rx_port_sample_rate =
3442 this_afe.afe_sample_rates[port_index];
3443 } else {
3444 pr_err("%s: Invalid port index %d\n",
3445 __func__, port_index);
3446 ret = -EINVAL;
3447 goto fail_cmd;
3448 }
3449 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
3450 this_afe.aanc_info.aanc_rx_port);
3451 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
3452 }
3453
3454 if ((port_id == AFE_PORT_ID_USB_RX) ||
3455 (port_id == AFE_PORT_ID_USB_TX)) {
3456 ret = afe_port_send_usb_dev_param(port_id, afe_config);
3457 if (ret) {
3458 pr_err("%s: AFE device param for port 0x%x failed %d\n",
3459 __func__, port_id, ret);
3460 ret = -EINVAL;
3461 goto fail_cmd;
3462 }
3463 }
3464
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303465 switch (port_id) {
3466 case AFE_PORT_ID_PRIMARY_PCM_RX:
3467 case AFE_PORT_ID_PRIMARY_PCM_TX:
3468 case AFE_PORT_ID_SECONDARY_PCM_RX:
3469 case AFE_PORT_ID_SECONDARY_PCM_TX:
3470 case AFE_PORT_ID_TERTIARY_PCM_RX:
3471 case AFE_PORT_ID_TERTIARY_PCM_TX:
3472 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3473 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303474 case AFE_PORT_ID_QUINARY_PCM_RX:
3475 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303476 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
3477 break;
3478 case PRIMARY_I2S_RX:
3479 case PRIMARY_I2S_TX:
3480 case SECONDARY_I2S_RX:
3481 case SECONDARY_I2S_TX:
3482 case MI2S_RX:
3483 case MI2S_TX:
3484 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3485 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3486 case AFE_PORT_ID_SECONDARY_MI2S_RX:
3487 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
3488 case AFE_PORT_ID_SECONDARY_MI2S_TX:
3489 case AFE_PORT_ID_TERTIARY_MI2S_RX:
3490 case AFE_PORT_ID_TERTIARY_MI2S_TX:
3491 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3492 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3493 case AFE_PORT_ID_QUINARY_MI2S_RX:
3494 case AFE_PORT_ID_QUINARY_MI2S_TX:
3495 case AFE_PORT_ID_SENARY_MI2S_TX:
3496 case AFE_PORT_ID_INT0_MI2S_RX:
3497 case AFE_PORT_ID_INT0_MI2S_TX:
3498 case AFE_PORT_ID_INT1_MI2S_RX:
3499 case AFE_PORT_ID_INT1_MI2S_TX:
3500 case AFE_PORT_ID_INT2_MI2S_RX:
3501 case AFE_PORT_ID_INT2_MI2S_TX:
3502 case AFE_PORT_ID_INT3_MI2S_RX:
3503 case AFE_PORT_ID_INT3_MI2S_TX:
3504 case AFE_PORT_ID_INT4_MI2S_RX:
3505 case AFE_PORT_ID_INT4_MI2S_TX:
3506 case AFE_PORT_ID_INT5_MI2S_RX:
3507 case AFE_PORT_ID_INT5_MI2S_TX:
3508 case AFE_PORT_ID_INT6_MI2S_RX:
3509 case AFE_PORT_ID_INT6_MI2S_TX:
3510 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
3511 break;
3512 case HDMI_RX:
3513 case DISPLAY_PORT_RX:
3514 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
3515 break;
3516 case VOICE_PLAYBACK_TX:
3517 case VOICE2_PLAYBACK_TX:
3518 case VOICE_RECORD_RX:
3519 case VOICE_RECORD_TX:
3520 cfg_type = AFE_PARAM_ID_PSEUDO_PORT_CONFIG;
3521 break;
3522 case SLIMBUS_0_RX:
3523 case SLIMBUS_0_TX:
3524 case SLIMBUS_1_RX:
3525 case SLIMBUS_1_TX:
3526 case SLIMBUS_2_RX:
3527 case SLIMBUS_2_TX:
3528 case SLIMBUS_3_RX:
3529 case SLIMBUS_3_TX:
3530 case SLIMBUS_4_RX:
3531 case SLIMBUS_4_TX:
3532 case SLIMBUS_5_RX:
3533 case SLIMBUS_5_TX:
3534 case SLIMBUS_6_RX:
3535 case SLIMBUS_6_TX:
3536 case SLIMBUS_7_RX:
3537 case SLIMBUS_7_TX:
3538 case SLIMBUS_8_RX:
3539 case SLIMBUS_8_TX:
3540 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
3541 break;
3542 case AFE_PORT_ID_USB_RX:
3543 case AFE_PORT_ID_USB_TX:
3544 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
3545 break;
3546 case RT_PROXY_PORT_001_RX:
3547 case RT_PROXY_PORT_001_TX:
3548 cfg_type = AFE_PARAM_ID_RT_PROXY_CONFIG;
3549 break;
3550 case INT_BT_SCO_RX:
3551 case INT_BT_A2DP_RX:
3552 case INT_BT_SCO_TX:
3553 case INT_FM_RX:
3554 case INT_FM_TX:
3555 cfg_type = AFE_PARAM_ID_INTERNAL_BT_FM_CONFIG;
3556 break;
3557 default:
3558 pr_err("%s: Invalid port id 0x%x\n", __func__, port_id);
3559 ret = -EINVAL;
3560 goto fail_cmd;
3561 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303562
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003563 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3564 param_hdr.instance_id = INSTANCE_ID_0;
3565 param_hdr.param_id = cfg_type;
3566 param_hdr.param_size = sizeof(union afe_port_config);
3567
3568 port_cfg = *afe_config;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003569 if (((enc_cfg != NULL) || (dec_cfg != NULL)) &&
3570 (codec_format != ASM_MEDIA_FMT_NONE) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303571 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003572 port_cfg.slim_sch.data_format =
3573 AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303574 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003575 ret = q6afe_pack_and_set_param_in_band(port_id,
3576 q6audio_get_port_index(port_id),
3577 param_hdr, (u8 *) &port_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303578 if (ret) {
3579 pr_err("%s: AFE enable for port 0x%x failed %d\n",
3580 __func__, port_id, ret);
3581 goto fail_cmd;
3582 }
3583
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003584 if ((codec_format != ASM_MEDIA_FMT_NONE) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303585 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003586 if (enc_cfg != NULL) {
3587 pr_debug("%s: Found AFE encoder support for SLIMBUS format = %d\n",
3588 __func__, codec_format);
3589 ret = q6afe_send_enc_config(port_id, enc_cfg,
3590 codec_format, *afe_config,
3591 afe_in_channels,
3592 afe_in_bit_width,
3593 scrambler_mode);
3594 if (ret) {
3595 pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
3596 __func__, port_id, ret);
3597 goto fail_cmd;
3598 }
3599 }
3600 if (dec_cfg != NULL) {
3601 pr_debug("%s: Found AFE decoder support for SLIMBUS format = %d\n",
3602 __func__, codec_format);
3603 ret = q6afe_send_dec_config(port_id, *afe_config,
3604 dec_cfg);
3605 if (ret) {
3606 pr_err("%s: AFE decoder config for port 0x%x failed %d\n",
3607 __func__, port_id, ret);
3608 goto fail_cmd;
3609 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303610 }
3611 }
3612
3613 port_index = afe_get_port_index(port_id);
3614 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3615 /*
3616 * If afe_port_start() for tx port called before
3617 * rx port, then aanc rx sample rate is zero. So,
3618 * AANC state machine in AFE will not get triggered.
3619 * Make sure to check whether aanc is active during
3620 * afe_port_start() for rx port and if aanc rx
3621 * sample rate is zero, call afe_aanc_start to configure
3622 * aanc with valid sample rates.
3623 */
3624 if (this_afe.aanc_info.aanc_active &&
3625 !this_afe.aanc_info.aanc_rx_port_sample_rate) {
3626 this_afe.aanc_info.aanc_rx_port_sample_rate =
3627 this_afe.afe_sample_rates[port_index];
3628 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
3629 this_afe.aanc_info.aanc_rx_port);
3630 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
3631 }
3632 } else {
3633 pr_err("%s: Invalid port index %d\n", __func__, port_index);
3634 ret = -EINVAL;
3635 goto fail_cmd;
3636 }
3637 ret = afe_send_cmd_port_start(port_id);
3638
3639fail_cmd:
3640 mutex_unlock(&this_afe.afe_cmd_lock);
3641 return ret;
3642}
3643
3644/**
3645 * afe_port_start - to configure AFE session with
3646 * specified port configuration
3647 *
3648 * @port_id: AFE port id number
3649 * @afe_config: port configutation
3650 * @rate: sampling rate of port
3651 *
3652 * Returns 0 on success or error value on port start failure.
3653 */
3654int afe_port_start(u16 port_id, union afe_port_config *afe_config,
3655 u32 rate)
3656{
3657 return __afe_port_start(port_id, afe_config, rate,
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003658 0, 0, NULL, ASM_MEDIA_FMT_NONE, 0, NULL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303659}
3660EXPORT_SYMBOL(afe_port_start);
3661
3662/**
3663 * afe_port_start_v2 - to configure AFE session with
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003664 * specified port configuration and encoder /decoder params
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303665 *
3666 * @port_id: AFE port id number
3667 * @afe_config: port configutation
3668 * @rate: sampling rate of port
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003669 * @enc_cfg: AFE enc configuration information to setup encoder
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303670 * @afe_in_channels: AFE input channel configuration, this needs
3671 * update only if input channel is differ from AFE output
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003672 * @dec_cfg: AFE dec configuration information to set up decoder
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303673 *
3674 * Returns 0 on success or error value on port start failure.
3675 */
3676int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
3677 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003678 struct afe_enc_config *enc_cfg,
3679 struct afe_dec_config *dec_cfg)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303680{
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003681 int ret = 0;
3682
3683 if (enc_cfg != NULL)
3684 ret = __afe_port_start(port_id, afe_config, rate,
3685 afe_in_channels, afe_in_bit_width,
3686 &enc_cfg->data, enc_cfg->format,
3687 enc_cfg->scrambler_mode, dec_cfg);
3688 else if (dec_cfg != NULL)
3689 ret = __afe_port_start(port_id, afe_config, rate,
3690 afe_in_channels, afe_in_bit_width,
3691 NULL, dec_cfg->format, 0, dec_cfg);
3692
3693 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303694}
3695EXPORT_SYMBOL(afe_port_start_v2);
3696
3697int afe_get_port_index(u16 port_id)
3698{
3699 switch (port_id) {
3700 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
3701 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
3702 case AFE_PORT_ID_PRIMARY_PCM_RX:
3703 return IDX_AFE_PORT_ID_PRIMARY_PCM_RX;
3704 case AFE_PORT_ID_PRIMARY_PCM_TX:
3705 return IDX_AFE_PORT_ID_PRIMARY_PCM_TX;
3706 case AFE_PORT_ID_SECONDARY_PCM_RX:
3707 return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
3708 case AFE_PORT_ID_SECONDARY_PCM_TX:
3709 return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
3710 case AFE_PORT_ID_TERTIARY_PCM_RX:
3711 return IDX_AFE_PORT_ID_TERTIARY_PCM_RX;
3712 case AFE_PORT_ID_TERTIARY_PCM_TX:
3713 return IDX_AFE_PORT_ID_TERTIARY_PCM_TX;
3714 case AFE_PORT_ID_QUATERNARY_PCM_RX:
3715 return IDX_AFE_PORT_ID_QUATERNARY_PCM_RX;
3716 case AFE_PORT_ID_QUATERNARY_PCM_TX:
3717 return IDX_AFE_PORT_ID_QUATERNARY_PCM_TX;
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303718 case AFE_PORT_ID_QUINARY_PCM_RX:
3719 return IDX_AFE_PORT_ID_QUINARY_PCM_RX;
3720 case AFE_PORT_ID_QUINARY_PCM_TX:
3721 return IDX_AFE_PORT_ID_QUINARY_PCM_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303722 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
3723 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
3724 case MI2S_RX: return IDX_MI2S_RX;
3725 case MI2S_TX: return IDX_MI2S_TX;
3726 case HDMI_RX: return IDX_HDMI_RX;
3727 case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX;
3728 case AFE_PORT_ID_SPDIF_RX: return IDX_SPDIF_RX;
3729 case RSVD_2: return IDX_RSVD_2;
3730 case RSVD_3: return IDX_RSVD_3;
3731 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
3732 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
3733 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
3734 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
3735 case VOICE2_PLAYBACK_TX: return IDX_VOICE2_PLAYBACK_TX;
3736 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
3737 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
3738 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
3739 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
3740 case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
3741 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
3742 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
3743 case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
3744 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
3745 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
3746 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
3747 case INT_FM_RX: return IDX_INT_FM_RX;
3748 case INT_FM_TX: return IDX_INT_FM_TX;
3749 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
3750 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
3751 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
3752 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
3753 case SLIMBUS_5_RX: return IDX_SLIMBUS_5_RX;
3754 case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX;
3755 case SLIMBUS_6_RX: return IDX_SLIMBUS_6_RX;
3756 case SLIMBUS_6_TX: return IDX_SLIMBUS_6_TX;
3757 case SLIMBUS_7_RX: return IDX_SLIMBUS_7_RX;
3758 case SLIMBUS_7_TX: return IDX_SLIMBUS_7_TX;
3759 case SLIMBUS_8_RX: return IDX_SLIMBUS_8_RX;
3760 case SLIMBUS_8_TX: return IDX_SLIMBUS_8_TX;
3761 case AFE_PORT_ID_USB_RX: return IDX_AFE_PORT_ID_USB_RX;
3762 case AFE_PORT_ID_USB_TX: return IDX_AFE_PORT_ID_USB_TX;
3763 case AFE_PORT_ID_PRIMARY_MI2S_RX:
3764 return IDX_AFE_PORT_ID_PRIMARY_MI2S_RX;
3765 case AFE_PORT_ID_PRIMARY_MI2S_TX:
3766 return IDX_AFE_PORT_ID_PRIMARY_MI2S_TX;
3767 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
3768 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
3769 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
3770 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX;
3771 case AFE_PORT_ID_SECONDARY_MI2S_RX:
3772 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX;
3773 case AFE_PORT_ID_SECONDARY_MI2S_TX:
3774 return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX;
3775 case AFE_PORT_ID_TERTIARY_MI2S_RX:
3776 return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX;
3777 case AFE_PORT_ID_TERTIARY_MI2S_TX:
3778 return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX;
3779 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
3780 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_SD1;
3781 case AFE_PORT_ID_QUINARY_MI2S_RX:
3782 return IDX_AFE_PORT_ID_QUINARY_MI2S_RX;
3783 case AFE_PORT_ID_QUINARY_MI2S_TX:
3784 return IDX_AFE_PORT_ID_QUINARY_MI2S_TX;
3785 case AFE_PORT_ID_SENARY_MI2S_TX:
3786 return IDX_AFE_PORT_ID_SENARY_MI2S_TX;
3787 case AFE_PORT_ID_PRIMARY_TDM_RX:
3788 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_0;
3789 case AFE_PORT_ID_PRIMARY_TDM_TX:
3790 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_0;
3791 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
3792 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_1;
3793 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
3794 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_1;
3795 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
3796 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_2;
3797 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
3798 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_2;
3799 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
3800 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_3;
3801 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
3802 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_3;
3803 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
3804 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_4;
3805 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
3806 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_4;
3807 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
3808 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_5;
3809 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
3810 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_5;
3811 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
3812 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_6;
3813 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
3814 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_6;
3815 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
3816 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_7;
3817 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
3818 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_7;
3819 case AFE_PORT_ID_SECONDARY_TDM_RX:
3820 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_0;
3821 case AFE_PORT_ID_SECONDARY_TDM_TX:
3822 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_0;
3823 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
3824 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_1;
3825 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
3826 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_1;
3827 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
3828 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_2;
3829 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
3830 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_2;
3831 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
3832 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_3;
3833 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
3834 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_3;
3835 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
3836 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_4;
3837 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
3838 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_4;
3839 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
3840 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_5;
3841 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
3842 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_5;
3843 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
3844 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_6;
3845 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
3846 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_6;
3847 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
3848 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_7;
3849 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
3850 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_7;
3851 case AFE_PORT_ID_TERTIARY_TDM_RX:
3852 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_0;
3853 case AFE_PORT_ID_TERTIARY_TDM_TX:
3854 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_0;
3855 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
3856 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_1;
3857 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
3858 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_1;
3859 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
3860 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_2;
3861 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
3862 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_2;
3863 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
3864 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_3;
3865 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
3866 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_3;
3867 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
3868 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_4;
3869 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
3870 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_4;
3871 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
3872 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_5;
3873 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
3874 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_5;
3875 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
3876 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_6;
3877 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
3878 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_6;
3879 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
3880 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_7;
3881 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
3882 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_7;
3883 case AFE_PORT_ID_QUATERNARY_TDM_RX:
3884 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_0;
3885 case AFE_PORT_ID_QUATERNARY_TDM_TX:
3886 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_0;
3887 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
3888 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_1;
3889 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
3890 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_1;
3891 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
3892 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_2;
3893 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
3894 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_2;
3895 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
3896 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_3;
3897 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
3898 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_3;
3899 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
3900 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_4;
3901 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
3902 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_4;
3903 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
3904 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_5;
3905 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
3906 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_5;
3907 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
3908 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_6;
3909 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
3910 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_6;
3911 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
3912 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_7;
3913 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
3914 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_7;
Rohit Kumarc08b14f2017-10-06 10:52:17 +05303915 case AFE_PORT_ID_QUINARY_TDM_RX:
3916 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_0;
3917 case AFE_PORT_ID_QUINARY_TDM_TX:
3918 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_0;
3919 case AFE_PORT_ID_QUINARY_TDM_RX_1:
3920 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_1;
3921 case AFE_PORT_ID_QUINARY_TDM_TX_1:
3922 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_1;
3923 case AFE_PORT_ID_QUINARY_TDM_RX_2:
3924 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_2;
3925 case AFE_PORT_ID_QUINARY_TDM_TX_2:
3926 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_2;
3927 case AFE_PORT_ID_QUINARY_TDM_RX_3:
3928 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_3;
3929 case AFE_PORT_ID_QUINARY_TDM_TX_3:
3930 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_3;
3931 case AFE_PORT_ID_QUINARY_TDM_RX_4:
3932 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_4;
3933 case AFE_PORT_ID_QUINARY_TDM_TX_4:
3934 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_4;
3935 case AFE_PORT_ID_QUINARY_TDM_RX_5:
3936 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_5;
3937 case AFE_PORT_ID_QUINARY_TDM_TX_5:
3938 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_5;
3939 case AFE_PORT_ID_QUINARY_TDM_RX_6:
3940 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_6;
3941 case AFE_PORT_ID_QUINARY_TDM_TX_6:
3942 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_6;
3943 case AFE_PORT_ID_QUINARY_TDM_RX_7:
3944 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_7;
3945 case AFE_PORT_ID_QUINARY_TDM_TX_7:
3946 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_7;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303947 case AFE_PORT_ID_INT0_MI2S_RX:
3948 return IDX_AFE_PORT_ID_INT0_MI2S_RX;
3949 case AFE_PORT_ID_INT0_MI2S_TX:
3950 return IDX_AFE_PORT_ID_INT0_MI2S_TX;
3951 case AFE_PORT_ID_INT1_MI2S_RX:
3952 return IDX_AFE_PORT_ID_INT1_MI2S_RX;
3953 case AFE_PORT_ID_INT1_MI2S_TX:
3954 return IDX_AFE_PORT_ID_INT1_MI2S_TX;
3955 case AFE_PORT_ID_INT2_MI2S_RX:
3956 return IDX_AFE_PORT_ID_INT2_MI2S_RX;
3957 case AFE_PORT_ID_INT2_MI2S_TX:
3958 return IDX_AFE_PORT_ID_INT2_MI2S_TX;
3959 case AFE_PORT_ID_INT3_MI2S_RX:
3960 return IDX_AFE_PORT_ID_INT3_MI2S_RX;
3961 case AFE_PORT_ID_INT3_MI2S_TX:
3962 return IDX_AFE_PORT_ID_INT3_MI2S_TX;
3963 case AFE_PORT_ID_INT4_MI2S_RX:
3964 return IDX_AFE_PORT_ID_INT4_MI2S_RX;
3965 case AFE_PORT_ID_INT4_MI2S_TX:
3966 return IDX_AFE_PORT_ID_INT4_MI2S_TX;
3967 case AFE_PORT_ID_INT5_MI2S_RX:
3968 return IDX_AFE_PORT_ID_INT5_MI2S_RX;
3969 case AFE_PORT_ID_INT5_MI2S_TX:
3970 return IDX_AFE_PORT_ID_INT5_MI2S_TX;
3971 case AFE_PORT_ID_INT6_MI2S_RX:
3972 return IDX_AFE_PORT_ID_INT6_MI2S_RX;
3973 case AFE_PORT_ID_INT6_MI2S_TX:
3974 return IDX_AFE_PORT_ID_INT6_MI2S_TX;
3975 default:
3976 pr_err("%s: port 0x%x\n", __func__, port_id);
3977 return -EINVAL;
3978 }
3979}
3980
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303981/**
3982 * afe_open -
3983 * command to open AFE port
3984 *
3985 * @port_id: AFE port id
3986 * @afe_config: AFE port config to pass
3987 * @rate: sample rate
3988 *
3989 * Returns 0 on success or error on failure
3990 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303991int afe_open(u16 port_id,
3992 union afe_port_config *afe_config, int rate)
3993{
3994 struct afe_port_cmd_device_start start;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003995 union afe_port_config port_cfg;
3996 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303997 int ret = 0;
3998 int cfg_type;
3999 int index = 0;
4000
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004001 memset(&param_hdr, 0, sizeof(param_hdr));
4002 memset(&start, 0, sizeof(start));
4003 memset(&port_cfg, 0, sizeof(port_cfg));
4004
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304005 if (!afe_config) {
4006 pr_err("%s: Error, no configuration data\n", __func__);
4007 ret = -EINVAL;
4008 return ret;
4009 }
4010
4011 pr_err("%s: port_id 0x%x rate %d\n", __func__, port_id, rate);
4012
4013 index = q6audio_get_port_index(port_id);
4014 if (index < 0 || index >= AFE_MAX_PORTS) {
4015 pr_err("%s: AFE port index[%d] invalid!\n",
4016 __func__, index);
4017 return -EINVAL;
4018 }
4019 ret = q6audio_validate_port(port_id);
4020 if (ret < 0) {
4021 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
4022 return -EINVAL;
4023 }
4024
4025 if ((port_id == RT_PROXY_DAI_001_RX) ||
4026 (port_id == RT_PROXY_DAI_002_TX)) {
4027 pr_err("%s: wrong port 0x%x\n", __func__, port_id);
4028 return -EINVAL;
4029 }
4030 if ((port_id == RT_PROXY_DAI_002_RX) ||
4031 (port_id == RT_PROXY_DAI_001_TX))
4032 port_id = VIRTUAL_ID_TO_PORTID(port_id);
4033
4034 ret = afe_q6_interface_prepare();
4035 if (ret != 0) {
4036 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4037 return -EINVAL;
4038 }
4039
4040 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
4041 this_afe.afe_sample_rates[index] = rate;
4042
4043 if (this_afe.rt_cb)
4044 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
4045 }
4046
4047 /* Also send the topology id here: */
4048 afe_send_custom_topology(); /* One time call: only for first time */
4049 afe_send_port_topology_id(port_id);
4050
4051 ret = q6audio_validate_port(port_id);
4052 if (ret < 0) {
4053 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
4054 __func__, port_id, ret);
4055 return -EINVAL;
4056 }
4057 mutex_lock(&this_afe.afe_cmd_lock);
4058
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304059 switch (port_id) {
4060 case PRIMARY_I2S_RX:
4061 case PRIMARY_I2S_TX:
4062 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
4063 break;
4064 case AFE_PORT_ID_PRIMARY_PCM_RX:
4065 case AFE_PORT_ID_PRIMARY_PCM_TX:
4066 case AFE_PORT_ID_SECONDARY_PCM_RX:
4067 case AFE_PORT_ID_SECONDARY_PCM_TX:
4068 case AFE_PORT_ID_TERTIARY_PCM_RX:
4069 case AFE_PORT_ID_TERTIARY_PCM_TX:
4070 case AFE_PORT_ID_QUATERNARY_PCM_RX:
4071 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304072 case AFE_PORT_ID_QUINARY_PCM_RX:
4073 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304074 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
4075 break;
4076 case SECONDARY_I2S_RX:
4077 case SECONDARY_I2S_TX:
4078 case AFE_PORT_ID_PRIMARY_MI2S_RX:
4079 case AFE_PORT_ID_PRIMARY_MI2S_TX:
4080 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
4081 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
4082 case MI2S_RX:
4083 case MI2S_TX:
4084 case AFE_PORT_ID_QUINARY_MI2S_RX:
4085 case AFE_PORT_ID_QUINARY_MI2S_TX:
4086 case AFE_PORT_ID_SENARY_MI2S_TX:
4087 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
4088 break;
4089 case HDMI_RX:
4090 case DISPLAY_PORT_RX:
4091 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
4092 break;
4093 case SLIMBUS_0_RX:
4094 case SLIMBUS_0_TX:
4095 case SLIMBUS_1_RX:
4096 case SLIMBUS_1_TX:
4097 case SLIMBUS_2_RX:
4098 case SLIMBUS_2_TX:
4099 case SLIMBUS_3_RX:
4100 case SLIMBUS_3_TX:
4101 case SLIMBUS_4_RX:
4102 case SLIMBUS_4_TX:
4103 case SLIMBUS_5_RX:
4104 case SLIMBUS_6_RX:
4105 case SLIMBUS_6_TX:
4106 case SLIMBUS_7_RX:
4107 case SLIMBUS_7_TX:
4108 case SLIMBUS_8_RX:
4109 case SLIMBUS_8_TX:
4110 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
4111 break;
4112 case AFE_PORT_ID_USB_RX:
4113 case AFE_PORT_ID_USB_TX:
4114 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
4115 break;
4116 default:
4117 pr_err("%s: Invalid port id 0x%x\n",
4118 __func__, port_id);
4119 ret = -EINVAL;
4120 goto fail_cmd;
4121 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304122
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004123 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
4124 param_hdr.instance_id = INSTANCE_ID_0;
4125 param_hdr.param_id = cfg_type;
4126 param_hdr.param_size = sizeof(union afe_port_config);
4127 port_cfg = *afe_config;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304128
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004129 ret = q6afe_pack_and_set_param_in_band(port_id,
4130 q6audio_get_port_index(port_id),
4131 param_hdr, (u8 *) &port_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304132 if (ret) {
4133 pr_err("%s: AFE enable for port 0x%x opcode[0x%x]failed %d\n",
4134 __func__, port_id, cfg_type, ret);
4135 goto fail_cmd;
4136 }
4137 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4138 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4139 start.hdr.pkt_size = sizeof(start);
4140 start.hdr.src_port = 0;
4141 start.hdr.dest_port = 0;
4142 start.hdr.token = index;
4143 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
4144 start.port_id = q6audio_get_port_id(port_id);
4145 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
4146 __func__, start.hdr.opcode, start.port_id);
4147
4148 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
4149 if (ret) {
4150 pr_err("%s: AFE enable for port 0x%x failed %d\n", __func__,
4151 port_id, ret);
4152 goto fail_cmd;
4153 }
4154
4155fail_cmd:
4156 mutex_unlock(&this_afe.afe_cmd_lock);
4157 return ret;
4158}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304159EXPORT_SYMBOL(afe_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304160
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304161/**
4162 * afe_loopback -
4163 * command to set loopback between AFE ports
4164 *
4165 * @enable: enable or disable loopback
4166 * @rx_port: AFE RX port ID
4167 * @tx_port: AFE TX port ID
4168 *
4169 * Returns 0 on success or error on failure
4170 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304171int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
4172{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004173 struct afe_loopback_cfg_v1 lb_param;
4174 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304175 int ret = 0;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004176
4177 memset(&lb_param, 0, sizeof(lb_param));
4178 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304179
4180 if (rx_port == MI2S_RX)
4181 rx_port = AFE_PORT_ID_PRIMARY_MI2S_RX;
4182 if (tx_port == MI2S_TX)
4183 tx_port = AFE_PORT_ID_PRIMARY_MI2S_TX;
4184
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004185 param_hdr.module_id = AFE_MODULE_LOOPBACK;
4186 param_hdr.instance_id = INSTANCE_ID_0;
4187 param_hdr.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
4188 param_hdr.param_size = sizeof(struct afe_loopback_cfg_v1);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304189
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004190 lb_param.dst_port_id = rx_port;
4191 lb_param.routing_mode = LB_MODE_DEFAULT;
4192 lb_param.enable = (enable ? 1 : 0);
4193 lb_param.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304194
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004195 ret = q6afe_pack_and_set_param_in_band(tx_port,
4196 q6audio_get_port_index(tx_port),
4197 param_hdr, (u8 *) &lb_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304198 if (ret)
4199 pr_err("%s: AFE loopback failed %d\n", __func__, ret);
4200 return ret;
4201}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304202EXPORT_SYMBOL(afe_loopback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304203
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304204/**
4205 * afe_loopback_gain -
4206 * command to set gain for AFE loopback
4207 *
4208 * @port_id: AFE port id
4209 * @volume: gain value to set
4210 *
4211 * Returns 0 on success or error on failure
4212 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304213int afe_loopback_gain(u16 port_id, u16 volume)
4214{
4215 struct afe_loopback_gain_per_path_param set_param;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004216 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304217 int ret = 0;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004218
4219 memset(&set_param, 0, sizeof(set_param));
4220 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304221
4222 if (this_afe.apr == NULL) {
4223 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4224 0xFFFFFFFF, &this_afe);
4225 pr_debug("%s: Register AFE\n", __func__);
4226 if (this_afe.apr == NULL) {
4227 pr_err("%s: Unable to register AFE\n", __func__);
4228 ret = -ENODEV;
4229 return ret;
4230 }
4231 rtac_set_afe_handle(this_afe.apr);
4232 }
4233
4234 ret = q6audio_validate_port(port_id);
4235 if (ret < 0) {
4236 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
4237 __func__, port_id, ret);
4238 ret = -EINVAL;
4239 goto fail_cmd;
4240 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304241
4242 /* RX ports numbers are even .TX ports numbers are odd. */
4243 if (port_id % 2 == 0) {
4244 pr_err("%s: Failed : afe loopback gain only for TX ports. port_id %d\n",
4245 __func__, port_id);
4246 ret = -EINVAL;
4247 goto fail_cmd;
4248 }
4249
4250 pr_debug("%s: port 0x%x volume %d\n", __func__, port_id, volume);
4251
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004252 param_hdr.module_id = AFE_MODULE_LOOPBACK;
4253 param_hdr.instance_id = INSTANCE_ID_0;
4254 param_hdr.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
4255 param_hdr.param_size = sizeof(struct afe_loopback_gain_per_path_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304256 set_param.rx_port_id = port_id;
4257 set_param.gain = volume;
4258
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004259 ret = q6afe_pack_and_set_param_in_band(port_id,
4260 q6audio_get_port_index(port_id),
4261 param_hdr, (u8 *) &set_param);
4262 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304263 pr_err("%s: AFE param set failed for port 0x%x ret %d\n",
4264 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304265
4266fail_cmd:
4267 return ret;
4268}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304269EXPORT_SYMBOL(afe_loopback_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304270
4271int afe_pseudo_port_start_nowait(u16 port_id)
4272{
4273 struct afe_pseudoport_start_command start;
4274 int ret = 0;
4275
4276 pr_debug("%s: port_id=0x%x\n", __func__, port_id);
4277 if (this_afe.apr == NULL) {
4278 pr_err("%s: AFE APR is not registered\n", __func__);
4279 return -ENODEV;
4280 }
4281
4282
4283 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4284 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4285 start.hdr.pkt_size = sizeof(start);
4286 start.hdr.src_port = 0;
4287 start.hdr.dest_port = 0;
4288 start.hdr.token = 0;
4289 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
4290 start.port_id = port_id;
4291 start.timing = 1;
4292
4293 ret = afe_apr_send_pkt(&start, NULL);
4294 if (ret) {
4295 pr_err("%s: AFE enable for port 0x%x failed %d\n",
4296 __func__, port_id, ret);
4297 return ret;
4298 }
4299 return 0;
4300}
4301
4302int afe_start_pseudo_port(u16 port_id)
4303{
4304 int ret = 0;
4305 struct afe_pseudoport_start_command start;
4306 int index = 0;
4307
4308 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4309
4310 ret = afe_q6_interface_prepare();
4311 if (ret != 0) {
4312 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4313 return ret;
4314 }
4315
4316 index = q6audio_get_port_index(port_id);
4317 if (index < 0 || index >= AFE_MAX_PORTS) {
4318 pr_err("%s: AFE port index[%d] invalid!\n",
4319 __func__, index);
4320 return -EINVAL;
4321 }
4322 ret = q6audio_validate_port(port_id);
4323 if (ret < 0) {
4324 pr_err("%s: Invalid port 0x%x ret %d",
4325 __func__, port_id, ret);
4326 return -EINVAL;
4327 }
4328
4329 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4330 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4331 start.hdr.pkt_size = sizeof(start);
4332 start.hdr.src_port = 0;
4333 start.hdr.dest_port = 0;
4334 start.hdr.token = 0;
4335 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
4336 start.port_id = port_id;
4337 start.timing = 1;
4338 start.hdr.token = index;
4339
4340 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
4341 if (ret)
4342 pr_err("%s: AFE enable for port 0x%x failed %d\n",
4343 __func__, port_id, ret);
4344 return ret;
4345}
4346
4347int afe_pseudo_port_stop_nowait(u16 port_id)
4348{
4349 int ret = 0;
4350 struct afe_pseudoport_stop_command stop;
4351 int index = 0;
4352
4353 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4354
4355 if (this_afe.apr == NULL) {
4356 pr_err("%s: AFE is already closed\n", __func__);
4357 return -EINVAL;
4358 }
4359 index = q6audio_get_port_index(port_id);
4360 if (index < 0 || index >= AFE_MAX_PORTS) {
4361 pr_err("%s: AFE port index[%d] invalid!\n",
4362 __func__, index);
4363 return -EINVAL;
4364 }
4365 ret = q6audio_validate_port(port_id);
4366 if (ret < 0) {
4367 pr_err("%s: Invalid port 0x%x ret %d",
4368 __func__, port_id, ret);
4369 return -EINVAL;
4370 }
4371
4372 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4373 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4374 stop.hdr.pkt_size = sizeof(stop);
4375 stop.hdr.src_port = 0;
4376 stop.hdr.dest_port = 0;
4377 stop.hdr.token = 0;
4378 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
4379 stop.port_id = port_id;
4380 stop.reserved = 0;
4381 stop.hdr.token = index;
4382
4383 ret = afe_apr_send_pkt(&stop, NULL);
4384 if (ret)
4385 pr_err("%s: AFE close failed %d\n", __func__, ret);
4386
4387 return ret;
4388}
4389
4390int afe_port_group_set_param(u16 group_id,
4391 union afe_port_group_config *afe_group_config)
4392{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004393 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304394 int cfg_type;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004395 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304396
4397 if (!afe_group_config) {
4398 pr_err("%s: Error, no configuration data\n", __func__);
4399 return -EINVAL;
4400 }
4401
4402 pr_debug("%s: group id: 0x%x\n", __func__, group_id);
4403
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004404 memset(&param_hdr, 0, sizeof(param_hdr));
4405
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304406 ret = afe_q6_interface_prepare();
4407 if (ret != 0) {
4408 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4409 return ret;
4410 }
4411
4412 switch (group_id) {
4413 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX:
4414 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX:
4415 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_RX:
4416 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_TX:
4417 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_RX:
4418 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_TX:
4419 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_RX:
4420 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304421 case AFE_GROUP_DEVICE_ID_QUINARY_TDM_RX:
4422 case AFE_GROUP_DEVICE_ID_QUINARY_TDM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304423 cfg_type = AFE_PARAM_ID_GROUP_DEVICE_TDM_CONFIG;
4424 break;
4425 default:
4426 pr_err("%s: Invalid group id 0x%x\n", __func__, group_id);
4427 return -EINVAL;
4428 }
4429
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004430 param_hdr.module_id = AFE_MODULE_GROUP_DEVICE;
4431 param_hdr.instance_id = INSTANCE_ID_0;
4432 param_hdr.param_id = cfg_type;
4433 param_hdr.param_size = sizeof(union afe_port_group_config);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304434
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004435 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
4436 (u8 *) afe_group_config);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304437 if (ret)
4438 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_CFG failed %d\n",
4439 __func__, ret);
4440
4441 return ret;
4442}
4443
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304444/**
4445 * afe_port_group_enable -
4446 * command to enable AFE port group
4447 *
4448 * @group_id: group ID for AFE port group
4449 * @afe_group_config: config for AFE group
4450 * @enable: flag to indicate enable or disable
4451 *
4452 * Returns 0 on success or error on failure
4453 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304454int afe_port_group_enable(u16 group_id,
4455 union afe_port_group_config *afe_group_config,
4456 u16 enable)
4457{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004458 struct afe_group_device_enable group_enable;
4459 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304460 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304461
4462 pr_debug("%s: group id: 0x%x enable: %d\n", __func__,
4463 group_id, enable);
4464
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004465 memset(&group_enable, 0, sizeof(group_enable));
4466 memset(&param_hdr, 0, sizeof(param_hdr));
4467
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304468 ret = afe_q6_interface_prepare();
4469 if (ret != 0) {
4470 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4471 return ret;
4472 }
4473
4474 if (enable) {
4475 ret = afe_port_group_set_param(group_id, afe_group_config);
4476 if (ret < 0) {
4477 pr_err("%s: afe send failed %d\n", __func__, ret);
4478 return ret;
4479 }
4480 }
4481
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004482 param_hdr.module_id = AFE_MODULE_GROUP_DEVICE;
4483 param_hdr.instance_id = INSTANCE_ID_0;
4484 param_hdr.param_id = AFE_PARAM_ID_GROUP_DEVICE_ENABLE;
4485 param_hdr.param_size = sizeof(struct afe_group_device_enable);
4486 group_enable.group_id = group_id;
4487 group_enable.enable = enable;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304488
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004489 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
4490 (u8 *) &group_enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304491 if (ret)
4492 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_ENABLE failed %d\n",
4493 __func__, ret);
4494
4495 return ret;
4496}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304497EXPORT_SYMBOL(afe_port_group_enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304498
4499int afe_stop_pseudo_port(u16 port_id)
4500{
4501 int ret = 0;
4502 struct afe_pseudoport_stop_command stop;
4503 int index = 0;
4504
4505 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
4506
4507 if (this_afe.apr == NULL) {
4508 pr_err("%s: AFE is already closed\n", __func__);
4509 return -EINVAL;
4510 }
4511
4512 index = q6audio_get_port_index(port_id);
4513 if (index < 0 || index >= AFE_MAX_PORTS) {
4514 pr_err("%s: AFE port index[%d] invalid!\n",
4515 __func__, index);
4516 return -EINVAL;
4517 }
4518 ret = q6audio_validate_port(port_id);
4519 if (ret < 0) {
4520 pr_err("%s: Invalid port 0x%x ret %d\n",
4521 __func__, port_id, ret);
4522 return -EINVAL;
4523 }
4524
4525 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4526 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4527 stop.hdr.pkt_size = sizeof(stop);
4528 stop.hdr.src_port = 0;
4529 stop.hdr.dest_port = 0;
4530 stop.hdr.token = 0;
4531 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
4532 stop.port_id = port_id;
4533 stop.reserved = 0;
4534 stop.hdr.token = index;
4535
4536 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
4537 if (ret)
4538 pr_err("%s: AFE close failed %d\n", __func__, ret);
4539
4540 return ret;
4541}
4542
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304543/**
4544 * afe_req_mmap_handle -
4545 * Retrieve AFE memory map handle
4546 *
4547 * @ac: AFE audio client
4548 *
4549 * Returns memory map handle
4550 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304551uint32_t afe_req_mmap_handle(struct afe_audio_client *ac)
4552{
4553 return ac->mem_map_handle;
4554}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304555EXPORT_SYMBOL(afe_req_mmap_handle);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304556
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304557/**
4558 * q6afe_audio_client_alloc -
4559 * Assign new AFE audio client
4560 *
4561 * @priv: privata data to hold for audio client
4562 *
4563 * Returns ac pointer on success or NULL on failure
4564 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304565struct afe_audio_client *q6afe_audio_client_alloc(void *priv)
4566{
4567 struct afe_audio_client *ac;
4568 int lcnt = 0;
4569
4570 ac = kzalloc(sizeof(struct afe_audio_client), GFP_KERNEL);
4571 if (!ac)
4572 return NULL;
4573
4574 ac->priv = priv;
4575
4576 init_waitqueue_head(&ac->cmd_wait);
4577 INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
4578 INIT_LIST_HEAD(&ac->port[1].mem_map_handle);
4579 pr_debug("%s: mem_map_handle list init'ed\n", __func__);
4580 mutex_init(&ac->cmd_lock);
4581 for (lcnt = 0; lcnt <= OUT; lcnt++) {
4582 mutex_init(&ac->port[lcnt].lock);
4583 spin_lock_init(&ac->port[lcnt].dsp_lock);
4584 }
4585 atomic_set(&ac->cmd_state, 0);
4586
4587 return ac;
4588}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304589EXPORT_SYMBOL(q6afe_audio_client_alloc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304590
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304591/**
4592 * q6afe_audio_client_buf_alloc_contiguous -
4593 * Allocate contiguous shared buffers
4594 *
4595 * @dir: RX or TX direction of AFE port
4596 * @ac: AFE audio client handle
4597 * @bufsz: size of each shared buffer
4598 * @bufcnt: number of buffers
4599 *
4600 * Returns 0 on success or error on failure
4601 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304602int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir,
4603 struct afe_audio_client *ac,
4604 unsigned int bufsz,
4605 unsigned int bufcnt)
4606{
4607 int cnt = 0;
4608 int rc = 0;
4609 struct afe_audio_buffer *buf;
4610 size_t len;
4611
4612 if (!(ac) || ((dir != IN) && (dir != OUT))) {
4613 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
4614 return -EINVAL;
4615 }
4616
4617 pr_debug("%s: bufsz[%d]bufcnt[%d]\n",
4618 __func__,
4619 bufsz, bufcnt);
4620
4621 if (ac->port[dir].buf) {
4622 pr_debug("%s: buffer already allocated\n", __func__);
4623 return 0;
4624 }
4625 mutex_lock(&ac->cmd_lock);
4626 buf = kzalloc(((sizeof(struct afe_audio_buffer))*bufcnt),
4627 GFP_KERNEL);
4628
4629 if (!buf) {
4630 pr_err("%s: null buf\n", __func__);
4631 mutex_unlock(&ac->cmd_lock);
4632 goto fail;
4633 }
4634
4635 ac->port[dir].buf = buf;
4636
Banajit Goswami08bb7362017-11-03 22:48:23 -07004637 rc = msm_audio_ion_alloc(&buf[0].dma_buf,
4638 bufsz * bufcnt,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304639 &buf[0].phys, &len,
4640 &buf[0].data);
4641 if (rc) {
4642 pr_err("%s: audio ION alloc failed, rc = %d\n",
4643 __func__, rc);
4644 mutex_unlock(&ac->cmd_lock);
4645 goto fail;
4646 }
4647
4648 buf[0].used = dir ^ 1;
4649 buf[0].size = bufsz;
4650 buf[0].actual_size = bufsz;
4651 cnt = 1;
4652 while (cnt < bufcnt) {
4653 if (bufsz > 0) {
4654 buf[cnt].data = buf[0].data + (cnt * bufsz);
4655 buf[cnt].phys = buf[0].phys + (cnt * bufsz);
4656 if (!buf[cnt].data) {
4657 pr_err("%s: Buf alloc failed\n",
4658 __func__);
4659 mutex_unlock(&ac->cmd_lock);
4660 goto fail;
4661 }
4662 buf[cnt].used = dir ^ 1;
4663 buf[cnt].size = bufsz;
4664 buf[cnt].actual_size = bufsz;
4665 pr_debug("%s: data[%pK]phys[%pK][%pK]\n", __func__,
4666 buf[cnt].data,
4667 &buf[cnt].phys,
4668 &buf[cnt].phys);
4669 }
4670 cnt++;
4671 }
4672 ac->port[dir].max_buf_cnt = cnt;
4673 mutex_unlock(&ac->cmd_lock);
4674 return 0;
4675fail:
4676 pr_err("%s: jump fail\n", __func__);
4677 q6afe_audio_client_buf_free_contiguous(dir, ac);
4678 return -EINVAL;
4679}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304680EXPORT_SYMBOL(q6afe_audio_client_buf_alloc_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304681
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304682/**
4683 * afe_memory_map -
4684 * command to map shared buffers to AFE
4685 *
4686 * @dma_addr_p: DMA physical address
4687 * @dma_buf_sz: shared DMA buffer size
4688 * @ac: AFE audio client handle
4689 *
4690 * Returns 0 on success or error on failure
4691 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304692int afe_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz,
4693 struct afe_audio_client *ac)
4694{
4695 int ret = 0;
4696
4697 mutex_lock(&this_afe.afe_cmd_lock);
4698 ac->mem_map_handle = 0;
4699 ret = afe_cmd_memory_map(dma_addr_p, dma_buf_sz);
4700 if (ret < 0) {
4701 pr_err("%s: afe_cmd_memory_map failed %d\n",
4702 __func__, ret);
4703
4704 mutex_unlock(&this_afe.afe_cmd_lock);
4705 return ret;
4706 }
4707 ac->mem_map_handle = this_afe.mmap_handle;
4708 mutex_unlock(&this_afe.afe_cmd_lock);
4709
4710 return ret;
4711}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304712EXPORT_SYMBOL(afe_memory_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304713
4714int afe_cmd_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz)
4715{
4716 int ret = 0;
4717 int cmd_size = 0;
4718 void *payload = NULL;
4719 void *mmap_region_cmd = NULL;
4720 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
4721 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
4722 int index = 0;
4723
4724 pr_debug("%s:\n", __func__);
4725
4726 if (this_afe.apr == NULL) {
4727 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4728 0xFFFFFFFF, &this_afe);
4729 pr_debug("%s: Register AFE\n", __func__);
4730 if (this_afe.apr == NULL) {
4731 pr_err("%s: Unable to register AFE\n", __func__);
4732 ret = -ENODEV;
4733 return ret;
4734 }
4735 rtac_set_afe_handle(this_afe.apr);
4736 }
4737 if (dma_buf_sz % SZ_4K != 0) {
4738 /*
4739 * The memory allocated by msm_audio_ion_alloc is always 4kB
4740 * aligned, ADSP expects the size to be 4kB aligned as well
4741 * so re-adjusts the buffer size before passing to ADSP.
4742 */
4743 dma_buf_sz = PAGE_ALIGN(dma_buf_sz);
4744 }
4745
4746 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
4747 + sizeof(struct afe_service_shared_map_region_payload);
4748
4749 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
4750 if (!mmap_region_cmd)
4751 return -ENOMEM;
4752
4753 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
4754 mmap_region_cmd;
4755 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4756 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4757 mregion->hdr.pkt_size = cmd_size;
4758 mregion->hdr.src_port = 0;
4759 mregion->hdr.dest_port = 0;
4760 mregion->hdr.token = 0;
4761 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
4762 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
4763 mregion->num_regions = 1;
4764 mregion->property_flag = 0x00;
4765 /* Todo */
4766 index = mregion->hdr.token = IDX_RSVD_2;
4767
4768 payload = ((u8 *) mmap_region_cmd +
4769 sizeof(struct afe_service_cmd_shared_mem_map_regions));
4770
4771 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
4772
4773 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
4774 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
4775 mregion_pl->mem_size_bytes = dma_buf_sz;
4776
4777 pr_debug("%s: dma_addr_p 0x%pK , size %d\n", __func__,
4778 &dma_addr_p, dma_buf_sz);
4779 atomic_set(&this_afe.state, 1);
4780 atomic_set(&this_afe.status, 0);
4781 this_afe.mmap_handle = 0;
4782 ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
4783 if (ret < 0) {
4784 pr_err("%s: AFE memory map cmd failed %d\n",
4785 __func__, ret);
4786 ret = -EINVAL;
4787 goto fail_cmd;
4788 }
4789
4790 ret = wait_event_timeout(this_afe.wait[index],
4791 (atomic_read(&this_afe.state) == 0),
4792 msecs_to_jiffies(TIMEOUT_MS));
4793 if (!ret) {
4794 pr_err("%s: wait_event timeout\n", __func__);
4795 ret = -EINVAL;
4796 goto fail_cmd;
4797 }
4798 if (atomic_read(&this_afe.status) > 0) {
4799 pr_err("%s: config cmd failed [%s]\n",
4800 __func__, adsp_err_get_err_str(
4801 atomic_read(&this_afe.status)));
4802 ret = adsp_err_get_lnx_err_code(
4803 atomic_read(&this_afe.status));
4804 goto fail_cmd;
4805 }
4806
4807 kfree(mmap_region_cmd);
4808 return 0;
4809fail_cmd:
4810 kfree(mmap_region_cmd);
4811 pr_err("%s: fail_cmd\n", __func__);
4812 return ret;
4813}
4814
4815int afe_cmd_memory_map_nowait(int port_id, phys_addr_t dma_addr_p,
4816 u32 dma_buf_sz)
4817{
4818 int ret = 0;
4819 int cmd_size = 0;
4820 void *payload = NULL;
4821 void *mmap_region_cmd = NULL;
4822 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
4823 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
4824 int index = 0;
4825
4826 pr_debug("%s:\n", __func__);
4827
4828 if (this_afe.apr == NULL) {
4829 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4830 0xFFFFFFFF, &this_afe);
4831 pr_debug("%s: Register AFE\n", __func__);
4832 if (this_afe.apr == NULL) {
4833 pr_err("%s: Unable to register AFE\n", __func__);
4834 ret = -ENODEV;
4835 return ret;
4836 }
4837 rtac_set_afe_handle(this_afe.apr);
4838 }
4839 index = q6audio_get_port_index(port_id);
4840 if (index < 0 || index >= AFE_MAX_PORTS) {
4841 pr_err("%s: AFE port index[%d] invalid!\n",
4842 __func__, index);
4843 return -EINVAL;
4844 }
4845 ret = q6audio_validate_port(port_id);
4846 if (ret < 0) {
4847 pr_err("%s: Invalid port 0x%x ret %d",
4848 __func__, port_id, ret);
4849 return -EINVAL;
4850 }
4851
4852 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
4853 + sizeof(struct afe_service_shared_map_region_payload);
4854
4855 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
4856 if (!mmap_region_cmd)
4857 return -ENOMEM;
4858
4859 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
4860 mmap_region_cmd;
4861 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4862 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4863 mregion->hdr.pkt_size = sizeof(mregion);
4864 mregion->hdr.src_port = 0;
4865 mregion->hdr.dest_port = 0;
4866 mregion->hdr.token = 0;
4867 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
4868 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
4869 mregion->num_regions = 1;
4870 mregion->property_flag = 0x00;
4871
4872 payload = ((u8 *) mmap_region_cmd +
4873 sizeof(struct afe_service_cmd_shared_mem_map_regions));
4874 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
4875
4876 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
4877 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
4878 mregion_pl->mem_size_bytes = dma_buf_sz;
4879
4880 ret = afe_apr_send_pkt(mmap_region_cmd, NULL);
4881 if (ret)
4882 pr_err("%s: AFE memory map cmd failed %d\n",
4883 __func__, ret);
4884 kfree(mmap_region_cmd);
4885 return ret;
4886}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304887
4888/**
4889 * q6afe_audio_client_buf_free_contiguous -
4890 * frees the shared contiguous memory
4891 *
4892 * @dir: RX or TX direction of port
4893 * @ac: AFE audio client handle
4894 *
4895 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304896int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
4897 struct afe_audio_client *ac)
4898{
4899 struct afe_audio_port_data *port;
4900 int cnt = 0;
4901
4902 mutex_lock(&ac->cmd_lock);
4903 port = &ac->port[dir];
4904 if (!port->buf) {
4905 pr_err("%s: buf is null\n", __func__);
4906 mutex_unlock(&ac->cmd_lock);
4907 return 0;
4908 }
4909 cnt = port->max_buf_cnt - 1;
4910
4911 if (port->buf[0].data) {
Banajit Goswami08bb7362017-11-03 22:48:23 -07004912 pr_debug("%s: data[%pK], phys[%pK], dma_buf[%pK]\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304913 __func__,
4914 port->buf[0].data,
4915 &port->buf[0].phys,
Banajit Goswami08bb7362017-11-03 22:48:23 -07004916 port->buf[0].dma_buf);
4917 msm_audio_ion_free(port->buf[0].dma_buf);
4918 port->buf[0].dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304919 }
4920
4921 while (cnt >= 0) {
4922 port->buf[cnt].data = NULL;
4923 port->buf[cnt].phys = 0;
4924 cnt--;
4925 }
4926 port->max_buf_cnt = 0;
4927 kfree(port->buf);
4928 port->buf = NULL;
4929 mutex_unlock(&ac->cmd_lock);
4930 return 0;
4931}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304932EXPORT_SYMBOL(q6afe_audio_client_buf_free_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304933
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304934/**
4935 * q6afe_audio_client_free -
4936 * frees the audio client from AFE
4937 *
4938 * @ac: AFE audio client handle
4939 *
4940 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304941void q6afe_audio_client_free(struct afe_audio_client *ac)
4942{
4943 int loopcnt;
4944 struct afe_audio_port_data *port;
4945
4946 if (!ac) {
4947 pr_err("%s: audio client is NULL\n", __func__);
4948 return;
4949 }
4950 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
4951 port = &ac->port[loopcnt];
4952 if (!port->buf)
4953 continue;
4954 pr_debug("%s: loopcnt = %d\n", __func__, loopcnt);
4955 q6afe_audio_client_buf_free_contiguous(loopcnt, ac);
4956 }
4957 kfree(ac);
4958}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304959EXPORT_SYMBOL(q6afe_audio_client_free);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304960
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304961/**
4962 * afe_cmd_memory_unmap -
4963 * command to unmap memory for AFE shared buffer
4964 *
4965 * @mem_map_handle: memory map handle to be unmapped
4966 *
4967 * Returns 0 on success or error on failure
4968 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304969int afe_cmd_memory_unmap(u32 mem_map_handle)
4970{
4971 int ret = 0;
4972 struct afe_service_cmd_shared_mem_unmap_regions mregion;
4973 int index = 0;
4974
4975 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
4976
4977 if (this_afe.apr == NULL) {
4978 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
4979 0xFFFFFFFF, &this_afe);
4980 pr_debug("%s: Register AFE\n", __func__);
4981 if (this_afe.apr == NULL) {
4982 pr_err("%s: Unable to register AFE\n", __func__);
4983 ret = -ENODEV;
4984 return ret;
4985 }
4986 rtac_set_afe_handle(this_afe.apr);
4987 }
4988
4989 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4990 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4991 mregion.hdr.pkt_size = sizeof(mregion);
4992 mregion.hdr.src_port = 0;
4993 mregion.hdr.dest_port = 0;
4994 mregion.hdr.token = 0;
4995 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
4996 mregion.mem_map_handle = mem_map_handle;
4997
4998 /* Todo */
4999 index = mregion.hdr.token = IDX_RSVD_2;
5000
5001 atomic_set(&this_afe.status, 0);
5002 ret = afe_apr_send_pkt(&mregion, &this_afe.wait[index]);
5003 if (ret)
5004 pr_err("%s: AFE memory unmap cmd failed %d\n",
5005 __func__, ret);
5006
5007 return ret;
5008}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305009EXPORT_SYMBOL(afe_cmd_memory_unmap);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305010
5011int afe_cmd_memory_unmap_nowait(u32 mem_map_handle)
5012{
5013 int ret = 0;
5014 struct afe_service_cmd_shared_mem_unmap_regions mregion;
5015
5016 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
5017
5018 if (this_afe.apr == NULL) {
5019 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5020 0xFFFFFFFF, &this_afe);
5021 pr_debug("%s: Register AFE\n", __func__);
5022 if (this_afe.apr == NULL) {
5023 pr_err("%s: Unable to register AFE\n", __func__);
5024 ret = -ENODEV;
5025 return ret;
5026 }
5027 rtac_set_afe_handle(this_afe.apr);
5028 }
5029
5030 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5031 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5032 mregion.hdr.pkt_size = sizeof(mregion);
5033 mregion.hdr.src_port = 0;
5034 mregion.hdr.dest_port = 0;
5035 mregion.hdr.token = 0;
5036 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
5037 mregion.mem_map_handle = mem_map_handle;
5038
5039 ret = afe_apr_send_pkt(&mregion, NULL);
5040 if (ret)
5041 pr_err("%s: AFE memory unmap cmd failed %d\n",
5042 __func__, ret);
5043 return ret;
5044}
5045
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305046/**
5047 * afe_register_get_events -
5048 * register for events from proxy port
5049 *
5050 * @port_id: Port ID to register events
5051 * @cb: callback function to invoke for events from proxy port
5052 * @private_data: private data to sent back in callback fn
5053 *
5054 * Returns 0 on success or error on failure
5055 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305056int afe_register_get_events(u16 port_id,
5057 void (*cb)(uint32_t opcode,
5058 uint32_t token, uint32_t *payload, void *priv),
5059 void *private_data)
5060{
5061 int ret = 0;
5062 struct afe_service_cmd_register_rt_port_driver rtproxy;
5063
5064 pr_debug("%s: port_id: 0x%x\n", __func__, port_id);
5065
5066 if (this_afe.apr == NULL) {
5067 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5068 0xFFFFFFFF, &this_afe);
5069 pr_debug("%s: Register AFE\n", __func__);
5070 if (this_afe.apr == NULL) {
5071 pr_err("%s: Unable to register AFE\n", __func__);
5072 ret = -ENODEV;
5073 return ret;
5074 }
5075 rtac_set_afe_handle(this_afe.apr);
5076 }
5077 if ((port_id == RT_PROXY_DAI_002_RX) ||
5078 (port_id == RT_PROXY_DAI_001_TX)) {
5079 port_id = VIRTUAL_ID_TO_PORTID(port_id);
5080 } else {
5081 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
5082 return -EINVAL;
5083 }
5084
5085 if (port_id == RT_PROXY_PORT_001_TX) {
5086 this_afe.tx_cb = cb;
5087 this_afe.tx_private_data = private_data;
5088 } else if (port_id == RT_PROXY_PORT_001_RX) {
5089 this_afe.rx_cb = cb;
5090 this_afe.rx_private_data = private_data;
5091 }
5092
5093 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5094 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5095 rtproxy.hdr.pkt_size = sizeof(rtproxy);
5096 rtproxy.hdr.src_port = 1;
5097 rtproxy.hdr.dest_port = 1;
5098 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER;
5099 rtproxy.port_id = port_id;
5100 rtproxy.reserved = 0;
5101
5102 ret = afe_apr_send_pkt(&rtproxy, NULL);
5103 if (ret)
5104 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
5105 __func__, ret);
5106 return ret;
5107}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305108EXPORT_SYMBOL(afe_register_get_events);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305109
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305110/**
5111 * afe_unregister_get_events -
5112 * unregister for events from proxy port
5113 *
5114 * @port_id: Port ID to unregister events
5115 *
5116 * Returns 0 on success or error on failure
5117 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305118int afe_unregister_get_events(u16 port_id)
5119{
5120 int ret = 0;
5121 struct afe_service_cmd_unregister_rt_port_driver rtproxy;
5122 int index = 0;
5123
5124 pr_debug("%s:\n", __func__);
5125
5126 if (this_afe.apr == NULL) {
5127 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5128 0xFFFFFFFF, &this_afe);
5129 pr_debug("%s: Register AFE\n", __func__);
5130 if (this_afe.apr == NULL) {
5131 pr_err("%s: Unable to register AFE\n", __func__);
5132 ret = -ENODEV;
5133 return ret;
5134 }
5135 rtac_set_afe_handle(this_afe.apr);
5136 }
5137
5138 if ((port_id == RT_PROXY_DAI_002_RX) ||
5139 (port_id == RT_PROXY_DAI_001_TX)) {
5140 port_id = VIRTUAL_ID_TO_PORTID(port_id);
5141 } else {
5142 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
5143 return -EINVAL;
5144 }
5145
5146 index = q6audio_get_port_index(port_id);
5147 if (index < 0 || index >= AFE_MAX_PORTS) {
5148 pr_err("%s: AFE port index[%d] invalid!\n",
5149 __func__, index);
5150 return -EINVAL;
5151 }
5152 ret = q6audio_validate_port(port_id);
5153 if (ret < 0) {
5154 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
5155 return -EINVAL;
5156 }
5157
5158 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5159 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5160 rtproxy.hdr.pkt_size = sizeof(rtproxy);
5161 rtproxy.hdr.src_port = 0;
5162 rtproxy.hdr.dest_port = 0;
5163 rtproxy.hdr.token = 0;
5164 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER;
5165 rtproxy.port_id = port_id;
5166 rtproxy.reserved = 0;
5167
5168 rtproxy.hdr.token = index;
5169
5170 if (port_id == RT_PROXY_PORT_001_TX) {
5171 this_afe.tx_cb = NULL;
5172 this_afe.tx_private_data = NULL;
5173 } else if (port_id == RT_PROXY_PORT_001_RX) {
5174 this_afe.rx_cb = NULL;
5175 this_afe.rx_private_data = NULL;
5176 }
5177
5178 ret = afe_apr_send_pkt(&rtproxy, &this_afe.wait[index]);
5179 if (ret)
5180 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
5181 __func__, ret);
5182 return ret;
5183}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305184EXPORT_SYMBOL(afe_unregister_get_events);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305185
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305186/**
5187 * afe_rt_proxy_port_write -
5188 * command for AFE RT proxy port write
5189 *
5190 * @buf_addr_p: Physical buffer address with
5191 * playback data to proxy port
5192 * @mem_map_handle: memory map handle of write buffer
5193 * @bytes: number of bytes to write
5194 *
5195 * Returns 0 on success or error on failure
5196 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305197int afe_rt_proxy_port_write(phys_addr_t buf_addr_p,
5198 u32 mem_map_handle, int bytes)
5199{
5200 int ret = 0;
5201 struct afe_port_data_cmd_rt_proxy_port_write_v2 afecmd_wr;
5202
5203 if (this_afe.apr == NULL) {
5204 pr_err("%s: register to AFE is not done\n", __func__);
5205 ret = -ENODEV;
5206 return ret;
5207 }
5208 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
5209 &buf_addr_p, bytes);
5210
5211 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5212 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5213 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
5214 afecmd_wr.hdr.src_port = 0;
5215 afecmd_wr.hdr.dest_port = 0;
5216 afecmd_wr.hdr.token = 0;
5217 afecmd_wr.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2;
5218 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
5219 afecmd_wr.buffer_address_lsw = lower_32_bits(buf_addr_p);
5220 afecmd_wr.buffer_address_msw =
5221 msm_audio_populate_upper_32_bits(buf_addr_p);
5222 afecmd_wr.mem_map_handle = mem_map_handle;
5223 afecmd_wr.available_bytes = bytes;
5224 afecmd_wr.reserved = 0;
5225
5226 ret = afe_apr_send_pkt(&afecmd_wr, NULL);
5227 if (ret)
5228 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
5229 __func__, afecmd_wr.port_id, ret);
5230 return ret;
5231
5232}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305233EXPORT_SYMBOL(afe_rt_proxy_port_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305234
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305235/**
5236 * afe_rt_proxy_port_read -
5237 * command for AFE RT proxy port read
5238 *
5239 * @buf_addr_p: Physical buffer address to fill read data
5240 * @mem_map_handle: memory map handle for buffer read
5241 * @bytes: number of bytes to read
5242 *
5243 * Returns 0 on success or error on failure
5244 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305245int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
5246 u32 mem_map_handle, int bytes)
5247{
5248 int ret = 0;
5249 struct afe_port_data_cmd_rt_proxy_port_read_v2 afecmd_rd;
5250
5251 if (this_afe.apr == NULL) {
5252 pr_err("%s: register to AFE is not done\n", __func__);
5253 ret = -ENODEV;
5254 return ret;
5255 }
5256 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
5257 &buf_addr_p, bytes);
5258
5259 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5260 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5261 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
5262 afecmd_rd.hdr.src_port = 0;
5263 afecmd_rd.hdr.dest_port = 0;
5264 afecmd_rd.hdr.token = 0;
5265 afecmd_rd.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2;
5266 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
5267 afecmd_rd.buffer_address_lsw = lower_32_bits(buf_addr_p);
5268 afecmd_rd.buffer_address_msw =
5269 msm_audio_populate_upper_32_bits(buf_addr_p);
5270 afecmd_rd.available_bytes = bytes;
5271 afecmd_rd.mem_map_handle = mem_map_handle;
5272
5273 ret = afe_apr_send_pkt(&afecmd_rd, NULL);
5274 if (ret)
5275 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
5276 __func__, afecmd_rd.port_id, ret);
5277 return ret;
5278}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305279EXPORT_SYMBOL(afe_rt_proxy_port_read);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305280
5281#ifdef CONFIG_DEBUG_FS
5282static struct dentry *debugfs_afelb;
5283static struct dentry *debugfs_afelb_gain;
5284
5285static int afe_debug_open(struct inode *inode, struct file *file)
5286{
5287 file->private_data = inode->i_private;
5288 pr_info("%s: debug intf %s\n", __func__, (char *) file->private_data);
5289 return 0;
5290}
5291
5292static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
5293{
5294 char *token;
5295 int base, cnt;
5296
5297 token = strsep(&buf, " ");
5298
5299 for (cnt = 0; cnt < num_of_par; cnt++) {
5300 if (token != NULL) {
5301 if ((token[1] == 'x') || (token[1] == 'X'))
5302 base = 16;
5303 else
5304 base = 10;
5305
5306 if (kstrtoul(token, base, &param1[cnt]) != 0) {
5307 pr_err("%s: kstrtoul failed\n",
5308 __func__);
5309 return -EINVAL;
5310 }
5311
5312 token = strsep(&buf, " ");
5313 } else {
5314 pr_err("%s: token NULL\n", __func__);
5315 return -EINVAL;
5316 }
5317 }
5318 return 0;
5319}
5320#define AFE_LOOPBACK_ON (1)
5321#define AFE_LOOPBACK_OFF (0)
5322static ssize_t afe_debug_write(struct file *filp,
5323 const char __user *ubuf, size_t cnt, loff_t *ppos)
5324{
5325 char *lb_str = filp->private_data;
5326 char lbuf[32];
5327 int rc;
5328 unsigned long param[5];
5329
5330 if (cnt > sizeof(lbuf) - 1) {
5331 pr_err("%s: cnt %zd size %zd\n", __func__, cnt, sizeof(lbuf)-1);
5332 return -EINVAL;
5333 }
5334
5335 rc = copy_from_user(lbuf, ubuf, cnt);
5336 if (rc) {
5337 pr_err("%s: copy from user failed %d\n", __func__, rc);
5338 return -EFAULT;
5339 }
5340
5341 lbuf[cnt] = '\0';
5342
5343 if (!strcmp(lb_str, "afe_loopback")) {
5344 rc = afe_get_parameters(lbuf, param, 3);
5345 if (!rc) {
5346 pr_info("%s: %lu %lu %lu\n", lb_str, param[0], param[1],
5347 param[2]);
5348
5349 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
5350 AFE_LOOPBACK_OFF)) {
5351 pr_err("%s: Error, parameter 0 incorrect\n",
5352 __func__);
5353 rc = -EINVAL;
5354 goto afe_error;
5355 }
5356 if ((q6audio_validate_port(param[1]) < 0) ||
5357 (q6audio_validate_port(param[2])) < 0) {
5358 pr_err("%s: Error, invalid afe port\n",
5359 __func__);
5360 }
5361 if (this_afe.apr == NULL) {
5362 pr_err("%s: Error, AFE not opened\n", __func__);
5363 rc = -EINVAL;
5364 } else {
5365 rc = afe_loopback(param[0], param[1], param[2]);
5366 }
5367 } else {
5368 pr_err("%s: Error, invalid parameters\n", __func__);
5369 rc = -EINVAL;
5370 }
5371
5372 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
5373 rc = afe_get_parameters(lbuf, param, 2);
5374 if (!rc) {
5375 pr_info("%s: %s %lu %lu\n",
5376 __func__, lb_str, param[0], param[1]);
5377
5378 rc = q6audio_validate_port(param[0]);
5379 if (rc < 0) {
5380 pr_err("%s: Error, invalid afe port %d %lu\n",
5381 __func__, rc, param[0]);
5382 rc = -EINVAL;
5383 goto afe_error;
5384 }
5385
5386 if (param[1] > 100) {
5387 pr_err("%s: Error, volume should be 0 to 100 percentage param = %lu\n",
5388 __func__, param[1]);
5389 rc = -EINVAL;
5390 goto afe_error;
5391 }
5392
5393 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
5394
5395 if (this_afe.apr == NULL) {
5396 pr_err("%s: Error, AFE not opened\n", __func__);
5397 rc = -EINVAL;
5398 } else {
5399 rc = afe_loopback_gain(param[0], param[1]);
5400 }
5401 } else {
5402 pr_err("%s: Error, invalid parameters\n", __func__);
5403 rc = -EINVAL;
5404 }
5405 }
5406
5407afe_error:
5408 if (rc == 0)
5409 rc = cnt;
5410 else
5411 pr_err("%s: rc = %d\n", __func__, rc);
5412
5413 return rc;
5414}
5415
5416static const struct file_operations afe_debug_fops = {
5417 .open = afe_debug_open,
5418 .write = afe_debug_write
5419};
5420
5421static void config_debug_fs_init(void)
5422{
5423 debugfs_afelb = debugfs_create_file("afe_loopback",
5424 0664, NULL, (void *) "afe_loopback",
5425 &afe_debug_fops);
5426
5427 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
5428 0664, NULL, (void *) "afe_loopback_gain",
5429 &afe_debug_fops);
5430}
5431static void config_debug_fs_exit(void)
5432{
5433 debugfs_remove(debugfs_afelb);
5434 debugfs_remove(debugfs_afelb_gain);
5435}
5436#else
5437static void config_debug_fs_init(void)
5438{
5439}
5440static void config_debug_fs_exit(void)
5441{
5442}
5443#endif
5444
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305445/**
5446 * afe_set_dtmf_gen_rx_portid -
5447 * Set port_id for DTMF tone generation
5448 *
5449 * @port_id: AFE port id
5450 * @set: set or reset port id value for dtmf gen
5451 *
5452 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305453void afe_set_dtmf_gen_rx_portid(u16 port_id, int set)
5454{
5455 if (set)
5456 this_afe.dtmf_gen_rx_portid = port_id;
5457 else if (this_afe.dtmf_gen_rx_portid == port_id)
5458 this_afe.dtmf_gen_rx_portid = -1;
5459}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305460EXPORT_SYMBOL(afe_set_dtmf_gen_rx_portid);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305461
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305462/**
5463 * afe_dtmf_generate_rx - command to generate AFE DTMF RX
5464 *
5465 * @duration_in_ms: Duration in ms for dtmf tone
5466 * @high_freq: Higher frequency for dtmf
5467 * @low_freq: lower frequency for dtmf
5468 * @gain: Gain value for DTMF tone
5469 *
5470 * Returns 0 on success, appropriate error code otherwise
5471 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305472int afe_dtmf_generate_rx(int64_t duration_in_ms,
5473 uint16_t high_freq,
5474 uint16_t low_freq, uint16_t gain)
5475{
5476 int ret = 0;
5477 int index = 0;
5478 struct afe_dtmf_generation_command cmd_dtmf;
5479
5480 pr_debug("%s: DTMF AFE Gen\n", __func__);
5481
5482 if (afe_validate_port(this_afe.dtmf_gen_rx_portid) < 0) {
5483 pr_err("%s: Failed : Invalid Port id = 0x%x\n",
5484 __func__, this_afe.dtmf_gen_rx_portid);
5485 ret = -EINVAL;
5486 goto fail_cmd;
5487 }
5488
5489 if (this_afe.apr == NULL) {
5490 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5491 0xFFFFFFFF, &this_afe);
5492 pr_debug("%s: Register AFE\n", __func__);
5493 if (this_afe.apr == NULL) {
5494 pr_err("%s: Unable to register AFE\n", __func__);
5495 ret = -ENODEV;
5496 return ret;
5497 }
5498 rtac_set_afe_handle(this_afe.apr);
5499 }
5500
5501 pr_debug("%s: dur=%lld: hfreq=%d lfreq=%d gain=%d portid=0x%x\n",
5502 __func__,
5503 duration_in_ms, high_freq, low_freq, gain,
5504 this_afe.dtmf_gen_rx_portid);
5505
5506 cmd_dtmf.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5507 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5508 cmd_dtmf.hdr.pkt_size = sizeof(cmd_dtmf);
5509 cmd_dtmf.hdr.src_port = 0;
5510 cmd_dtmf.hdr.dest_port = 0;
5511 cmd_dtmf.hdr.token = 0;
5512 cmd_dtmf.hdr.opcode = AFE_PORTS_CMD_DTMF_CTL;
5513 cmd_dtmf.duration_in_ms = duration_in_ms;
5514 cmd_dtmf.high_freq = high_freq;
5515 cmd_dtmf.low_freq = low_freq;
5516 cmd_dtmf.gain = gain;
5517 cmd_dtmf.num_ports = 1;
5518 cmd_dtmf.port_ids = q6audio_get_port_id(this_afe.dtmf_gen_rx_portid);
5519
5520 atomic_set(&this_afe.state, 1);
5521 atomic_set(&this_afe.status, 0);
5522 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_dtmf);
5523 if (ret < 0) {
5524 pr_err("%s: AFE DTMF failed for num_ports:%d ids:0x%x\n",
5525 __func__, cmd_dtmf.num_ports, cmd_dtmf.port_ids);
5526 ret = -EINVAL;
5527 goto fail_cmd;
5528 }
5529 index = q6audio_get_port_index(this_afe.dtmf_gen_rx_portid);
5530 if (index < 0 || index >= AFE_MAX_PORTS) {
5531 pr_err("%s: AFE port index[%d] invalid!\n",
5532 __func__, index);
5533 ret = -EINVAL;
5534 goto fail_cmd;
5535 }
5536 ret = wait_event_timeout(this_afe.wait[index],
5537 (atomic_read(&this_afe.state) == 0),
5538 msecs_to_jiffies(TIMEOUT_MS));
5539 if (!ret) {
5540 pr_err("%s: wait_event timeout\n", __func__);
5541 ret = -EINVAL;
5542 goto fail_cmd;
5543 }
5544 if (atomic_read(&this_afe.status) > 0) {
5545 pr_err("%s: config cmd failed [%s]\n",
5546 __func__, adsp_err_get_err_str(
5547 atomic_read(&this_afe.status)));
5548 ret = adsp_err_get_lnx_err_code(
5549 atomic_read(&this_afe.status));
5550 goto fail_cmd;
5551 }
5552 return 0;
5553
5554fail_cmd:
5555 pr_err("%s: failed %d\n", __func__, ret);
5556 return ret;
5557}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305558EXPORT_SYMBOL(afe_dtmf_generate_rx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305559
5560static int afe_sidetone_iir(u16 tx_port_id)
5561{
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305562 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305563 uint16_t size = 0;
5564 int cal_index = AFE_SIDETONE_IIR_CAL;
5565 int iir_pregain = 0;
5566 int iir_num_biquad_stages = 0;
5567 int iir_enable;
5568 struct cal_block_data *cal_block;
5569 int mid;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005570 struct afe_mod_enable_param enable;
5571 struct afe_sidetone_iir_filter_config_params filter_data;
5572 struct param_hdr_v3 param_hdr;
5573 u8 *packed_param_data = NULL;
5574 u32 packed_param_size = 0;
5575 u32 single_param_size = 0;
5576 struct audio_cal_info_sidetone_iir *st_iir_cal_info = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305577
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005578 memset(&enable, 0, sizeof(enable));
5579 memset(&filter_data, 0, sizeof(filter_data));
5580 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305581
5582 if (this_afe.cal_data[cal_index] == NULL) {
5583 pr_err("%s: cal data is NULL\n", __func__);
5584 ret = -EINVAL;
5585 goto done;
5586 }
5587 mutex_lock(&this_afe.cal_data[cal_index]->lock);
5588 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07005589 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305590 pr_err("%s: cal_block not found\n ", __func__);
5591 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5592 ret = -EINVAL;
5593 goto done;
5594 }
5595
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005596 /* Cache data from cal block while inside lock to reduce locked time */
5597 st_iir_cal_info =
5598 (struct audio_cal_info_sidetone_iir *) cal_block->cal_info;
5599 iir_pregain = st_iir_cal_info->pregain;
5600 iir_enable = st_iir_cal_info->iir_enable;
5601 iir_num_biquad_stages = st_iir_cal_info->num_biquad_stages;
5602 mid = st_iir_cal_info->mid;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305603
5604 /*
5605 * calculate the actual size of payload based on no of stages
5606 * enabled in calibration
5607 */
5608 size = (MAX_SIDETONE_IIR_DATA_SIZE / MAX_NO_IIR_FILTER_STAGE) *
5609 iir_num_biquad_stages;
5610 /*
5611 * For an odd number of stages, 2 bytes of padding are
5612 * required at the end of the payload.
5613 */
5614 if (iir_num_biquad_stages % 2) {
5615 pr_debug("%s: adding 2 to size:%d\n", __func__, size);
5616 size = size + 2;
5617 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005618 memcpy(&filter_data.iir_config, &st_iir_cal_info->iir_config, size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305619 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5620
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005621 packed_param_size =
5622 sizeof(param_hdr) * 2 + sizeof(enable) + sizeof(filter_data);
5623 packed_param_data = kzalloc(packed_param_size, GFP_KERNEL);
5624 if (!packed_param_data)
5625 return -ENOMEM;
5626 packed_param_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305627
5628 /*
5629 * Set IIR enable params
5630 */
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005631 param_hdr.module_id = mid;
5632 param_hdr.param_id = INSTANCE_ID_0;
5633 param_hdr.param_id = AFE_PARAM_ID_ENABLE;
5634 param_hdr.param_size = sizeof(enable);
5635 enable.enable = iir_enable;
5636 ret = q6common_pack_pp_params(packed_param_data, &param_hdr,
5637 (u8 *) &enable, &single_param_size);
5638 if (ret) {
5639 pr_err("%s: Failed to pack param data, error %d\n", __func__,
5640 ret);
5641 goto done;
5642 }
5643 packed_param_size += single_param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305644
5645 /*
5646 * Set IIR filter config params
5647 */
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005648 param_hdr.module_id = mid;
5649 param_hdr.instance_id = INSTANCE_ID_0;
5650 param_hdr.param_id = AFE_PARAM_ID_SIDETONE_IIR_FILTER_CONFIG;
5651 param_hdr.param_size = sizeof(filter_data.num_biquad_stages) +
5652 sizeof(filter_data.pregain) + size;
5653 filter_data.num_biquad_stages = iir_num_biquad_stages;
5654 filter_data.pregain = iir_pregain;
5655 ret = q6common_pack_pp_params(packed_param_data + packed_param_size,
5656 &param_hdr, (u8 *) &filter_data,
5657 &single_param_size);
5658 if (ret) {
5659 pr_err("%s: Failed to pack param data, error %d\n", __func__,
5660 ret);
5661 goto done;
5662 }
5663 packed_param_size += single_param_size;
5664
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305665 pr_debug("%s: tx(0x%x)mid(0x%x)iir_en(%d)stg(%d)gain(0x%x)size(%d)\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005666 __func__, tx_port_id, mid, enable.enable,
5667 filter_data.num_biquad_stages, filter_data.pregain,
5668 param_hdr.param_size);
5669
5670 ret = q6afe_set_params(tx_port_id, q6audio_get_port_index(tx_port_id),
5671 NULL, packed_param_data, packed_param_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305672 if (ret)
5673 pr_err("%s: AFE sidetone failed for tx_port(0x%x)\n",
5674 __func__, tx_port_id);
5675
5676done:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005677 kfree(packed_param_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305678 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305679}
5680
5681static int afe_sidetone(u16 tx_port_id, u16 rx_port_id, bool enable)
5682{
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305683 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305684 int cal_index = AFE_SIDETONE_CAL;
5685 int sidetone_gain;
5686 int sidetone_enable;
5687 struct cal_block_data *cal_block;
5688 int mid = 0;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005689 struct afe_loopback_sidetone_gain gain_data;
5690 struct loopback_cfg_data cfg_data;
5691 struct param_hdr_v3 param_hdr;
5692 u8 *packed_param_data = NULL;
5693 u32 packed_param_size = 0;
5694 u32 single_param_size = 0;
5695 struct audio_cal_info_sidetone *st_cal_info = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305696
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305697 if (this_afe.cal_data[cal_index] == NULL) {
5698 pr_err("%s: cal data is NULL\n", __func__);
5699 ret = -EINVAL;
5700 goto done;
5701 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005702
5703 memset(&gain_data, 0, sizeof(gain_data));
5704 memset(&cfg_data, 0, sizeof(cfg_data));
5705 memset(&param_hdr, 0, sizeof(param_hdr));
5706
5707 packed_param_size =
5708 sizeof(param_hdr) * 2 + sizeof(gain_data) + sizeof(cfg_data);
5709 packed_param_data = kzalloc(packed_param_size, GFP_KERNEL);
5710 if (!packed_param_data)
5711 return -ENOMEM;
5712 packed_param_size = 0;
5713
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305714 mutex_lock(&this_afe.cal_data[cal_index]->lock);
5715 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07005716 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305717 pr_err("%s: cal_block not found\n", __func__);
5718 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5719 ret = -EINVAL;
5720 goto done;
5721 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005722
5723 /* Cache data from cal block while inside lock to reduce locked time */
5724 st_cal_info = (struct audio_cal_info_sidetone *) cal_block->cal_info;
5725 sidetone_gain = st_cal_info->gain;
5726 sidetone_enable = st_cal_info->enable;
5727 mid = st_cal_info->mid;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305728 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
5729
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005730 /* Set gain data. */
5731 param_hdr.module_id = AFE_MODULE_LOOPBACK;
5732 param_hdr.instance_id = INSTANCE_ID_0;
5733 param_hdr.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
5734 param_hdr.param_size = sizeof(struct afe_loopback_sidetone_gain);
5735 gain_data.rx_port_id = rx_port_id;
5736 gain_data.gain = sidetone_gain;
5737 ret = q6common_pack_pp_params(packed_param_data, &param_hdr,
5738 (u8 *) &gain_data, &single_param_size);
5739 if (ret) {
5740 pr_err("%s: Failed to pack param data, error %d\n", __func__,
5741 ret);
5742 goto done;
5743 }
5744 packed_param_size += single_param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305745
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005746 /* Set configuration data. */
5747 param_hdr.module_id = AFE_MODULE_LOOPBACK;
5748 param_hdr.instance_id = INSTANCE_ID_0;
5749 param_hdr.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
5750 param_hdr.param_size = sizeof(struct loopback_cfg_data);
5751 cfg_data.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
5752 cfg_data.dst_port_id = rx_port_id;
5753 cfg_data.routing_mode = LB_MODE_SIDETONE;
5754 cfg_data.enable = enable;
5755 ret = q6common_pack_pp_params(packed_param_data + packed_param_size,
5756 &param_hdr, (u8 *) &cfg_data,
5757 &single_param_size);
5758 if (ret) {
5759 pr_err("%s: Failed to pack param data, error %d\n", __func__,
5760 ret);
5761 goto done;
5762 }
5763 packed_param_size += single_param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305764
5765 pr_debug("%s rx(0x%x) tx(0x%x) enable(%d) mid(0x%x) gain(%d) sidetone_enable(%d)\n",
5766 __func__, rx_port_id, tx_port_id,
5767 enable, mid, sidetone_gain, sidetone_enable);
5768
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005769 ret = q6afe_set_params(tx_port_id, q6audio_get_port_index(tx_port_id),
5770 NULL, packed_param_data, packed_param_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305771 if (ret)
5772 pr_err("%s: AFE sidetone send failed for tx_port:%d rx_port:%d ret:%d\n",
5773 __func__, tx_port_id, rx_port_id, ret);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005774
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305775done:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005776 kfree(packed_param_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305777 return ret;
5778}
5779
5780int afe_sidetone_enable(u16 tx_port_id, u16 rx_port_id, bool enable)
5781{
5782 int ret;
5783 int index;
5784
5785 index = q6audio_get_port_index(rx_port_id);
5786 if (index < 0 || index >= AFE_MAX_PORTS) {
5787 pr_err("%s: AFE port index[%d] invalid!\n",
5788 __func__, index);
5789 ret = -EINVAL;
5790 goto done;
5791 }
5792 if (q6audio_validate_port(rx_port_id) < 0) {
5793 pr_err("%s: Invalid port 0x%x\n",
5794 __func__, rx_port_id);
5795 ret = -EINVAL;
5796 goto done;
5797 }
5798 index = q6audio_get_port_index(tx_port_id);
5799 if (index < 0 || index >= AFE_MAX_PORTS) {
5800 pr_err("%s: AFE port index[%d] invalid!\n",
5801 __func__, index);
5802 ret = -EINVAL;
5803 goto done;
5804 }
5805 if (q6audio_validate_port(tx_port_id) < 0) {
5806 pr_err("%s: Invalid port 0x%x\n",
5807 __func__, tx_port_id);
5808 ret = -EINVAL;
5809 goto done;
5810 }
5811 if (enable) {
5812 ret = afe_sidetone_iir(tx_port_id);
5813 if (ret)
5814 goto done;
5815 }
5816
5817 ret = afe_sidetone(tx_port_id, rx_port_id, enable);
5818
5819done:
5820 return ret;
5821}
5822
Karthikeyan Mani16b69722018-05-03 18:26:21 -07005823/**
5824 * afe_set_display_stream - command to update AFE dp port params
5825 *
5826 * @rx_port_id: AFE port id
5827 * @stream_idx: dp controller stream index
5828 * @ctl_idx: dp controller index
5829 *
5830 * Returns 0 on success, appropriate error code otherwise
5831 */
5832int afe_set_display_stream(u16 rx_port_id, u32 stream_idx, u32 ctl_idx)
5833{
5834 int ret;
5835 struct param_hdr_v3 param_hdr;
5836 u32 packed_param_size = 0;
5837 u8 *packed_param_data = NULL;
5838 struct afe_display_stream_idx stream_data;
5839 struct afe_display_ctl_idx ctl_data;
5840 u32 single_param_size = 0;
5841
5842 memset(&param_hdr, 0, sizeof(param_hdr));
5843 memset(&stream_data, 0, sizeof(stream_data));
5844 memset(&ctl_data, 0, sizeof(ctl_data));
5845
5846 packed_param_size =
5847 sizeof(param_hdr) * 2 + sizeof(stream_data) + sizeof(ctl_data);
5848 packed_param_data = kzalloc(packed_param_size, GFP_KERNEL);
5849 if (!packed_param_data)
5850 return -ENOMEM;
5851 packed_param_size = 0;
5852
5853 /* Set stream index */
5854 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
5855 param_hdr.instance_id = INSTANCE_ID_0;
5856 param_hdr.param_id = AFE_PARAM_ID_HDMI_DP_MST_VID_IDX_CFG;
5857 param_hdr.param_size = sizeof(struct afe_display_stream_idx);
5858 stream_data.minor_version = 1;
5859 stream_data.stream_idx = stream_idx;
5860 ret = q6common_pack_pp_params(packed_param_data, &param_hdr,
5861 (u8 *) &stream_data, &single_param_size);
5862 if (ret) {
5863 pr_err("%s: Failed to pack param data, error %d\n", __func__,
5864 ret);
5865 goto done;
5866 }
5867 packed_param_size += single_param_size;
5868
5869 /* Set controller dptx index */
5870 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
5871 param_hdr.instance_id = INSTANCE_ID_0;
5872 param_hdr.param_id = AFE_PARAM_ID_HDMI_DPTX_IDX_CFG;
5873 param_hdr.param_size = sizeof(struct afe_display_ctl_idx);
5874 ctl_data.minor_version = 1;
5875 ctl_data.ctl_idx = ctl_idx;
5876 ret = q6common_pack_pp_params(packed_param_data + packed_param_size,
5877 &param_hdr, (u8 *) &ctl_data,
5878 &single_param_size);
5879 if (ret) {
5880 pr_err("%s: Failed to pack param data, error %d\n", __func__,
5881 ret);
5882 goto done;
5883 }
5884 packed_param_size += single_param_size;
5885
5886 pr_debug("%s: rx(0x%x) stream(%d) controller(%d)\n",
5887 __func__, rx_port_id, stream_idx, ctl_idx);
5888
5889 ret = q6afe_set_params(rx_port_id, q6audio_get_port_index(rx_port_id),
5890 NULL, packed_param_data, packed_param_size);
5891 if (ret)
5892 pr_err("%s: AFE display stream send failed for rx_port:%d ret:%d\n",
5893 __func__, rx_port_id, ret);
5894
5895done:
5896 kfree(packed_param_data);
5897 return ret;
5898
5899}
5900EXPORT_SYMBOL(afe_set_display_stream);
5901
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305902int afe_validate_port(u16 port_id)
5903{
5904 int ret;
5905
5906 switch (port_id) {
5907 case PRIMARY_I2S_RX:
5908 case PRIMARY_I2S_TX:
5909 case AFE_PORT_ID_PRIMARY_PCM_RX:
5910 case AFE_PORT_ID_PRIMARY_PCM_TX:
5911 case AFE_PORT_ID_SECONDARY_PCM_RX:
5912 case AFE_PORT_ID_SECONDARY_PCM_TX:
5913 case AFE_PORT_ID_TERTIARY_PCM_RX:
5914 case AFE_PORT_ID_TERTIARY_PCM_TX:
5915 case AFE_PORT_ID_QUATERNARY_PCM_RX:
5916 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05305917 case AFE_PORT_ID_QUINARY_PCM_RX:
5918 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305919 case SECONDARY_I2S_RX:
5920 case SECONDARY_I2S_TX:
5921 case MI2S_RX:
5922 case MI2S_TX:
5923 case HDMI_RX:
5924 case DISPLAY_PORT_RX:
5925 case AFE_PORT_ID_SPDIF_RX:
5926 case RSVD_2:
5927 case RSVD_3:
5928 case DIGI_MIC_TX:
5929 case VOICE_RECORD_RX:
5930 case VOICE_RECORD_TX:
5931 case VOICE_PLAYBACK_TX:
5932 case VOICE2_PLAYBACK_TX:
5933 case SLIMBUS_0_RX:
5934 case SLIMBUS_0_TX:
5935 case SLIMBUS_1_RX:
5936 case SLIMBUS_1_TX:
5937 case SLIMBUS_2_RX:
5938 case SLIMBUS_2_TX:
5939 case SLIMBUS_3_RX:
5940 case INT_BT_SCO_RX:
5941 case INT_BT_SCO_TX:
5942 case INT_BT_A2DP_RX:
5943 case INT_FM_RX:
5944 case INT_FM_TX:
5945 case RT_PROXY_PORT_001_RX:
5946 case RT_PROXY_PORT_001_TX:
5947 case SLIMBUS_4_RX:
5948 case SLIMBUS_4_TX:
5949 case SLIMBUS_5_RX:
5950 case SLIMBUS_6_RX:
5951 case SLIMBUS_6_TX:
5952 case SLIMBUS_7_RX:
5953 case SLIMBUS_7_TX:
5954 case SLIMBUS_8_RX:
5955 case SLIMBUS_8_TX:
5956 case AFE_PORT_ID_USB_RX:
5957 case AFE_PORT_ID_USB_TX:
5958 case AFE_PORT_ID_PRIMARY_MI2S_RX:
5959 case AFE_PORT_ID_PRIMARY_MI2S_TX:
5960 case AFE_PORT_ID_SECONDARY_MI2S_RX:
5961 case AFE_PORT_ID_SECONDARY_MI2S_TX:
5962 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
5963 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
5964 case AFE_PORT_ID_TERTIARY_MI2S_RX:
5965 case AFE_PORT_ID_TERTIARY_MI2S_TX:
5966 case AFE_PORT_ID_QUINARY_MI2S_RX:
5967 case AFE_PORT_ID_QUINARY_MI2S_TX:
5968 case AFE_PORT_ID_SENARY_MI2S_TX:
5969 case AFE_PORT_ID_PRIMARY_TDM_RX:
5970 case AFE_PORT_ID_PRIMARY_TDM_TX:
5971 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
5972 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
5973 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
5974 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
5975 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
5976 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
5977 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
5978 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
5979 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
5980 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
5981 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
5982 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
5983 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
5984 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
5985 case AFE_PORT_ID_SECONDARY_TDM_RX:
5986 case AFE_PORT_ID_SECONDARY_TDM_TX:
5987 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
5988 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
5989 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
5990 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
5991 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
5992 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
5993 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
5994 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
5995 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
5996 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
5997 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
5998 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
5999 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
6000 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
6001 case AFE_PORT_ID_TERTIARY_TDM_RX:
6002 case AFE_PORT_ID_TERTIARY_TDM_TX:
6003 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
6004 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
6005 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
6006 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
6007 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
6008 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
6009 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
6010 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
6011 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
6012 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
6013 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
6014 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
6015 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
6016 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
6017 case AFE_PORT_ID_QUATERNARY_TDM_RX:
6018 case AFE_PORT_ID_QUATERNARY_TDM_TX:
6019 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
6020 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
6021 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
6022 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
6023 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
6024 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
6025 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
6026 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
6027 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
6028 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
6029 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
6030 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
6031 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
6032 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05306033 case AFE_PORT_ID_QUINARY_TDM_RX:
6034 case AFE_PORT_ID_QUINARY_TDM_TX:
6035 case AFE_PORT_ID_QUINARY_TDM_RX_1:
6036 case AFE_PORT_ID_QUINARY_TDM_TX_1:
6037 case AFE_PORT_ID_QUINARY_TDM_RX_2:
6038 case AFE_PORT_ID_QUINARY_TDM_TX_2:
6039 case AFE_PORT_ID_QUINARY_TDM_RX_3:
6040 case AFE_PORT_ID_QUINARY_TDM_TX_3:
6041 case AFE_PORT_ID_QUINARY_TDM_RX_4:
6042 case AFE_PORT_ID_QUINARY_TDM_TX_4:
6043 case AFE_PORT_ID_QUINARY_TDM_RX_5:
6044 case AFE_PORT_ID_QUINARY_TDM_TX_5:
6045 case AFE_PORT_ID_QUINARY_TDM_RX_6:
6046 case AFE_PORT_ID_QUINARY_TDM_TX_6:
6047 case AFE_PORT_ID_QUINARY_TDM_RX_7:
6048 case AFE_PORT_ID_QUINARY_TDM_TX_7:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306049 case AFE_PORT_ID_INT0_MI2S_RX:
6050 case AFE_PORT_ID_INT1_MI2S_RX:
6051 case AFE_PORT_ID_INT2_MI2S_RX:
6052 case AFE_PORT_ID_INT3_MI2S_RX:
6053 case AFE_PORT_ID_INT4_MI2S_RX:
6054 case AFE_PORT_ID_INT5_MI2S_RX:
6055 case AFE_PORT_ID_INT6_MI2S_RX:
6056 case AFE_PORT_ID_INT0_MI2S_TX:
6057 case AFE_PORT_ID_INT1_MI2S_TX:
6058 case AFE_PORT_ID_INT2_MI2S_TX:
6059 case AFE_PORT_ID_INT3_MI2S_TX:
6060 case AFE_PORT_ID_INT4_MI2S_TX:
6061 case AFE_PORT_ID_INT5_MI2S_TX:
6062 case AFE_PORT_ID_INT6_MI2S_TX:
6063 {
6064 ret = 0;
6065 break;
6066 }
6067
6068 default:
6069 pr_err("%s: default ret 0x%x\n", __func__, port_id);
6070 ret = -EINVAL;
6071 }
6072
6073 return ret;
6074}
6075
6076int afe_convert_virtual_to_portid(u16 port_id)
6077{
6078 int ret;
6079
6080 /*
6081 * if port_id is virtual, convert to physical..
6082 * if port_id is already physical, return physical
6083 */
6084 if (afe_validate_port(port_id) < 0) {
6085 if (port_id == RT_PROXY_DAI_001_RX ||
6086 port_id == RT_PROXY_DAI_001_TX ||
6087 port_id == RT_PROXY_DAI_002_RX ||
6088 port_id == RT_PROXY_DAI_002_TX) {
6089 ret = VIRTUAL_ID_TO_PORTID(port_id);
6090 } else {
6091 pr_err("%s: wrong port 0x%x\n",
6092 __func__, port_id);
6093 ret = -EINVAL;
6094 }
6095 } else
6096 ret = port_id;
6097
6098 return ret;
6099}
6100int afe_port_stop_nowait(int port_id)
6101{
6102 struct afe_port_cmd_device_stop stop;
6103 int ret = 0;
6104
6105 if (this_afe.apr == NULL) {
6106 pr_err("%s: AFE is already closed\n", __func__);
6107 ret = -EINVAL;
6108 goto fail_cmd;
6109 }
6110 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
6111 port_id = q6audio_convert_virtual_to_portid(port_id);
6112
6113 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6114 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6115 stop.hdr.pkt_size = sizeof(stop);
6116 stop.hdr.src_port = 0;
6117 stop.hdr.dest_port = 0;
6118 stop.hdr.token = 0;
6119 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
6120 stop.port_id = port_id;
6121 stop.reserved = 0;
6122
6123 ret = afe_apr_send_pkt(&stop, NULL);
6124 if (ret)
6125 pr_err("%s: AFE close failed %d\n", __func__, ret);
6126
6127fail_cmd:
6128 return ret;
6129
6130}
6131
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306132/**
6133 * afe_close - command to close AFE port
6134 *
6135 * @port_id: AFE port id
6136 *
6137 * Returns 0 on success, appropriate error code otherwise
6138 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306139int afe_close(int port_id)
6140{
6141 struct afe_port_cmd_device_stop stop;
6142 enum afe_mad_type mad_type;
6143 int ret = 0;
6144 int index = 0;
6145 uint16_t port_index;
6146
6147 if (this_afe.apr == NULL) {
6148 pr_err("%s: AFE is already closed\n", __func__);
6149 if ((port_id == RT_PROXY_DAI_001_RX) ||
6150 (port_id == RT_PROXY_DAI_002_TX))
6151 pcm_afe_instance[port_id & 0x1] = 0;
6152 if ((port_id == RT_PROXY_DAI_002_RX) ||
6153 (port_id == RT_PROXY_DAI_001_TX))
6154 proxy_afe_instance[port_id & 0x1] = 0;
6155 afe_close_done[port_id & 0x1] = true;
6156 ret = -EINVAL;
6157 goto fail_cmd;
6158 }
6159 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
6160 if ((port_id == RT_PROXY_DAI_001_RX) ||
6161 (port_id == RT_PROXY_DAI_002_TX)) {
6162 pr_debug("%s: before decrementing pcm_afe_instance %d\n",
6163 __func__, pcm_afe_instance[port_id & 0x1]);
6164 port_id = VIRTUAL_ID_TO_PORTID(port_id);
6165 pcm_afe_instance[port_id & 0x1]--;
6166 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
6167 proxy_afe_instance[port_id & 0x1] == 0)) ||
6168 afe_close_done[port_id & 0x1] == true)
6169 return 0;
6170
6171 afe_close_done[port_id & 0x1] = true;
6172 }
6173
6174 if ((port_id == RT_PROXY_DAI_002_RX) ||
6175 (port_id == RT_PROXY_DAI_001_TX)) {
6176 pr_debug("%s: before decrementing proxy_afe_instance %d\n",
6177 __func__, proxy_afe_instance[port_id & 0x1]);
6178 port_id = VIRTUAL_ID_TO_PORTID(port_id);
6179 proxy_afe_instance[port_id & 0x1]--;
6180 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
6181 proxy_afe_instance[port_id & 0x1] == 0)) ||
6182 afe_close_done[port_id & 0x1] == true)
6183 return 0;
6184
6185 afe_close_done[port_id & 0x1] = true;
6186 }
6187
6188 port_id = q6audio_convert_virtual_to_portid(port_id);
6189 index = q6audio_get_port_index(port_id);
6190 if (index < 0 || index >= AFE_MAX_PORTS) {
6191 pr_err("%s: AFE port index[%d] invalid!\n",
6192 __func__, index);
6193 return -EINVAL;
6194 }
6195 ret = q6audio_validate_port(port_id);
6196 if (ret < 0) {
6197 pr_warn("%s: Not a valid port id 0x%x ret %d\n",
6198 __func__, port_id, ret);
6199 return -EINVAL;
6200 }
6201
6202 mad_type = afe_port_get_mad_type(port_id);
6203 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
6204 mad_type);
6205 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
6206 pr_debug("%s: Turn off MAD\n", __func__);
6207 ret = afe_turn_onoff_hw_mad(mad_type, false);
6208 if (ret) {
6209 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
6210 __func__, ret);
6211 return ret;
6212 }
6213 } else {
6214 pr_debug("%s: Not a MAD port\n", __func__);
6215 }
6216
6217 port_index = afe_get_port_index(port_id);
6218 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
6219 this_afe.afe_sample_rates[port_index] = 0;
6220 this_afe.topology[port_index] = 0;
6221 this_afe.dev_acdb_id[port_index] = 0;
6222 } else {
6223 pr_err("%s: port %d\n", __func__, port_index);
6224 ret = -EINVAL;
6225 goto fail_cmd;
6226 }
6227
6228 if ((port_id == this_afe.aanc_info.aanc_tx_port) &&
6229 (this_afe.aanc_info.aanc_active)) {
6230 memset(&this_afe.aanc_info, 0x00, sizeof(this_afe.aanc_info));
6231 ret = afe_aanc_mod_enable(this_afe.apr, port_id, 0);
6232 if (ret)
6233 pr_err("%s: AFE mod disable failed %d\n",
6234 __func__, ret);
6235 }
6236
6237 /*
6238 * even if ramp down configuration failed it is not serious enough to
6239 * warrant bailaing out.
6240 */
6241 if (afe_spk_ramp_dn_cfg(port_id) < 0)
6242 pr_err("%s: ramp down configuration failed\n", __func__);
6243
6244 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6245 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6246 stop.hdr.pkt_size = sizeof(stop);
6247 stop.hdr.src_port = 0;
6248 stop.hdr.dest_port = 0;
6249 stop.hdr.token = index;
6250 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
6251 stop.port_id = q6audio_get_port_id(port_id);
6252 stop.reserved = 0;
6253
6254 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
6255 if (ret)
6256 pr_err("%s: AFE close failed %d\n", __func__, ret);
6257
6258fail_cmd:
6259 return ret;
6260}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306261EXPORT_SYMBOL(afe_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306262
6263int afe_set_digital_codec_core_clock(u16 port_id,
6264 struct afe_digital_clk_cfg *cfg)
6265{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006266 struct afe_digital_clk_cfg clk_cfg;
6267 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306268 int ret = 0;
6269
6270 if (!cfg) {
6271 pr_err("%s: clock cfg is NULL\n", __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006272 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306273 }
6274
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006275 memset(&clk_cfg, 0, sizeof(clk_cfg));
6276 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306277
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306278 /*default rx port is taken to enable the codec digital clock*/
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006279 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6280 param_hdr.instance_id = INSTANCE_ID_0;
6281 param_hdr.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
6282 param_hdr.param_size = sizeof(struct afe_digital_clk_cfg);
6283 clk_cfg = *cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306284
6285 pr_debug("%s: Minor version =0x%x clk val = %d\n"
6286 "clk root = 0x%x resrv = 0x%x\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006287 __func__, cfg->i2s_cfg_minor_version, cfg->clk_val,
6288 cfg->clk_root, cfg->reserved);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306289
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006290 ret = q6afe_pack_and_set_param_in_band(port_id,
6291 q6audio_get_port_index(port_id),
6292 param_hdr, (u8 *) &clk_cfg);
6293 if (ret < 0)
6294 pr_err("%s: AFE enable for port 0x%x ret %d\n", __func__,
6295 port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306296 return ret;
6297}
6298
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306299/**
6300 * afe_set_lpass_clock - Enable AFE lpass clock
6301 *
6302 * @port_id: AFE port id
6303 * @cfg: pointer to clk set struct
6304 *
6305 * Returns 0 on success, appropriate error code otherwise
6306 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306307int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg)
6308{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006309 struct afe_clk_cfg clk_cfg;
6310 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306311 int ret = 0;
6312
6313 if (!cfg) {
6314 pr_err("%s: clock cfg is NULL\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306315 return -EINVAL;
6316 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006317
6318 memset(&clk_cfg, 0, sizeof(clk_cfg));
6319 memset(&param_hdr, 0, sizeof(param_hdr));
6320
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306321 ret = q6audio_is_digital_pcm_interface(port_id);
6322 if (ret < 0) {
6323 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6324 __func__, ret);
6325 return -EINVAL;
6326 }
6327
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306328 mutex_lock(&this_afe.afe_cmd_lock);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006329 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6330 param_hdr.instance_id = INSTANCE_ID_0;
6331 param_hdr.param_id = AFE_PARAM_ID_LPAIF_CLK_CONFIG;
6332 param_hdr.param_size = sizeof(clk_cfg);
6333 clk_cfg = *cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306334
6335 pr_debug("%s: Minor version =0x%x clk val1 = %d\n"
6336 "clk val2 = %d, clk src = 0x%x\n"
6337 "clk root = 0x%x clk mode = 0x%x resrv = 0x%x\n"
6338 "port id = 0x%x\n",
6339 __func__, cfg->i2s_cfg_minor_version,
6340 cfg->clk_val1, cfg->clk_val2, cfg->clk_src,
6341 cfg->clk_root, cfg->clk_set_mode,
6342 cfg->reserved, q6audio_get_port_id(port_id));
6343
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006344 ret = q6afe_pack_and_set_param_in_band(port_id,
6345 q6audio_get_port_index(port_id),
6346 param_hdr, (u8 *) &clk_cfg);
6347 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306348 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6349 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306350
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306351 mutex_unlock(&this_afe.afe_cmd_lock);
6352 return ret;
6353}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306354EXPORT_SYMBOL(afe_set_lpass_clock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306355
6356/**
6357 * afe_set_lpass_clk_cfg - Set AFE clk config
6358 *
6359 * @index: port index
6360 * @cfg: pointer to clk set struct
6361 *
6362 * Returns 0 on success, appropriate error code otherwise
6363 */
6364int afe_set_lpass_clk_cfg(int index, struct afe_clk_set *cfg)
6365{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006366 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306367 int ret = 0;
6368
6369 if (!cfg) {
6370 pr_err("%s: clock cfg is NULL\n", __func__);
6371 ret = -EINVAL;
6372 return ret;
6373 }
6374
6375 if (index < 0 || index >= AFE_MAX_PORTS) {
6376 pr_err("%s: index[%d] invalid!\n", __func__, index);
6377 return -EINVAL;
6378 }
6379
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006380 memset(&param_hdr, 0, sizeof(param_hdr));
6381
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306382 ret = afe_q6_interface_prepare();
6383 if (ret != 0) {
6384 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
6385 return ret;
6386 }
6387
6388 mutex_lock(&this_afe.afe_cmd_lock);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006389 param_hdr.module_id = AFE_MODULE_CLOCK_SET;
6390 param_hdr.instance_id = INSTANCE_ID_0;
6391 param_hdr.param_id = AFE_PARAM_ID_CLOCK_SET;
6392 param_hdr.param_size = sizeof(struct afe_clk_set);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306393
6394
6395 pr_debug("%s: Minor version =0x%x clk id = %d\n"
6396 "clk freq (Hz) = %d, clk attri = 0x%x\n"
6397 "clk root = 0x%x clk enable = 0x%x\n",
6398 __func__, cfg->clk_set_minor_version,
6399 cfg->clk_id, cfg->clk_freq_in_hz, cfg->clk_attri,
6400 cfg->clk_root, cfg->enable);
6401
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006402 ret = q6afe_svc_pack_and_set_param_in_band(index, param_hdr,
6403 (u8 *) cfg);
6404 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306405 pr_err("%s: AFE clk cfg failed with ret %d\n",
6406 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306407
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306408 mutex_unlock(&this_afe.afe_cmd_lock);
6409 return ret;
6410}
6411EXPORT_SYMBOL(afe_set_lpass_clk_cfg);
6412
6413/**
6414 * afe_set_lpass_clock_v2 - Enable AFE lpass clock
6415 *
6416 * @port_id: AFE port id
6417 * @cfg: pointer to clk set struct
6418 *
6419 * Returns 0 on success, appropriate error code otherwise
6420 */
6421int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
6422{
6423 int index = 0;
6424 int ret = 0;
6425
6426 index = q6audio_get_port_index(port_id);
6427 if (index < 0 || index >= AFE_MAX_PORTS) {
6428 pr_err("%s: AFE port index[%d] invalid!\n",
6429 __func__, index);
6430 return -EINVAL;
6431 }
6432 ret = q6audio_is_digital_pcm_interface(port_id);
6433 if (ret < 0) {
6434 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6435 __func__, ret);
6436 return -EINVAL;
6437 }
6438
6439 ret = afe_set_lpass_clk_cfg(index, cfg);
6440 if (ret)
6441 pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
6442 __func__, ret);
6443
6444 return ret;
6445}
6446EXPORT_SYMBOL(afe_set_lpass_clock_v2);
6447
6448int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
6449 struct afe_digital_clk_cfg *cfg)
6450{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006451 struct afe_digital_clk_cfg clk_cfg;
6452 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306453 int ret = 0;
6454
6455 if (!cfg) {
6456 pr_err("%s: clock cfg is NULL\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306457 return -EINVAL;
6458 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006459
6460 memset(&clk_cfg, 0, sizeof(clk_cfg));
6461 memset(&param_hdr, 0, sizeof(param_hdr));
6462
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306463 ret = q6audio_is_digital_pcm_interface(port_id);
6464 if (ret < 0) {
6465 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6466 __func__, ret);
6467 return -EINVAL;
6468 }
6469
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006470 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6471 param_hdr.instance_id = INSTANCE_ID_0;
6472 param_hdr.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
6473 param_hdr.param_size = sizeof(clk_cfg);
6474 clk_cfg = *cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306475
6476 pr_debug("%s: Minor version =0x%x clk val = %d\n"
6477 "clk root = 0x%x resrv = 0x%x port id = 0x%x\n",
6478 __func__, cfg->i2s_cfg_minor_version,
6479 cfg->clk_val, cfg->clk_root, cfg->reserved,
6480 q6audio_get_port_id(port_id));
6481
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006482 ret = q6afe_pack_and_set_param_in_band(port_id,
6483 q6audio_get_port_index(port_id),
6484 param_hdr, (u8 *) &clk_cfg);
6485 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306486 pr_err("%s: AFE enable for port 0x0x%x ret %d\n",
6487 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306488
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306489 return ret;
6490}
6491
6492int afe_enable_lpass_core_shared_clock(u16 port_id, u32 enable)
6493{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006494 struct afe_param_id_lpass_core_shared_clk_cfg clk_cfg;
6495 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306496 int ret = 0;
6497
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006498 memset(&clk_cfg, 0, sizeof(clk_cfg));
6499 memset(&param_hdr, 0, sizeof(param_hdr));
6500
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306501 ret = q6audio_is_digital_pcm_interface(port_id);
6502 if (ret < 0) {
6503 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
6504 __func__, ret);
6505 return -EINVAL;
6506 }
6507
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306508 mutex_lock(&this_afe.afe_cmd_lock);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006509 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6510 param_hdr.instance_id = INSTANCE_ID_0;
6511 param_hdr.param_id = AFE_PARAM_ID_LPASS_CORE_SHARED_CLOCK_CONFIG;
6512 param_hdr.param_size = sizeof(clk_cfg);
6513 clk_cfg.lpass_core_shared_clk_cfg_minor_version =
6514 AFE_API_VERSION_LPASS_CORE_SHARED_CLK_CONFIG;
6515 clk_cfg.enable = enable;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306516
6517 pr_debug("%s: port id = %d, enable = %d\n",
6518 __func__, q6audio_get_port_id(port_id), enable);
6519
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006520 ret = q6afe_pack_and_set_param_in_band(port_id,
6521 q6audio_get_port_index(port_id),
6522 param_hdr, (u8 *) &clk_cfg);
6523 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306524 pr_err("%s: AFE enable for port 0x%x ret %d\n",
6525 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306526
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306527 mutex_unlock(&this_afe.afe_cmd_lock);
6528 return ret;
6529}
6530
6531int q6afe_check_osr_clk_freq(u32 freq)
6532{
6533 int ret = 0;
6534
6535 switch (freq) {
6536 case Q6AFE_LPASS_OSR_CLK_12_P288_MHZ:
Karthikeyan Mani0575b672017-12-10 23:50:37 -08006537 case Q6AFE_LPASS_OSR_CLK_9_P600_MHZ:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306538 case Q6AFE_LPASS_OSR_CLK_8_P192_MHZ:
6539 case Q6AFE_LPASS_OSR_CLK_6_P144_MHZ:
6540 case Q6AFE_LPASS_OSR_CLK_4_P096_MHZ:
6541 case Q6AFE_LPASS_OSR_CLK_3_P072_MHZ:
6542 case Q6AFE_LPASS_OSR_CLK_2_P048_MHZ:
6543 case Q6AFE_LPASS_OSR_CLK_1_P536_MHZ:
6544 case Q6AFE_LPASS_OSR_CLK_1_P024_MHZ:
6545 case Q6AFE_LPASS_OSR_CLK_768_kHZ:
6546 case Q6AFE_LPASS_OSR_CLK_512_kHZ:
6547 break;
6548 default:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006549 pr_err("%s: default freq 0x%x\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306550 __func__, freq);
6551 ret = -EINVAL;
6552 }
6553 return ret;
6554}
6555
6556int afe_get_sp_th_vi_ftm_data(struct afe_sp_th_vi_get_param *th_vi)
6557{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006558 struct param_hdr_v3 param_hdr;
6559 int port = SLIMBUS_4_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306560 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306561
6562 if (!th_vi) {
6563 pr_err("%s: Invalid params\n", __func__);
6564 goto done;
6565 }
6566 if (this_afe.vi_tx_port != -1)
6567 port = this_afe.vi_tx_port;
6568
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006569 memset(&param_hdr, 0, sizeof(param_hdr));
6570
6571 param_hdr.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
6572 param_hdr.instance_id = INSTANCE_ID_0;
6573 param_hdr.param_id = AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS;
6574 param_hdr.param_size = sizeof(struct afe_sp_th_vi_ftm_params);
6575
6576 ret = q6afe_get_params(port, NULL, &param_hdr);
6577 if (ret) {
6578 pr_err("%s: Failed to get TH VI FTM data\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306579 goto done;
6580 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006581
6582 th_vi->pdata = param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306583 memcpy(&th_vi->param, &this_afe.th_vi_resp.param,
6584 sizeof(this_afe.th_vi_resp.param));
6585 pr_debug("%s: DC resistance %d %d temp %d %d status %d %d\n",
6586 __func__, th_vi->param.dc_res_q24[SP_V2_SPKR_1],
6587 th_vi->param.dc_res_q24[SP_V2_SPKR_2],
6588 th_vi->param.temp_q22[SP_V2_SPKR_1],
6589 th_vi->param.temp_q22[SP_V2_SPKR_2],
6590 th_vi->param.status[SP_V2_SPKR_1],
6591 th_vi->param.status[SP_V2_SPKR_2]);
6592 ret = 0;
6593done:
6594 return ret;
6595}
6596
6597int afe_get_sp_ex_vi_ftm_data(struct afe_sp_ex_vi_get_param *ex_vi)
6598{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006599 struct param_hdr_v3 param_hdr;
6600 int port = SLIMBUS_4_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306601 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306602
6603 if (!ex_vi) {
6604 pr_err("%s: Invalid params\n", __func__);
6605 goto done;
6606 }
6607 if (this_afe.vi_tx_port != -1)
6608 port = this_afe.vi_tx_port;
6609
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006610 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306611
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006612 param_hdr.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
6613 param_hdr.instance_id = INSTANCE_ID_0;
6614 param_hdr.param_id = AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS;
6615 param_hdr.param_size = sizeof(struct afe_sp_ex_vi_ftm_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306616
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006617 ret = q6afe_get_params(port, NULL, &param_hdr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306618 if (ret < 0) {
6619 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006620 __func__, port, param_hdr.param_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306621 goto done;
6622 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006623
6624 ex_vi->pdata = param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306625 memcpy(&ex_vi->param, &this_afe.ex_vi_resp.param,
6626 sizeof(this_afe.ex_vi_resp.param));
6627 pr_debug("%s: freq %d %d resistance %d %d qfactor %d %d state %d %d\n",
6628 __func__, ex_vi->param.freq_q20[SP_V2_SPKR_1],
6629 ex_vi->param.freq_q20[SP_V2_SPKR_2],
6630 ex_vi->param.resis_q24[SP_V2_SPKR_1],
6631 ex_vi->param.resis_q24[SP_V2_SPKR_2],
6632 ex_vi->param.qmct_q24[SP_V2_SPKR_1],
6633 ex_vi->param.qmct_q24[SP_V2_SPKR_2],
6634 ex_vi->param.status[SP_V2_SPKR_1],
6635 ex_vi->param.status[SP_V2_SPKR_2]);
6636 ret = 0;
6637done:
6638 return ret;
6639}
6640
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306641/**
6642 * afe_get_av_dev_drift -
6643 * command to retrieve AV drift
6644 *
6645 * @timing_stats: timing stats to be updated with AV drift values
6646 * @port: AFE port ID
6647 *
6648 * Returns 0 on success or error on failure
6649 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306650int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
6651 u16 port)
6652{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006653 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306654 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306655
6656 if (!timing_stats) {
6657 pr_err("%s: Invalid params\n", __func__);
6658 goto exit;
6659 }
6660
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006661 memset(&param_hdr, 0, sizeof(param_hdr));
6662 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6663 param_hdr.instance_id = INSTANCE_ID_0;
6664 param_hdr.param_id = AFE_PARAM_ID_DEV_TIMING_STATS;
6665 param_hdr.param_size = sizeof(struct afe_param_id_dev_timing_stats);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306666
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006667 ret = q6afe_get_params(port, NULL, &param_hdr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306668 if (ret < 0) {
6669 pr_err("%s: get param port 0x%x param id[0x%x] failed %d\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006670 __func__, port, param_hdr.param_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306671 goto exit;
6672 }
6673
6674 memcpy(timing_stats, &this_afe.av_dev_drift_resp.timing_stats,
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006675 param_hdr.param_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306676 ret = 0;
6677exit:
6678 return ret;
6679}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306680EXPORT_SYMBOL(afe_get_av_dev_drift);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306681
6682int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp)
6683{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006684 struct param_hdr_v3 param_hdr;
6685 int port = SLIMBUS_4_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306686 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306687
6688 if (!calib_resp) {
6689 pr_err("%s: Invalid params\n", __func__);
6690 goto fail_cmd;
6691 }
6692 if (this_afe.vi_tx_port != -1)
6693 port = this_afe.vi_tx_port;
6694
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006695 memset(&param_hdr, 0, sizeof(param_hdr));
6696 param_hdr.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
6697 param_hdr.instance_id = INSTANCE_ID_0;
6698 param_hdr.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2;
6699 param_hdr.param_size = sizeof(struct afe_spkr_prot_get_vi_calib);
6700
6701 ret = q6afe_get_params(port, NULL, &param_hdr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306702 if (ret < 0) {
6703 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006704 __func__, port, param_hdr.param_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306705 goto fail_cmd;
6706 }
6707 memcpy(&calib_resp->res_cfg, &this_afe.calib_data.res_cfg,
6708 sizeof(this_afe.calib_data.res_cfg));
6709 pr_info("%s: state %s resistance %d %d\n", __func__,
6710 fbsp_state[calib_resp->res_cfg.th_vi_ca_state],
6711 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1],
6712 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]);
6713 ret = 0;
6714fail_cmd:
6715 return ret;
6716}
6717
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306718/**
6719 * afe_spk_prot_feed_back_cfg -
6720 * command to setup spk protection feedback config
6721 *
6722 * @src_port: source port id
6723 * @dst_port: destination port id
6724 * @l_ch: left speaker active or not
6725 * @r_ch: right speaker active or not
6726 * @enable: flag to enable or disable
6727 *
6728 * Returns 0 on success or error on failure
6729 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306730int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
6731 int l_ch, int r_ch, u32 enable)
6732{
6733 int ret = -EINVAL;
6734 union afe_spkr_prot_config prot_config;
6735 int index = 0;
6736
6737 if (!enable) {
6738 pr_debug("%s: Disable Feedback tx path", __func__);
6739 this_afe.vi_tx_port = -1;
6740 this_afe.vi_rx_port = -1;
6741 return 0;
6742 }
6743
6744 if ((q6audio_validate_port(src_port) < 0) ||
6745 (q6audio_validate_port(dst_port) < 0)) {
6746 pr_err("%s: invalid ports src 0x%x dst 0x%x",
6747 __func__, src_port, dst_port);
6748 goto fail_cmd;
6749 }
6750 if (!l_ch && !r_ch) {
6751 pr_err("%s: error ch values zero\n", __func__);
6752 goto fail_cmd;
6753 }
6754 pr_debug("%s: src_port 0x%x dst_port 0x%x l_ch %d r_ch %d\n",
6755 __func__, src_port, dst_port, l_ch, r_ch);
6756 memset(&prot_config, 0, sizeof(prot_config));
6757 prot_config.feedback_path_cfg.dst_portid =
6758 q6audio_get_port_id(dst_port);
6759 if (l_ch) {
6760 prot_config.feedback_path_cfg.chan_info[index++] = 1;
6761 prot_config.feedback_path_cfg.chan_info[index++] = 2;
6762 }
6763 if (r_ch) {
6764 prot_config.feedback_path_cfg.chan_info[index++] = 3;
6765 prot_config.feedback_path_cfg.chan_info[index++] = 4;
6766 }
6767 prot_config.feedback_path_cfg.num_channels = index;
6768 pr_debug("%s no of channels: %d\n", __func__, index);
6769 prot_config.feedback_path_cfg.minor_version = 1;
6770 ret = afe_spk_prot_prepare(src_port, dst_port,
6771 AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config);
6772fail_cmd:
6773 return ret;
6774}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306775EXPORT_SYMBOL(afe_spk_prot_feed_back_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306776
6777static int get_cal_type_index(int32_t cal_type)
6778{
6779 int ret = -EINVAL;
6780
6781 switch (cal_type) {
6782 case AFE_COMMON_RX_CAL_TYPE:
6783 ret = AFE_COMMON_RX_CAL;
6784 break;
6785 case AFE_COMMON_TX_CAL_TYPE:
6786 ret = AFE_COMMON_TX_CAL;
6787 break;
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05306788 case AFE_LSM_TX_CAL_TYPE:
6789 ret = AFE_LSM_TX_CAL;
6790 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306791 case AFE_AANC_CAL_TYPE:
6792 ret = AFE_AANC_CAL;
6793 break;
6794 case AFE_HW_DELAY_CAL_TYPE:
6795 ret = AFE_HW_DELAY_CAL;
6796 break;
6797 case AFE_FB_SPKR_PROT_CAL_TYPE:
6798 ret = AFE_FB_SPKR_PROT_CAL;
6799 break;
6800 case AFE_SIDETONE_CAL_TYPE:
6801 ret = AFE_SIDETONE_CAL;
6802 break;
6803 case AFE_SIDETONE_IIR_CAL_TYPE:
6804 ret = AFE_SIDETONE_IIR_CAL;
6805 break;
6806 case AFE_TOPOLOGY_CAL_TYPE:
6807 ret = AFE_TOPOLOGY_CAL;
6808 break;
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05306809 case AFE_LSM_TOPOLOGY_CAL_TYPE:
6810 ret = AFE_LSM_TOPOLOGY_CAL;
6811 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306812 case AFE_CUST_TOPOLOGY_CAL_TYPE:
6813 ret = AFE_CUST_TOPOLOGY_CAL;
6814 break;
6815 default:
6816 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
6817 }
6818 return ret;
6819}
6820
6821int afe_alloc_cal(int32_t cal_type, size_t data_size,
6822 void *data)
6823{
6824 int ret = 0;
6825 int cal_index;
6826
6827 cal_index = get_cal_type_index(cal_type);
6828 pr_debug("%s: cal_type = %d cal_index = %d\n",
6829 __func__, cal_type, cal_index);
6830
6831 if (cal_index < 0) {
6832 pr_err("%s: could not get cal index %d!\n",
6833 __func__, cal_index);
6834 ret = -EINVAL;
6835 goto done;
6836 }
6837
6838 ret = cal_utils_alloc_cal(data_size, data,
6839 this_afe.cal_data[cal_index], 0, NULL);
6840 if (ret < 0) {
6841 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
6842 __func__, ret, cal_type);
6843 ret = -EINVAL;
6844 goto done;
6845 }
6846done:
6847 return ret;
6848}
6849
6850static int afe_dealloc_cal(int32_t cal_type, size_t data_size,
6851 void *data)
6852{
6853 int ret = 0;
6854 int cal_index;
6855
6856 pr_debug("%s:\n", __func__);
6857
6858 cal_index = get_cal_type_index(cal_type);
6859 if (cal_index < 0) {
6860 pr_err("%s: could not get cal index %d!\n",
6861 __func__, cal_index);
6862 ret = -EINVAL;
6863 goto done;
6864 }
6865
6866 ret = cal_utils_dealloc_cal(data_size, data,
6867 this_afe.cal_data[cal_index]);
6868 if (ret < 0) {
6869 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
6870 __func__, ret, cal_type);
6871 ret = -EINVAL;
6872 goto done;
6873 }
6874done:
6875 return ret;
6876}
6877
6878static int afe_set_cal(int32_t cal_type, size_t data_size,
6879 void *data)
6880{
6881 int ret = 0;
6882 int cal_index;
6883
6884 pr_debug("%s:\n", __func__);
6885
6886 cal_index = get_cal_type_index(cal_type);
6887 if (cal_index < 0) {
6888 pr_err("%s: could not get cal index %d!\n",
6889 __func__, cal_index);
6890 ret = -EINVAL;
6891 goto done;
6892 }
6893
6894 ret = cal_utils_set_cal(data_size, data,
6895 this_afe.cal_data[cal_index], 0, NULL);
6896 if (ret < 0) {
6897 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
6898 __func__, ret, cal_type);
6899 ret = -EINVAL;
6900 goto done;
6901 }
6902
6903 if (cal_index == AFE_CUST_TOPOLOGY_CAL) {
6904 mutex_lock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
6905 this_afe.set_custom_topology = 1;
6906 pr_debug("%s:[AFE_CUSTOM_TOPOLOGY] ret = %d, cal type = %d!\n",
6907 __func__, ret, cal_type);
6908 mutex_unlock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
6909 }
6910
6911done:
6912 return ret;
6913}
6914
6915static struct cal_block_data *afe_find_hw_delay_by_path(
6916 struct cal_type_data *cal_type, int path)
6917{
6918 struct list_head *ptr, *next;
6919 struct cal_block_data *cal_block = NULL;
6920
6921 pr_debug("%s:\n", __func__);
6922
6923 list_for_each_safe(ptr, next,
6924 &cal_type->cal_blocks) {
6925
6926 cal_block = list_entry(ptr,
6927 struct cal_block_data, list);
6928
Vikram Panduranga770b8382017-09-27 12:17:36 -07006929 if (cal_utils_is_cal_stale(cal_block))
6930 continue;
6931
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306932 if (((struct audio_cal_info_hw_delay *)cal_block->cal_info)
6933 ->path == path) {
6934 return cal_block;
6935 }
6936 }
6937 return NULL;
6938}
6939
6940static int afe_get_cal_hw_delay(int32_t path,
6941 struct audio_cal_hw_delay_entry *entry)
6942{
6943 int ret = 0;
6944 int i;
6945 struct cal_block_data *cal_block = NULL;
6946 struct audio_cal_hw_delay_data *hw_delay_info = NULL;
6947
6948 pr_debug("%s:\n", __func__);
6949
6950 if (this_afe.cal_data[AFE_HW_DELAY_CAL] == NULL) {
6951 pr_err("%s: AFE_HW_DELAY_CAL not initialized\n", __func__);
6952 ret = -EINVAL;
6953 goto done;
6954 }
6955 if (entry == NULL) {
6956 pr_err("%s: entry is NULL\n", __func__);
6957 ret = -EINVAL;
6958 goto done;
6959 }
6960 if ((path >= MAX_PATH_TYPE) || (path < 0)) {
6961 pr_err("%s: bad path: %d\n",
6962 __func__, path);
6963 ret = -EINVAL;
6964 goto done;
6965 }
6966
6967 mutex_lock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
6968 cal_block = afe_find_hw_delay_by_path(
6969 this_afe.cal_data[AFE_HW_DELAY_CAL], path);
6970 if (cal_block == NULL)
6971 goto unlock;
6972
6973 hw_delay_info = &((struct audio_cal_info_hw_delay *)
6974 cal_block->cal_info)->data;
6975 if (hw_delay_info->num_entries > MAX_HW_DELAY_ENTRIES) {
6976 pr_err("%s: invalid num entries: %d\n",
6977 __func__, hw_delay_info->num_entries);
6978 ret = -EINVAL;
6979 goto unlock;
6980 }
6981
6982 for (i = 0; i < hw_delay_info->num_entries; i++) {
6983 if (hw_delay_info->entry[i].sample_rate ==
6984 entry->sample_rate) {
6985 entry->delay_usec = hw_delay_info->entry[i].delay_usec;
6986 break;
6987 }
6988 }
6989 if (i == hw_delay_info->num_entries) {
6990 pr_err("%s: Unable to find delay for sample rate %d\n",
6991 __func__, entry->sample_rate);
6992 ret = -EFAULT;
6993 goto unlock;
6994 }
Vikram Panduranga770b8382017-09-27 12:17:36 -07006995
6996 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306997 pr_debug("%s: Path = %d samplerate = %u usec = %u status %d\n",
6998 __func__, path, entry->sample_rate, entry->delay_usec, ret);
6999unlock:
7000 mutex_unlock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
7001done:
7002 return ret;
7003}
7004
7005static int afe_set_cal_sp_th_vi_ftm_cfg(int32_t cal_type, size_t data_size,
7006 void *data)
7007{
7008 int ret = 0;
7009 struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data;
7010
7011 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
7012 cal_data == NULL ||
7013 data_size != sizeof(*cal_data))
7014 goto done;
7015
7016 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7017 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7018 memcpy(&this_afe.th_ftm_cfg, &cal_data->cal_info,
7019 sizeof(this_afe.th_ftm_cfg));
7020 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7021done:
7022 return ret;
7023}
7024
7025static int afe_set_cal_sp_ex_vi_ftm_cfg(int32_t cal_type, size_t data_size,
7026 void *data)
7027{
7028 int ret = 0;
7029 struct audio_cal_type_sp_ex_vi_ftm_cfg *cal_data = data;
7030
7031 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
7032 cal_data == NULL ||
7033 data_size != sizeof(*cal_data))
7034 goto done;
7035
7036 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7037 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7038 memcpy(&this_afe.ex_ftm_cfg, &cal_data->cal_info,
7039 sizeof(this_afe.ex_ftm_cfg));
7040 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7041done:
7042 return ret;
7043}
7044
7045static int afe_set_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
7046 void *data)
7047{
7048 int ret = 0;
7049 struct audio_cal_type_fb_spk_prot_cfg *cal_data = data;
7050
7051 pr_debug("%s:\n", __func__);
7052
7053 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
7054 goto done;
7055 if (cal_data == NULL)
7056 goto done;
7057 if (data_size != sizeof(*cal_data))
7058 goto done;
7059
7060 if (cal_data->cal_info.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
7061 __pm_wakeup_event(&wl.ws, jiffies_to_msecs(WAKELOCK_TIMEOUT));
7062 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7063 memcpy(&this_afe.prot_cfg, &cal_data->cal_info,
7064 sizeof(this_afe.prot_cfg));
7065 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7066done:
7067 return ret;
7068}
7069
7070static int afe_get_cal_sp_th_vi_ftm_param(int32_t cal_type, size_t data_size,
7071 void *data)
7072{
7073 int i, ret = 0;
7074 struct audio_cal_type_sp_th_vi_param *cal_data = data;
7075 struct afe_sp_th_vi_get_param th_vi;
7076
7077 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7078 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
7079 cal_data == NULL ||
7080 data_size != sizeof(*cal_data))
7081 goto done;
7082
7083 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7084 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7085 cal_data->cal_info.status[i] = -EINVAL;
7086 cal_data->cal_info.r_dc_q24[i] = -1;
7087 cal_data->cal_info.temp_q22[i] = -1;
7088 }
7089 if (!afe_get_sp_th_vi_ftm_data(&th_vi)) {
7090 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7091 pr_debug("%s: ftm param status = %d\n",
7092 __func__, th_vi.param.status[i]);
7093 if (th_vi.param.status[i] == FBSP_IN_PROGRESS) {
7094 cal_data->cal_info.status[i] = -EAGAIN;
7095 } else if (th_vi.param.status[i] == FBSP_SUCCESS) {
7096 cal_data->cal_info.status[i] = 0;
7097 cal_data->cal_info.r_dc_q24[i] =
7098 th_vi.param.dc_res_q24[i];
7099 cal_data->cal_info.temp_q22[i] =
7100 th_vi.param.temp_q22[i];
7101 }
7102 }
7103 }
7104 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
7105done:
7106 return ret;
7107}
7108
7109static int afe_get_cal_sp_ex_vi_ftm_param(int32_t cal_type, size_t data_size,
7110 void *data)
7111{
7112 int i, ret = 0;
7113 struct audio_cal_type_sp_ex_vi_param *cal_data = data;
7114 struct afe_sp_ex_vi_get_param ex_vi;
7115
7116 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
7117 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
7118 cal_data == NULL ||
7119 data_size != sizeof(*cal_data))
7120 goto done;
7121
7122 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7123 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7124 cal_data->cal_info.status[i] = -EINVAL;
7125 cal_data->cal_info.freq_q20[i] = -1;
7126 cal_data->cal_info.resis_q24[i] = -1;
7127 cal_data->cal_info.qmct_q24[i] = -1;
7128 }
7129 if (!afe_get_sp_ex_vi_ftm_data(&ex_vi)) {
7130 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
7131 pr_debug("%s: ftm param status = %d\n",
7132 __func__, ex_vi.param.status[i]);
7133 if (ex_vi.param.status[i] == FBSP_IN_PROGRESS) {
7134 cal_data->cal_info.status[i] = -EAGAIN;
7135 } else if (ex_vi.param.status[i] == FBSP_SUCCESS) {
7136 cal_data->cal_info.status[i] = 0;
7137 cal_data->cal_info.freq_q20[i] =
7138 ex_vi.param.freq_q20[i];
7139 cal_data->cal_info.resis_q24[i] =
7140 ex_vi.param.resis_q24[i];
7141 cal_data->cal_info.qmct_q24[i] =
7142 ex_vi.param.qmct_q24[i];
7143 }
7144 }
7145 }
7146 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
7147done:
7148 return ret;
7149}
7150
7151static int afe_get_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
7152 void *data)
7153{
7154 int ret = 0;
7155 struct audio_cal_type_fb_spk_prot_status *cal_data = data;
7156 struct afe_spkr_prot_get_vi_calib calib_resp;
7157
7158 pr_debug("%s:\n", __func__);
7159
7160 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
7161 goto done;
7162 if (cal_data == NULL)
7163 goto done;
7164 if (data_size != sizeof(*cal_data))
7165 goto done;
7166
7167 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7168 if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATED) {
7169 cal_data->cal_info.r0[SP_V2_SPKR_1] =
7170 this_afe.prot_cfg.r0[SP_V2_SPKR_1];
7171 cal_data->cal_info.r0[SP_V2_SPKR_2] =
7172 this_afe.prot_cfg.r0[SP_V2_SPKR_2];
7173 cal_data->cal_info.status = 0;
7174 } else if (this_afe.prot_cfg.mode ==
7175 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
7176 /*Call AFE to query the status*/
7177 cal_data->cal_info.status = -EINVAL;
7178 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
7179 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
7180 if (!afe_spk_prot_get_calib_data(&calib_resp)) {
7181 if (calib_resp.res_cfg.th_vi_ca_state ==
7182 FBSP_IN_PROGRESS)
7183 cal_data->cal_info.status = -EAGAIN;
7184 else if (calib_resp.res_cfg.th_vi_ca_state ==
7185 FBSP_SUCCESS) {
7186 cal_data->cal_info.status = 0;
7187 cal_data->cal_info.r0[SP_V2_SPKR_1] =
7188 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_1];
7189 cal_data->cal_info.r0[SP_V2_SPKR_2] =
7190 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_2];
7191 }
7192 }
7193 if (!cal_data->cal_info.status) {
7194 this_afe.prot_cfg.mode =
7195 MSM_SPKR_PROT_CALIBRATED;
7196 this_afe.prot_cfg.r0[SP_V2_SPKR_1] =
7197 cal_data->cal_info.r0[SP_V2_SPKR_1];
7198 this_afe.prot_cfg.r0[SP_V2_SPKR_2] =
7199 cal_data->cal_info.r0[SP_V2_SPKR_2];
7200 }
7201 } else {
7202 /*Indicates calibration data is invalid*/
7203 cal_data->cal_info.status = -EINVAL;
7204 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
7205 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
7206 }
7207 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
7208 __pm_relax(&wl.ws);
7209done:
7210 return ret;
7211}
7212
7213static int afe_map_cal_data(int32_t cal_type,
7214 struct cal_block_data *cal_block)
7215{
7216 int ret = 0;
7217 int cal_index;
7218
7219 pr_debug("%s:\n", __func__);
7220
7221 cal_index = get_cal_type_index(cal_type);
7222 if (cal_index < 0) {
7223 pr_err("%s: could not get cal index %d!\n",
7224 __func__, cal_index);
7225 ret = -EINVAL;
7226 goto done;
7227 }
7228
7229
7230 mutex_lock(&this_afe.afe_cmd_lock);
7231 atomic_set(&this_afe.mem_map_cal_index, cal_index);
7232 ret = afe_cmd_memory_map(cal_block->cal_data.paddr,
7233 cal_block->map_data.map_size);
7234 atomic_set(&this_afe.mem_map_cal_index, -1);
7235 if (ret < 0) {
7236 pr_err("%s: mmap did not work! size = %zd ret %d\n",
7237 __func__,
7238 cal_block->map_data.map_size, ret);
7239 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
7240 __func__,
7241 &cal_block->cal_data.paddr,
7242 cal_block->map_data.map_size);
7243 mutex_unlock(&this_afe.afe_cmd_lock);
7244 goto done;
7245 }
7246 cal_block->map_data.q6map_handle = atomic_read(&this_afe.
7247 mem_map_cal_handles[cal_index]);
7248 mutex_unlock(&this_afe.afe_cmd_lock);
7249done:
7250 return ret;
7251}
7252
7253static int afe_unmap_cal_data(int32_t cal_type,
7254 struct cal_block_data *cal_block)
7255{
7256 int ret = 0;
7257 int cal_index;
7258
7259 pr_debug("%s:\n", __func__);
7260
7261 cal_index = get_cal_type_index(cal_type);
7262 if (cal_index < 0) {
7263 pr_err("%s: could not get cal index %d!\n",
7264 __func__, cal_index);
7265 ret = -EINVAL;
7266 goto done;
7267 }
7268
7269 if (cal_block == NULL) {
7270 pr_err("%s: Cal block is NULL!\n",
7271 __func__);
7272 goto done;
7273 }
7274
7275 if (cal_block->map_data.q6map_handle == 0) {
7276 pr_err("%s: Map handle is NULL, nothing to unmap\n",
7277 __func__);
7278 goto done;
7279 }
7280
7281 atomic_set(&this_afe.mem_map_cal_handles[cal_index],
7282 cal_block->map_data.q6map_handle);
7283 atomic_set(&this_afe.mem_map_cal_index, cal_index);
7284 ret = afe_cmd_memory_unmap_nowait(
7285 cal_block->map_data.q6map_handle);
7286 atomic_set(&this_afe.mem_map_cal_index, -1);
7287 if (ret < 0) {
7288 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
7289 __func__, cal_index, ret);
7290 }
7291 cal_block->map_data.q6map_handle = 0;
7292done:
7293 return ret;
7294}
7295
7296static void afe_delete_cal_data(void)
7297{
7298 pr_debug("%s:\n", __func__);
7299
7300 cal_utils_destroy_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data);
7301}
7302
7303static int afe_init_cal_data(void)
7304{
7305 int ret = 0;
7306 struct cal_type_info cal_type_info[] = {
7307 {{AFE_COMMON_RX_CAL_TYPE,
7308 {afe_alloc_cal, afe_dealloc_cal, NULL,
7309 afe_set_cal, NULL, NULL} },
7310 {afe_map_cal_data, afe_unmap_cal_data,
7311 cal_utils_match_buf_num} },
7312
7313 {{AFE_COMMON_TX_CAL_TYPE,
7314 {afe_alloc_cal, afe_dealloc_cal, NULL,
7315 afe_set_cal, NULL, NULL} },
7316 {afe_map_cal_data, afe_unmap_cal_data,
7317 cal_utils_match_buf_num} },
7318
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307319 {{AFE_LSM_TX_CAL_TYPE,
7320 {afe_alloc_cal, afe_dealloc_cal, NULL,
7321 afe_set_cal, NULL, NULL} },
7322 {afe_map_cal_data, afe_unmap_cal_data,
7323 cal_utils_match_buf_num} },
7324
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307325 {{AFE_AANC_CAL_TYPE,
7326 {afe_alloc_cal, afe_dealloc_cal, NULL,
7327 afe_set_cal, NULL, NULL} },
7328 {afe_map_cal_data, afe_unmap_cal_data,
7329 cal_utils_match_buf_num} },
7330
7331 {{AFE_FB_SPKR_PROT_CAL_TYPE,
7332 {NULL, NULL, NULL, afe_set_cal_fb_spkr_prot,
7333 afe_get_cal_fb_spkr_prot, NULL} },
7334 {NULL, NULL, cal_utils_match_buf_num} },
7335
7336 {{AFE_HW_DELAY_CAL_TYPE,
7337 {NULL, NULL, NULL,
7338 afe_set_cal, NULL, NULL} },
7339 {NULL, NULL, cal_utils_match_buf_num} },
7340
7341 {{AFE_SIDETONE_CAL_TYPE,
7342 {NULL, NULL, NULL,
7343 afe_set_cal, NULL, NULL} },
7344 {NULL, NULL, cal_utils_match_buf_num} },
7345
7346 {{AFE_SIDETONE_IIR_CAL_TYPE,
7347 {NULL, NULL, NULL,
7348 afe_set_cal, NULL, NULL} },
7349 {NULL, NULL, cal_utils_match_buf_num} },
7350
7351 {{AFE_TOPOLOGY_CAL_TYPE,
7352 {NULL, NULL, NULL,
7353 afe_set_cal, NULL, NULL} },
7354 {NULL, NULL,
7355 cal_utils_match_buf_num} },
7356
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307357 {{AFE_LSM_TOPOLOGY_CAL_TYPE,
7358 {NULL, NULL, NULL,
7359 afe_set_cal, NULL, NULL} },
7360 {NULL, NULL,
7361 cal_utils_match_buf_num} },
7362
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307363 {{AFE_CUST_TOPOLOGY_CAL_TYPE,
7364 {afe_alloc_cal, afe_dealloc_cal, NULL,
7365 afe_set_cal, NULL, NULL} },
7366 {afe_map_cal_data, afe_unmap_cal_data,
7367 cal_utils_match_buf_num} },
7368
7369 {{AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE,
7370 {NULL, NULL, NULL, afe_set_cal_sp_th_vi_ftm_cfg,
7371 afe_get_cal_sp_th_vi_ftm_param, NULL} },
7372 {NULL, NULL, cal_utils_match_buf_num} },
7373
7374 {{AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE,
7375 {NULL, NULL, NULL, afe_set_cal_sp_ex_vi_ftm_cfg,
7376 afe_get_cal_sp_ex_vi_ftm_param, NULL} },
7377 {NULL, NULL, cal_utils_match_buf_num} },
7378 };
7379 pr_debug("%s:\n", __func__);
7380
7381 ret = cal_utils_create_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data,
7382 cal_type_info);
7383 if (ret < 0) {
7384 pr_err("%s: could not create cal type! %d\n",
7385 __func__, ret);
7386 ret = -EINVAL;
7387 goto err;
7388 }
7389
7390 return ret;
7391err:
7392 afe_delete_cal_data();
7393 return ret;
7394}
7395
7396int afe_map_rtac_block(struct rtac_cal_block_data *cal_block)
7397{
7398 int result = 0;
7399
7400 pr_debug("%s:\n", __func__);
7401
7402 if (cal_block == NULL) {
7403 pr_err("%s: cal_block is NULL!\n",
7404 __func__);
7405 result = -EINVAL;
7406 goto done;
7407 }
7408
7409 if (cal_block->cal_data.paddr == 0) {
7410 pr_debug("%s: No address to map!\n",
7411 __func__);
7412 result = -EINVAL;
7413 goto done;
7414 }
7415
7416 if (cal_block->map_data.map_size == 0) {
7417 pr_debug("%s: map size is 0!\n",
7418 __func__);
7419 result = -EINVAL;
7420 goto done;
7421 }
7422
7423 result = afe_cmd_memory_map(cal_block->cal_data.paddr,
7424 cal_block->map_data.map_size);
7425 if (result < 0) {
7426 pr_err("%s: afe_cmd_memory_map failed for addr = 0x%pK, size = %d, err %d\n",
7427 __func__, &cal_block->cal_data.paddr,
7428 cal_block->map_data.map_size, result);
7429 return result;
7430 }
7431 cal_block->map_data.map_handle = this_afe.mmap_handle;
7432
7433done:
7434 return result;
7435}
7436
7437int afe_unmap_rtac_block(uint32_t *mem_map_handle)
7438{
7439 int result = 0;
7440
7441 pr_debug("%s:\n", __func__);
7442
7443 if (mem_map_handle == NULL) {
7444 pr_err("%s: Map handle is NULL, nothing to unmap\n",
7445 __func__);
7446 goto done;
7447 }
7448
7449 if (*mem_map_handle == 0) {
7450 pr_debug("%s: Map handle is 0, nothing to unmap\n",
7451 __func__);
7452 goto done;
7453 }
7454
7455 result = afe_cmd_memory_unmap(*mem_map_handle);
7456 if (result) {
7457 pr_err("%s: AFE memory unmap failed %d, handle 0x%x\n",
7458 __func__, result, *mem_map_handle);
7459 goto done;
7460 } else {
7461 *mem_map_handle = 0;
7462 }
7463
7464done:
7465 return result;
7466}
7467
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -07007468static void afe_release_uevent_data(struct kobject *kobj)
7469{
7470 struct audio_uevent_data *data = container_of(kobj,
7471 struct audio_uevent_data, kobj);
7472
7473 kfree(data);
7474}
7475
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307476int __init afe_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307477{
7478 int i = 0, ret;
7479
7480 atomic_set(&this_afe.state, 0);
7481 atomic_set(&this_afe.status, 0);
7482 atomic_set(&this_afe.mem_map_cal_index, -1);
7483 this_afe.apr = NULL;
7484 this_afe.dtmf_gen_rx_portid = -1;
7485 this_afe.mmap_handle = 0;
7486 this_afe.vi_tx_port = -1;
7487 this_afe.vi_rx_port = -1;
7488 this_afe.prot_cfg.mode = MSM_SPKR_PROT_DISABLED;
7489 this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
7490 this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
7491 mutex_init(&this_afe.afe_cmd_lock);
7492 for (i = 0; i < AFE_MAX_PORTS; i++) {
7493 this_afe.afe_cal_mode[i] = AFE_CAL_MODE_DEFAULT;
7494 this_afe.afe_sample_rates[i] = 0;
7495 this_afe.dev_acdb_id[i] = 0;
7496 init_waitqueue_head(&this_afe.wait[i]);
7497 }
7498 wakeup_source_init(&wl.ws, "spkr-prot");
7499 ret = afe_init_cal_data();
7500 if (ret)
7501 pr_err("%s: could not init cal data! %d\n", __func__, ret);
7502
7503 config_debug_fs_init();
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -07007504
7505 this_afe.uevent_data = kzalloc(sizeof(*(this_afe.uevent_data)), GFP_KERNEL);
7506 if (!this_afe.uevent_data)
7507 return -ENOMEM;
7508
7509 /*
7510 * Set release function to cleanup memory related to kobject
7511 * before initializing the kobject.
7512 */
7513 this_afe.uevent_data->ktype.release = afe_release_uevent_data;
7514 q6core_init_uevent_data(this_afe.uevent_data, "q6afe_uevent");
7515
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307516 return 0;
7517}
7518
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05307519void afe_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307520{
Laxminath Kasam30ad7512017-11-28 12:40:22 +05307521 if (this_afe.apr) {
7522 apr_reset(this_afe.apr);
7523 atomic_set(&this_afe.state, 0);
7524 this_afe.apr = NULL;
7525 rtac_set_afe_handle(this_afe.apr);
7526 }
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -07007527
7528 q6core_destroy_uevent_data(this_afe.uevent_data);
7529
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307530 afe_delete_cal_data();
7531
7532 config_debug_fs_exit();
7533 mutex_destroy(&this_afe.afe_cmd_lock);
7534 wakeup_source_trash(&wl.ws);
7535}