blob: fd66571dffbb367e2d3b13aa9bd957455c64fee0 [file] [log] [blame]
Meng Wang688a8672019-01-29 13:43:33 +08001// SPDX-License-Identifier: GPL-2.0-only
Josh Kirsch22533092019-01-17 16:01:08 -08002/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303 */
4#include <linux/slab.h>
5#include <linux/debugfs.h>
6#include <linux/kernel.h>
7#include <linux/kthread.h>
8#include <linux/uaccess.h>
9#include <linux/wait.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053010#include <linux/jiffies.h>
11#include <linux/sched.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053012#include <linux/delay.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053013#include <dsp/msm_audio_ion.h>
14#include <dsp/apr_audio-v2.h>
15#include <dsp/audio_cal_utils.h>
16#include <dsp/q6afe-v2.h>
17#include <dsp/q6audio-v2.h>
Vignesh Kulothungan85073c02018-01-26 10:27:56 -080018#include <dsp/q6common.h>
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -070019#include <dsp/q6core.h>
Vidyakumar Athota94bd8732018-02-28 17:13:35 -080020#include <dsp/msm-audio-event-notify.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053021#include <ipc/apr_tal.h>
22#include "adsp_err.h"
Mangesh Kunchamwar4e1e7182018-04-26 17:58:58 +053023#include "q6afecal-hwdep.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053024
25#define WAKELOCK_TIMEOUT 5000
26enum {
27 AFE_COMMON_RX_CAL = 0,
28 AFE_COMMON_TX_CAL,
Aditya Bavanari3889b4a2017-11-21 19:52:26 +053029 AFE_LSM_TX_CAL,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053030 AFE_AANC_CAL,
31 AFE_FB_SPKR_PROT_CAL,
32 AFE_HW_DELAY_CAL,
33 AFE_SIDETONE_CAL,
34 AFE_SIDETONE_IIR_CAL,
35 AFE_TOPOLOGY_CAL,
Aditya Bavanari3889b4a2017-11-21 19:52:26 +053036 AFE_LSM_TOPOLOGY_CAL,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053037 AFE_CUST_TOPOLOGY_CAL,
38 AFE_FB_SPKR_PROT_TH_VI_CAL,
39 AFE_FB_SPKR_PROT_EX_VI_CAL,
40 MAX_AFE_CAL_TYPES
41};
42
43enum fbsp_state {
44 FBSP_INCORRECT_OP_MODE,
45 FBSP_INACTIVE,
46 FBSP_WARMUP,
47 FBSP_IN_PROGRESS,
48 FBSP_SUCCESS,
49 FBSP_FAILED,
50 MAX_FBSP_STATE
51};
52
53static char fbsp_state[MAX_FBSP_STATE][50] = {
54 [FBSP_INCORRECT_OP_MODE] = "incorrect operation mode",
55 [FBSP_INACTIVE] = "port not started",
56 [FBSP_WARMUP] = "waiting for warmup",
57 [FBSP_IN_PROGRESS] = "in progress state",
58 [FBSP_SUCCESS] = "success",
59 [FBSP_FAILED] = "failed"
60};
61
Laxminath Kasam2e13d952019-02-20 15:05:39 +053062enum v_vali_state {
63 V_VALI_FAILED,
64 V_VALI_SUCCESS,
65 V_VALI_INCORRECT_OP_MODE,
66 V_VALI_INACTIVE,
67 V_VALI_WARMUP,
68 V_VALI_IN_PROGRESS,
69 MAX_V_VALI_STATE
70};
71
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053072enum {
73 USE_CALIBRATED_R0TO,
74 USE_SAFE_R0TO
75};
76
77enum {
78 QUICK_CALIB_DISABLE,
79 QUICK_CALIB_ENABLE
80};
81
82enum {
83 Q6AFE_MSM_SPKR_PROCESSING = 0,
84 Q6AFE_MSM_SPKR_CALIBRATION,
Laxminath Kasam2e13d952019-02-20 15:05:39 +053085 Q6AFE_MSM_SPKR_FTM_MODE,
86 Q6AFE_MSM_SPKR_V_VALI_MODE
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053087};
88
Chaithanya Krishna Bacharaju4a466532019-01-21 10:59:51 +053089enum {
90 APTX_AD_48 = 0,
91 APTX_AD_44_1 = 1
92};
93
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053094struct wlock {
95 struct wakeup_source ws;
96};
97
98static struct wlock wl;
99
100struct afe_ctl {
101 void *apr;
102 atomic_t state;
103 atomic_t status;
104 wait_queue_head_t wait[AFE_MAX_PORTS];
Ramprasad Katkam250075f2018-08-31 03:31:54 +0530105 wait_queue_head_t wait_wakeup;
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +0530106 struct task_struct *task;
107 wait_queue_head_t lpass_core_hw_wait;
108 uint32_t lpass_hw_core_client_hdl;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530109 void (*tx_cb)(uint32_t opcode,
110 uint32_t token, uint32_t *payload, void *priv);
111 void (*rx_cb)(uint32_t opcode,
112 uint32_t token, uint32_t *payload, void *priv);
113 void *tx_private_data;
114 void *rx_private_data;
115 uint32_t mmap_handle;
116
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530117 void (*pri_spdif_tx_cb)(uint32_t opcode,
118 uint32_t token, uint32_t *payload, void *priv);
119 void (*sec_spdif_tx_cb)(uint32_t opcode,
120 uint32_t token, uint32_t *payload, void *priv);
121 void *pri_spdif_tx_private_data;
122 void *sec_spdif_tx_private_data;
Ralf Herz044e4762018-09-10 11:04:16 +0200123 int pri_spdif_config_change;
124 int sec_spdif_config_change;
125 struct work_struct afe_spdif_work;
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530126
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530127 int topology[AFE_MAX_PORTS];
128 struct cal_type_data *cal_data[MAX_AFE_CAL_TYPES];
129
130 atomic_t mem_map_cal_handles[MAX_AFE_CAL_TYPES];
131 atomic_t mem_map_cal_index;
132 u32 afe_cal_mode[AFE_MAX_PORTS];
133
134 u16 dtmf_gen_rx_portid;
135 struct audio_cal_info_spk_prot_cfg prot_cfg;
136 struct afe_spkr_prot_calib_get_resp calib_data;
137 struct audio_cal_info_sp_th_vi_ftm_cfg th_ftm_cfg;
Laxminath Kasam2e13d952019-02-20 15:05:39 +0530138 struct audio_cal_info_sp_th_vi_v_vali_cfg v_vali_cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530139 struct audio_cal_info_sp_ex_vi_ftm_cfg ex_ftm_cfg;
140 struct afe_sp_th_vi_get_param_resp th_vi_resp;
Laxminath Kasam2e13d952019-02-20 15:05:39 +0530141 struct afe_sp_th_vi_v_vali_get_param_resp th_vi_v_vali_resp;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530142 struct afe_sp_ex_vi_get_param_resp ex_vi_resp;
Aditya Bavanari740b4832018-12-24 18:46:12 +0530143 struct afe_sp_rx_tmax_xmax_logging_resp xt_logging_resp;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530144 struct afe_av_dev_drift_get_param_resp av_dev_drift_resp;
Chaithanya Krishna Bacharaju8c6a1842018-11-16 15:02:39 +0530145 struct afe_doa_tracking_mon_get_param_resp doa_tracking_mon_resp;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530146 int vi_tx_port;
147 int vi_rx_port;
148 uint32_t afe_sample_rates[AFE_MAX_PORTS];
149 struct aanc_data aanc_info;
150 struct mutex afe_cmd_lock;
151 int set_custom_topology;
152 int dev_acdb_id[AFE_MAX_PORTS];
153 routing_cb rt_cb;
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -0700154 struct audio_uevent_data *uevent_data;
Mangesh Kunchamwar4e1e7182018-04-26 17:58:58 +0530155 /* cal info for AFE */
156 struct afe_fw_info *fw_data;
157 u32 island_mode[AFE_MAX_PORTS];
158 struct vad_config vad_cfg[AFE_MAX_PORTS];
Xiaoyu Yebaf28392018-06-22 15:22:27 -0700159 struct work_struct afe_dc_work;
Ramprasad Katkam250075f2018-08-31 03:31:54 +0530160 struct notifier_block event_notifier;
Laxminath Kasam36384ec2019-02-18 21:57:19 +0530161 /* FTM spk params */
162 uint32_t initial_cal;
163 uint32_t v_vali_flag;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530164};
165
166static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
167static unsigned long afe_configured_cmd;
168
169static struct afe_ctl this_afe;
170
171#define TIMEOUT_MS 1000
172#define Q6AFE_MAX_VOLUME 0x3FFF
173
174static int pcm_afe_instance[2];
175static int proxy_afe_instance[2];
176bool afe_close_done[2] = {true, true};
177
178#define SIZEOF_CFG_CMD(y) \
179 (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
180
181static int afe_get_cal_hw_delay(int32_t path,
182 struct audio_cal_hw_delay_entry *entry);
183static int remap_cal_data(struct cal_block_data *cal_block, int cal_index);
184
Laxminath Kasam36384ec2019-02-18 21:57:19 +0530185int afe_get_spk_initial_cal(void)
186{
187 return this_afe.initial_cal;
188}
189
190void afe_get_spk_r0(int *spk_r0)
191{
192 uint16_t i = 0;
193
194 for (; i < SP_V2_NUM_MAX_SPKRS; i++)
195 spk_r0[i] = this_afe.prot_cfg.r0[i];
196}
197
198void afe_get_spk_t0(int *spk_t0)
199{
200 uint16_t i = 0;
201
202 for (; i < SP_V2_NUM_MAX_SPKRS; i++)
203 spk_t0[i] = this_afe.prot_cfg.t0[i];
204}
205
206int afe_get_spk_v_vali_flag(void)
207{
208 return this_afe.v_vali_flag;
209}
210
211void afe_get_spk_v_vali_sts(int *spk_v_vali_sts)
212{
213 uint16_t i = 0;
214
215 for (; i < SP_V2_NUM_MAX_SPKRS; i++)
216 spk_v_vali_sts[i] =
217 this_afe.th_vi_v_vali_resp.param.status[i];
218}
219
220void afe_set_spk_initial_cal(int initial_cal)
221{
222 this_afe.initial_cal = initial_cal;
223}
224
225void afe_set_spk_v_vali_flag(int v_vali_flag)
226{
227 this_afe.v_vali_flag = v_vali_flag;
228}
229
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530230int afe_get_topology(int port_id)
231{
232 int topology;
233 int port_index = afe_get_port_index(port_id);
234
235 if ((port_index < 0) || (port_index >= AFE_MAX_PORTS)) {
236 pr_err("%s: Invalid port index %d\n", __func__, port_index);
237 topology = -EINVAL;
238 goto done;
239 }
240
241 topology = this_afe.topology[port_index];
242done:
243 return topology;
244}
245
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530246/**
247 * afe_set_aanc_info -
248 * Update AFE AANC info
249 *
250 * @q6_aanc_info: AFE AANC info params
251 *
252 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530253void afe_set_aanc_info(struct aanc_data *q6_aanc_info)
254{
255 this_afe.aanc_info.aanc_active = q6_aanc_info->aanc_active;
256 this_afe.aanc_info.aanc_rx_port = q6_aanc_info->aanc_rx_port;
257 this_afe.aanc_info.aanc_tx_port = q6_aanc_info->aanc_tx_port;
258
259 pr_debug("%s: aanc active is %d rx port is 0x%x, tx port is 0x%x\n",
260 __func__,
261 this_afe.aanc_info.aanc_active,
262 this_afe.aanc_info.aanc_rx_port,
263 this_afe.aanc_info.aanc_tx_port);
264}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530265EXPORT_SYMBOL(afe_set_aanc_info);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530266
267static void afe_callback_debug_print(struct apr_client_data *data)
268{
269 uint32_t *payload;
270
271 payload = data->payload;
272
273 if (data->payload_size >= 8)
274 pr_debug("%s: code = 0x%x PL#0[0x%x], PL#1[0x%x], size = %d\n",
275 __func__, data->opcode, payload[0], payload[1],
276 data->payload_size);
277 else if (data->payload_size >= 4)
278 pr_debug("%s: code = 0x%x PL#0[0x%x], size = %d\n",
279 __func__, data->opcode, payload[0],
280 data->payload_size);
281 else
282 pr_debug("%s: code = 0x%x, size = %d\n",
283 __func__, data->opcode, data->payload_size);
284}
285
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800286static void av_dev_drift_afe_cb_handler(uint32_t opcode, uint32_t *payload,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530287 uint32_t payload_size)
288{
289 u32 param_id;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800290 size_t expected_size =
291 sizeof(u32) + sizeof(struct afe_param_id_dev_timing_stats);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530292
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800293 /* Get param ID depending on command type */
294 param_id = (opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) ? payload[3] :
295 payload[2];
296 if (param_id != AFE_PARAM_ID_DEV_TIMING_STATS) {
297 pr_err("%s: Unrecognized param ID %d\n", __func__, param_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530298 return;
299 }
300
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800301 switch (opcode) {
302 case AFE_PORT_CMDRSP_GET_PARAM_V2:
303 expected_size += sizeof(struct param_hdr_v1);
304 if (payload_size < expected_size) {
305 pr_err("%s: Error: received size %d, expected size %zu\n",
306 __func__, payload_size, expected_size);
307 return;
308 }
309 /* Repack response to add IID */
310 this_afe.av_dev_drift_resp.status = payload[0];
311 this_afe.av_dev_drift_resp.pdata.module_id = payload[1];
312 this_afe.av_dev_drift_resp.pdata.instance_id = INSTANCE_ID_0;
313 this_afe.av_dev_drift_resp.pdata.param_id = payload[2];
314 this_afe.av_dev_drift_resp.pdata.param_size = payload[3];
315 memcpy(&this_afe.av_dev_drift_resp.timing_stats, &payload[4],
316 sizeof(struct afe_param_id_dev_timing_stats));
317 break;
318 case AFE_PORT_CMDRSP_GET_PARAM_V3:
319 expected_size += sizeof(struct param_hdr_v3);
320 if (payload_size < expected_size) {
321 pr_err("%s: Error: received size %d, expected size %zu\n",
322 __func__, payload_size, expected_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530323 return;
324 }
325 memcpy(&this_afe.av_dev_drift_resp, payload,
326 sizeof(this_afe.av_dev_drift_resp));
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800327 break;
328 default:
329 pr_err("%s: Unrecognized command %d\n", __func__, opcode);
330 return;
331 }
332
333 if (!this_afe.av_dev_drift_resp.status) {
334 atomic_set(&this_afe.state, 0);
335 } else {
Chaithanya Krishna Bacharaju8c6a1842018-11-16 15:02:39 +0530336 pr_debug("%s: av_dev_drift_resp status: %d\n", __func__,
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800337 this_afe.av_dev_drift_resp.status);
338 atomic_set(&this_afe.state, -1);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530339 }
340}
341
Chaithanya Krishna Bacharaju8c6a1842018-11-16 15:02:39 +0530342static void doa_tracking_mon_afe_cb_handler(uint32_t opcode, uint32_t *payload,
343 uint32_t payload_size)
344{
345 size_t expected_size =
346 sizeof(u32) + sizeof(struct doa_tracking_mon_param);
347
348 switch (opcode) {
349 case AFE_PORT_CMDRSP_GET_PARAM_V2:
350 expected_size += sizeof(struct param_hdr_v1);
351 if (payload_size < expected_size) {
352 pr_err("%s: Error: received size %d, expected size %zu\n",
353 __func__, payload_size, expected_size);
354 return;
355 }
356 /* Repack response to add IID */
357 this_afe.doa_tracking_mon_resp.status = payload[0];
358 this_afe.doa_tracking_mon_resp.pdata.module_id = payload[1];
359 this_afe.doa_tracking_mon_resp.pdata.instance_id =
360 INSTANCE_ID_0;
361 this_afe.doa_tracking_mon_resp.pdata.param_id = payload[2];
362 this_afe.doa_tracking_mon_resp.pdata.param_size = payload[3];
363 memcpy(&this_afe.doa_tracking_mon_resp.doa, &payload[4],
364 sizeof(struct doa_tracking_mon_param));
365 break;
366 case AFE_PORT_CMDRSP_GET_PARAM_V3:
367 expected_size += sizeof(struct param_hdr_v3);
368 if (payload_size < expected_size) {
369 pr_err("%s: Error: received size %d, expected size %zu\n",
370 __func__, payload_size, expected_size);
371 return;
372 }
373 memcpy(&this_afe.doa_tracking_mon_resp, payload,
374 sizeof(this_afe.doa_tracking_mon_resp));
375 break;
376 default:
377 pr_err("%s: Unrecognized command %d\n", __func__, opcode);
378 return;
379 }
380
381 if (!this_afe.doa_tracking_mon_resp.status) {
382 atomic_set(&this_afe.state, 0);
383 } else {
384 pr_debug("%s: doa_tracking_mon_resp status: %d\n", __func__,
385 this_afe.doa_tracking_mon_resp.status);
386 atomic_set(&this_afe.state, -1);
387 }
388}
389
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800390static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
391 uint32_t payload_size)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530392{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800393 struct param_hdr_v3 param_hdr;
394 u32 *data_dest = NULL;
395 u32 *data_start = NULL;
396 size_t expected_size = sizeof(u32);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530397
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800398 memset(&param_hdr, 0, sizeof(param_hdr));
399
400 /* Set command specific details */
401 switch (opcode) {
402 case AFE_PORT_CMDRSP_GET_PARAM_V2:
403 expected_size += sizeof(struct param_hdr_v1);
404 param_hdr.module_id = payload[1];
405 param_hdr.instance_id = INSTANCE_ID_0;
406 param_hdr.param_id = payload[2];
407 param_hdr.param_size = payload[3];
408 data_start = &payload[4];
409 break;
410 case AFE_PORT_CMDRSP_GET_PARAM_V3:
411 expected_size += sizeof(struct param_hdr_v3);
412 memcpy(&param_hdr, &payload[1], sizeof(struct param_hdr_v3));
413 data_start = &payload[5];
414 break;
415 default:
416 pr_err("%s: Unrecognized command %d\n", __func__, opcode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530417 return -EINVAL;
418 }
419
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800420 switch (param_hdr.param_id) {
421 case AFE_PARAM_ID_CALIB_RES_CFG_V2:
422 expected_size += sizeof(struct asm_calib_res_cfg);
423 data_dest = (u32 *) &this_afe.calib_data;
424 break;
425 case AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS:
426 expected_size += sizeof(struct afe_sp_th_vi_ftm_params);
427 data_dest = (u32 *) &this_afe.th_vi_resp;
428 break;
Laxminath Kasam2e13d952019-02-20 15:05:39 +0530429 case AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_PARAMS:
430 expected_size += sizeof(struct afe_sp_th_vi_v_vali_params);
431 data_dest = (u32 *) &this_afe.th_vi_v_vali_resp;
432 break;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800433 case AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS:
434 expected_size += sizeof(struct afe_sp_ex_vi_ftm_params);
435 data_dest = (u32 *) &this_afe.ex_vi_resp;
436 break;
Aditya Bavanari740b4832018-12-24 18:46:12 +0530437 case AFE_PARAM_ID_SP_RX_TMAX_XMAX_LOGGING:
438 expected_size += sizeof(
439 struct afe_sp_rx_tmax_xmax_logging_param);
440 data_dest = (u32 *) &this_afe.xt_logging_resp;
441 break;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800442 default:
443 pr_err("%s: Unrecognized param ID %d\n", __func__,
444 param_hdr.param_id);
445 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530446 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800447
448 if (payload_size < expected_size) {
449 pr_err("%s: Error: received size %d, expected size %zu for param %d\n",
450 __func__, payload_size, expected_size,
451 param_hdr.param_id);
452 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530453 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800454
455 data_dest[0] = payload[0];
456 memcpy(&data_dest[1], &param_hdr, sizeof(struct param_hdr_v3));
457 memcpy(&data_dest[5], data_start, param_hdr.param_size);
458
459 if (!data_dest[0]) {
460 atomic_set(&this_afe.state, 0);
461 } else {
462 pr_debug("%s: status: %d", __func__, data_dest[0]);
463 atomic_set(&this_afe.state, -1);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530464 }
465
466 return 0;
467}
468
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800469static void afe_notify_dc_presence(void)
470{
Vidyakumar Athota968be0a2018-07-12 16:39:44 -0700471 pr_debug("%s: DC detected\n", __func__);
Xiaoyu Yebaf28392018-06-22 15:22:27 -0700472 msm_aud_evt_notifier_call_chain(MSM_AUD_DC_EVENT, NULL);
473
474 schedule_work(&this_afe.afe_dc_work);
475}
476
477static void afe_notify_dc_presence_work_fn(struct work_struct *work)
478{
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -0700479 int ret = 0;
480 char event[] = "DC_PRESENCE=TRUE";
481
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -0700482 ret = q6core_send_uevent(this_afe.uevent_data, event);
483 if (ret)
Xiaoyu Yebaf28392018-06-22 15:22:27 -0700484 pr_err("%s: Send UEvent %s failed :%d\n",
485 __func__, event, ret);
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800486}
487
Ramprasad Katkam250075f2018-08-31 03:31:54 +0530488static int afe_aud_event_notify(struct notifier_block *self,
489 unsigned long action, void *data)
490{
491 switch (action) {
492 case SWR_WAKE_IRQ_REGISTER:
493 afe_send_cmd_wakeup_register(data, true);
494 break;
495 case SWR_WAKE_IRQ_DEREGISTER:
496 afe_send_cmd_wakeup_register(data, false);
497 break;
498 default:
499 pr_err("%s: invalid event type: %lu\n", __func__, action);
500 return -EINVAL;
501 }
502
503 return 0;
504}
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530505
Ralf Herz044e4762018-09-10 11:04:16 +0200506static void afe_notify_spdif_fmt_update_work_fn(struct work_struct *work)
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530507{
508 int ret = 0;
Ralf Herz044e4762018-09-10 11:04:16 +0200509 char event_pri[] = "PRI_SPDIF_TX=MEDIA_CONFIG_CHANGE";
510 char event_sec[] = "SEC_SPDIF_TX=MEDIA_CONFIG_CHANGE";
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530511
Ralf Herz044e4762018-09-10 11:04:16 +0200512 if (this_afe.pri_spdif_config_change) {
513 this_afe.pri_spdif_config_change = 0;
514 ret = q6core_send_uevent(this_afe.uevent_data, event_pri);
515 if (ret)
516 pr_err("%s: Send UEvent %s failed :%d\n",
517 __func__, event_pri, ret);
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530518 }
Ralf Herz044e4762018-09-10 11:04:16 +0200519 if (this_afe.sec_spdif_config_change) {
520 this_afe.sec_spdif_config_change = 0;
521 ret = q6core_send_uevent(this_afe.uevent_data, event_sec);
522 if (ret)
523 pr_err("%s: Send UEvent %s failed :%d\n",
524 __func__, event_sec, ret);
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530525 }
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530526}
527
528static void afe_notify_spdif_fmt_update(void *payload)
529{
530 struct afe_port_mod_evt_rsp_hdr *evt_pl;
531
532 evt_pl = (struct afe_port_mod_evt_rsp_hdr *)payload;
Ralf Herz044e4762018-09-10 11:04:16 +0200533 if (evt_pl->port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX)
534 this_afe.pri_spdif_config_change = 1;
535 else
536 this_afe.sec_spdif_config_change = 1;
537
538 schedule_work(&this_afe.afe_spdif_work);
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530539}
540
Xiaojun Sangcf353ed2019-01-15 16:49:02 +0800541static bool afe_token_is_valid(uint32_t token)
542{
543 if (token >= AFE_MAX_PORTS) {
544 pr_err("%s: token %d is invalid.\n", __func__, token);
545 return false;
546 }
547 return true;
548}
549
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530550static int32_t afe_callback(struct apr_client_data *data, void *priv)
551{
552 if (!data) {
553 pr_err("%s: Invalid param data\n", __func__);
554 return -EINVAL;
555 }
556 if (data->opcode == RESET_EVENTS) {
557 pr_debug("%s: reset event = %d %d apr[%pK]\n",
558 __func__,
559 data->reset_event, data->reset_proc, this_afe.apr);
560
561 cal_utils_clear_cal_block_q6maps(MAX_AFE_CAL_TYPES,
562 this_afe.cal_data);
563
564 /* Reset the custom topology mode: to resend again to AFE. */
565 mutex_lock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
566 this_afe.set_custom_topology = 1;
567 mutex_unlock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
568 rtac_clear_mapping(AFE_RTAC_CAL);
569
570 if (this_afe.apr) {
571 apr_reset(this_afe.apr);
572 atomic_set(&this_afe.state, 0);
573 this_afe.apr = NULL;
574 rtac_set_afe_handle(this_afe.apr);
575 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530576
577 /*
578 * Pass reset events to proxy driver, if cb is registered
579 */
580 if (this_afe.tx_cb) {
581 this_afe.tx_cb(data->opcode, data->token,
582 data->payload,
583 this_afe.tx_private_data);
584 this_afe.tx_cb = NULL;
585 }
586 if (this_afe.rx_cb) {
587 this_afe.rx_cb(data->opcode, data->token,
588 data->payload,
589 this_afe.rx_private_data);
590 this_afe.rx_cb = NULL;
591 }
592
593 return 0;
594 }
595 afe_callback_debug_print(data);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800596 if (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V2 ||
597 data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530598 uint32_t *payload = data->payload;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800599 uint32_t param_id;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530600
601 if (!payload || (data->token >= AFE_MAX_PORTS)) {
602 pr_err("%s: Error: size %d payload %pK token %d\n",
603 __func__, data->payload_size,
604 payload, data->token);
605 return -EINVAL;
606 }
607
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800608 param_id = (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) ?
609 payload[3] :
610 payload[2];
Chaithanya Krishna Bacharaju8c6a1842018-11-16 15:02:39 +0530611 if (param_id == AUDPROC_PARAM_ID_FFV_DOA_TRACKING_MONITOR) {
612 doa_tracking_mon_afe_cb_handler(data->opcode,
613 data->payload, data->payload_size);
614 } else if (param_id == AFE_PARAM_ID_DEV_TIMING_STATS) {
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800615 av_dev_drift_afe_cb_handler(data->opcode, data->payload,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530616 data->payload_size);
617 } else {
618 if (rtac_make_afe_callback(data->payload,
619 data->payload_size))
620 return 0;
621
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800622 if (sp_make_afe_callback(data->opcode, data->payload,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530623 data->payload_size))
624 return -EINVAL;
625 }
Xiaojun Sangcf353ed2019-01-15 16:49:02 +0800626 if (afe_token_is_valid(data->token))
627 wake_up(&this_afe.wait[data->token]);
628 else
629 return -EINVAL;
Ramprasad Katkam250075f2018-08-31 03:31:54 +0530630 } else if (data->opcode == AFE_EVENT_MBHC_DETECTION_SW_WA) {
631 msm_aud_evt_notifier_call_chain(SWR_WAKE_IRQ_EVENT, NULL);
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +0530632 } else if (data->opcode ==
633 AFE_CMD_RSP_REMOTE_LPASS_CORE_HW_VOTE_REQUEST) {
634 uint32_t *payload = data->payload;
635
636 pr_debug("%s: AFE_CMD_RSP_REMOTE_LPASS_CORE_HW_VOTE_REQUEST handle %d\n",
637 __func__, payload[0]);
638 this_afe.lpass_hw_core_client_hdl = payload[0];
639 atomic_set(&this_afe.state, 0);
640 atomic_set(&this_afe.status, 0);
641 wake_up(&this_afe.lpass_core_hw_wait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530642 } else if (data->payload_size) {
643 uint32_t *payload;
644 uint16_t port_id = 0;
645
646 payload = data->payload;
647 if (data->opcode == APR_BASIC_RSP_RESULT) {
648 pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x token=%d\n",
649 __func__, data->opcode,
650 payload[0], payload[1], data->token);
651 /* payload[1] contains the error status for response */
652 if (payload[1] != 0) {
653 atomic_set(&this_afe.status, payload[1]);
654 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
655 __func__, payload[0], payload[1]);
656 }
657 switch (payload[0]) {
658 case AFE_PORT_CMD_SET_PARAM_V2:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800659 case AFE_PORT_CMD_SET_PARAM_V3:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530660 if (rtac_make_afe_callback(payload,
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800661 data->payload_size))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530662 return 0;
663 case AFE_PORT_CMD_DEVICE_STOP:
664 case AFE_PORT_CMD_DEVICE_START:
665 case AFE_PSEUDOPORT_CMD_START:
666 case AFE_PSEUDOPORT_CMD_STOP:
667 case AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS:
668 case AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS:
669 case AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER:
670 case AFE_PORTS_CMD_DTMF_CTL:
671 case AFE_SVC_CMD_SET_PARAM:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800672 case AFE_SVC_CMD_SET_PARAM_V2:
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800673 case AFE_PORT_CMD_MOD_EVENT_CFG:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530674 atomic_set(&this_afe.state, 0);
Xiaojun Sangcf353ed2019-01-15 16:49:02 +0800675 if (afe_token_is_valid(data->token))
676 wake_up(&this_afe.wait[data->token]);
677 else
678 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530679 break;
680 case AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER:
681 break;
682 case AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2:
683 port_id = RT_PROXY_PORT_001_TX;
684 break;
685 case AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2:
686 port_id = RT_PROXY_PORT_001_RX;
687 break;
688 case AFE_CMD_ADD_TOPOLOGIES:
689 atomic_set(&this_afe.state, 0);
Xiaojun Sangcf353ed2019-01-15 16:49:02 +0800690 if (afe_token_is_valid(data->token))
691 wake_up(&this_afe.wait[data->token]);
692 else
693 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530694 pr_debug("%s: AFE_CMD_ADD_TOPOLOGIES cmd 0x%x\n",
695 __func__, payload[1]);
696 break;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800697 case AFE_PORT_CMD_GET_PARAM_V2:
698 case AFE_PORT_CMD_GET_PARAM_V3:
699 /*
700 * Should only come here if there is an APR
701 * error or malformed APR packet. Otherwise
702 * response will be returned as
703 * AFE_PORT_CMDRSP_GET_PARAM_V2/3
704 */
705 pr_debug("%s: AFE Get Param opcode 0x%x token 0x%x src %d dest %d\n",
706 __func__, data->opcode, data->token,
707 data->src_port, data->dest_port);
708 if (payload[1] != 0) {
709 pr_err("%s: AFE Get Param failed with error %d\n",
710 __func__, payload[1]);
711 if (rtac_make_afe_callback(
712 payload,
713 data->payload_size))
714 return 0;
715 }
716 atomic_set(&this_afe.state, payload[1]);
Xiaojun Sangcf353ed2019-01-15 16:49:02 +0800717 if (afe_token_is_valid(data->token))
718 wake_up(&this_afe.wait[data->token]);
719 else
720 return -EINVAL;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -0800721 break;
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +0530722 case AFE_CMD_REMOTE_LPASS_CORE_HW_VOTE_REQUEST:
723 case AFE_CMD_REMOTE_LPASS_CORE_HW_DEVOTE_REQUEST:
724 atomic_set(&this_afe.state, 0);
725 wake_up(&this_afe.lpass_core_hw_wait);
726 break;
Ramprasad Katkam250075f2018-08-31 03:31:54 +0530727 case AFE_SVC_CMD_EVENT_CFG:
728 atomic_set(&this_afe.state, payload[1]);
729 wake_up(&this_afe.wait_wakeup);
730 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530731 default:
732 pr_err("%s: Unknown cmd 0x%x\n", __func__,
733 payload[0]);
734 break;
735 }
736 } else if (data->opcode ==
737 AFE_SERVICE_CMDRSP_SHARED_MEM_MAP_REGIONS) {
738 pr_debug("%s: mmap_handle: 0x%x, cal index %d\n",
739 __func__, payload[0],
740 atomic_read(&this_afe.mem_map_cal_index));
741 if (atomic_read(&this_afe.mem_map_cal_index) != -1)
742 atomic_set(&this_afe.mem_map_cal_handles[
743 atomic_read(
744 &this_afe.mem_map_cal_index)],
745 (uint32_t)payload[0]);
746 else
747 this_afe.mmap_handle = payload[0];
748 atomic_set(&this_afe.state, 0);
Xiaojun Sangcf353ed2019-01-15 16:49:02 +0800749 if (afe_token_is_valid(data->token))
750 wake_up(&this_afe.wait[data->token]);
751 else
752 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530753 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
754 port_id = (uint16_t)(0x0000FFFF & payload[0]);
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800755 } else if (data->opcode == AFE_PORT_MOD_EVENT) {
756 u32 flag_dc_presence[2];
757 uint32_t *payload = data->payload;
758 struct afe_port_mod_evt_rsp_hdr *evt_pl =
759 (struct afe_port_mod_evt_rsp_hdr *)payload;
760
761 if (!payload || (data->token >= AFE_MAX_PORTS)) {
762 pr_err("%s: Error: size %d payload %pK token %d\n",
763 __func__, data->payload_size,
764 payload, data->token);
765 return -EINVAL;
766 }
767 if ((evt_pl->module_id == AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI) &&
768 (evt_pl->event_id == AFE_PORT_SP_DC_DETECTION_EVENT) &&
769 (evt_pl->payload_size == sizeof(flag_dc_presence))) {
770
771 memcpy(&flag_dc_presence,
Vidyakumar Athota968be0a2018-07-12 16:39:44 -0700772 (uint8_t *)payload +
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800773 sizeof(struct afe_port_mod_evt_rsp_hdr),
774 evt_pl->payload_size);
775 if (flag_dc_presence[0] == 1 ||
776 flag_dc_presence[1] == 1) {
777 afe_notify_dc_presence();
778 }
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530779 } else if (evt_pl->port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) {
780 if (this_afe.pri_spdif_tx_cb) {
781 this_afe.pri_spdif_tx_cb(data->opcode,
782 data->token, data->payload,
783 this_afe.pri_spdif_tx_private_data);
784 }
785 afe_notify_spdif_fmt_update(data->payload);
786 } else if (evt_pl->port_id == AFE_PORT_ID_SECONDARY_SPDIF_TX) {
787 if (this_afe.sec_spdif_tx_cb) {
788 this_afe.sec_spdif_tx_cb(data->opcode,
789 data->token, data->payload,
790 this_afe.sec_spdif_tx_private_data);
791 }
792 afe_notify_spdif_fmt_update(data->payload);
Vidyakumar Athota94bd8732018-02-28 17:13:35 -0800793 } else {
794 pr_debug("%s: mod ID = 0x%x event_id = 0x%x\n",
795 __func__, evt_pl->module_id,
796 evt_pl->event_id);
797 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530798 }
799 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
800 switch (port_id) {
801 case RT_PROXY_PORT_001_TX: {
802 if (this_afe.tx_cb) {
803 this_afe.tx_cb(data->opcode, data->token,
804 data->payload,
805 this_afe.tx_private_data);
806 }
807 break;
808 }
809 case RT_PROXY_PORT_001_RX: {
810 if (this_afe.rx_cb) {
811 this_afe.rx_cb(data->opcode, data->token,
812 data->payload,
813 this_afe.rx_private_data);
814 }
815 break;
816 }
817 default:
818 pr_debug("%s: default case 0x%x\n", __func__, port_id);
819 break;
820 }
821 }
822 return 0;
823}
824
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530825/**
826 * afe_get_port_type -
827 * Retrieve AFE port type whether RX or TX
828 *
829 * @port_id: AFE Port ID number
830 *
Mangesh Kunchamwar8c706ab2018-04-04 17:48:46 +0530831 * Returns RX/TX type.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530832 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530833int afe_get_port_type(u16 port_id)
834{
Mangesh Kunchamwar8c706ab2018-04-04 17:48:46 +0530835 int ret = MSM_AFE_PORT_TYPE_RX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530836
Vikram Pandurangadfae8ef2018-06-26 15:44:10 -0700837 switch (port_id) {
838 case VOICE_RECORD_RX:
839 case VOICE_RECORD_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530840 ret = MSM_AFE_PORT_TYPE_TX;
Vikram Pandurangadfae8ef2018-06-26 15:44:10 -0700841 break;
842 case VOICE_PLAYBACK_TX:
843 case VOICE2_PLAYBACK_TX:
Mangesh Kunchamwar8c706ab2018-04-04 17:48:46 +0530844 ret = MSM_AFE_PORT_TYPE_RX;
Vikram Pandurangadfae8ef2018-06-26 15:44:10 -0700845 break;
846 default:
847 /* Odd numbered ports are TX and Rx are Even numbered */
848 if (port_id & 0x1)
849 ret = MSM_AFE_PORT_TYPE_TX;
850 else
851 ret = MSM_AFE_PORT_TYPE_RX;
852 break;
853 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530854
855 return ret;
856}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530857EXPORT_SYMBOL(afe_get_port_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530858
859int afe_sizeof_cfg_cmd(u16 port_id)
860{
861 int ret_size;
862
863 switch (port_id) {
864 case PRIMARY_I2S_RX:
865 case PRIMARY_I2S_TX:
866 case SECONDARY_I2S_RX:
867 case SECONDARY_I2S_TX:
868 case MI2S_RX:
869 case MI2S_TX:
870 case AFE_PORT_ID_PRIMARY_MI2S_RX:
871 case AFE_PORT_ID_PRIMARY_MI2S_TX:
872 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
873 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
874 case AFE_PORT_ID_QUINARY_MI2S_RX:
875 case AFE_PORT_ID_QUINARY_MI2S_TX:
876 ret_size = SIZEOF_CFG_CMD(afe_param_id_i2s_cfg);
877 break;
878 case HDMI_RX:
879 case DISPLAY_PORT_RX:
880 ret_size =
881 SIZEOF_CFG_CMD(afe_param_id_hdmi_multi_chan_audio_cfg);
882 break;
Ralf Herzcc29b9e2018-07-17 20:19:04 +0530883 case AFE_PORT_ID_PRIMARY_SPDIF_RX:
884 case AFE_PORT_ID_PRIMARY_SPDIF_TX:
885 case AFE_PORT_ID_SECONDARY_SPDIF_RX:
886 case AFE_PORT_ID_SECONDARY_SPDIF_TX:
887 ret_size =
888 SIZEOF_CFG_CMD(afe_param_id_spdif_cfg_v2);
889 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530890 case SLIMBUS_0_RX:
891 case SLIMBUS_0_TX:
892 case SLIMBUS_1_RX:
893 case SLIMBUS_1_TX:
894 case SLIMBUS_2_RX:
895 case SLIMBUS_2_TX:
896 case SLIMBUS_3_RX:
897 case SLIMBUS_3_TX:
898 case SLIMBUS_4_RX:
899 case SLIMBUS_4_TX:
900 case SLIMBUS_5_RX:
901 case SLIMBUS_5_TX:
902 case SLIMBUS_6_RX:
903 case SLIMBUS_6_TX:
904 case SLIMBUS_7_RX:
905 case SLIMBUS_7_TX:
906 case SLIMBUS_8_RX:
907 case SLIMBUS_8_TX:
Surendar Karkab0dd21f2018-09-28 18:53:50 +0530908 case SLIMBUS_9_RX:
909 case SLIMBUS_9_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530910 ret_size = SIZEOF_CFG_CMD(afe_param_id_slimbus_cfg);
911 break;
912 case VOICE_PLAYBACK_TX:
913 case VOICE2_PLAYBACK_TX:
914 case VOICE_RECORD_RX:
915 case VOICE_RECORD_TX:
916 ret_size = SIZEOF_CFG_CMD(afe_param_id_pseudo_port_cfg);
917 break;
918 case RT_PROXY_PORT_001_RX:
919 case RT_PROXY_PORT_001_TX:
920 ret_size = SIZEOF_CFG_CMD(afe_param_id_rt_proxy_port_cfg);
921 break;
922 case AFE_PORT_ID_USB_RX:
923 case AFE_PORT_ID_USB_TX:
924 ret_size = SIZEOF_CFG_CMD(afe_param_id_usb_audio_cfg);
925 break;
Mangesh Kunchamwar8c706ab2018-04-04 17:48:46 +0530926 case AFE_PORT_ID_WSA_CODEC_DMA_RX_0:
927 case AFE_PORT_ID_WSA_CODEC_DMA_TX_0:
928 case AFE_PORT_ID_WSA_CODEC_DMA_RX_1:
929 case AFE_PORT_ID_WSA_CODEC_DMA_TX_1:
930 case AFE_PORT_ID_WSA_CODEC_DMA_TX_2:
931 case AFE_PORT_ID_VA_CODEC_DMA_TX_0:
932 case AFE_PORT_ID_VA_CODEC_DMA_TX_1:
Xiaoyu Ye8341eef2019-01-03 14:57:47 -0800933 case AFE_PORT_ID_VA_CODEC_DMA_TX_2:
Aditya Bavanari348a4a62018-05-16 21:48:45 +0530934 case AFE_PORT_ID_RX_CODEC_DMA_RX_0:
935 case AFE_PORT_ID_TX_CODEC_DMA_TX_0:
936 case AFE_PORT_ID_RX_CODEC_DMA_RX_1:
937 case AFE_PORT_ID_TX_CODEC_DMA_TX_1:
938 case AFE_PORT_ID_RX_CODEC_DMA_RX_2:
939 case AFE_PORT_ID_TX_CODEC_DMA_TX_2:
940 case AFE_PORT_ID_RX_CODEC_DMA_RX_3:
941 case AFE_PORT_ID_TX_CODEC_DMA_TX_3:
942 case AFE_PORT_ID_RX_CODEC_DMA_RX_4:
943 case AFE_PORT_ID_TX_CODEC_DMA_TX_4:
944 case AFE_PORT_ID_RX_CODEC_DMA_RX_5:
945 case AFE_PORT_ID_TX_CODEC_DMA_TX_5:
946 case AFE_PORT_ID_RX_CODEC_DMA_RX_6:
947 case AFE_PORT_ID_RX_CODEC_DMA_RX_7:
Mangesh Kunchamwar8c706ab2018-04-04 17:48:46 +0530948 ret_size = SIZEOF_CFG_CMD(afe_param_id_cdc_dma_cfg_t);
949 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530950 case AFE_PORT_ID_PRIMARY_PCM_RX:
951 case AFE_PORT_ID_PRIMARY_PCM_TX:
952 case AFE_PORT_ID_SECONDARY_PCM_RX:
953 case AFE_PORT_ID_SECONDARY_PCM_TX:
954 case AFE_PORT_ID_TERTIARY_PCM_RX:
955 case AFE_PORT_ID_TERTIARY_PCM_TX:
956 case AFE_PORT_ID_QUATERNARY_PCM_RX:
957 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +0530958 case AFE_PORT_ID_QUINARY_PCM_RX:
959 case AFE_PORT_ID_QUINARY_PCM_TX:
Dieter Lueckingfa7687b2018-09-28 14:21:44 +0200960 case AFE_PORT_ID_SENARY_PCM_RX:
961 case AFE_PORT_ID_SENARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530962 default:
963 pr_debug("%s: default case 0x%x\n", __func__, port_id);
964 ret_size = SIZEOF_CFG_CMD(afe_param_id_pcm_cfg);
965 break;
966 }
967 return ret_size;
968}
969
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530970/**
971 * afe_q6_interface_prepare -
972 * wrapper API to check Q6 AFE registered to APR otherwise registers
973 *
974 * Returns 0 on success or error on failure.
975 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530976int afe_q6_interface_prepare(void)
977{
978 int ret = 0;
979
980 pr_debug("%s:\n", __func__);
981
982 if (this_afe.apr == NULL) {
983 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
984 0xFFFFFFFF, &this_afe);
985 if (this_afe.apr == NULL) {
986 pr_err("%s: Unable to register AFE\n", __func__);
Laxminath Kasamc910c022018-04-04 10:59:57 +0530987 ret = -ENETRESET;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530988 }
989 rtac_set_afe_handle(this_afe.apr);
990 }
991 return ret;
992}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530993EXPORT_SYMBOL(afe_q6_interface_prepare);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530994
995/*
996 * afe_apr_send_pkt : returns 0 on success, negative otherwise.
997 */
998static int afe_apr_send_pkt(void *data, wait_queue_head_t *wait)
999{
1000 int ret;
1001
1002 if (wait)
1003 atomic_set(&this_afe.state, 1);
1004 atomic_set(&this_afe.status, 0);
1005 ret = apr_send_pkt(this_afe.apr, data);
1006 if (ret > 0) {
1007 if (wait) {
1008 ret = wait_event_timeout(*wait,
1009 (atomic_read(&this_afe.state) == 0),
Vidyakumar Athotaaade87e2018-10-26 17:28:46 -07001010 msecs_to_jiffies(2 * TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301011 if (!ret) {
1012 ret = -ETIMEDOUT;
1013 } else if (atomic_read(&this_afe.status) > 0) {
1014 pr_err("%s: DSP returned error[%s]\n", __func__,
1015 adsp_err_get_err_str(atomic_read(
1016 &this_afe.status)));
1017 ret = adsp_err_get_lnx_err_code(
1018 atomic_read(&this_afe.status));
1019 } else {
1020 ret = 0;
1021 }
1022 } else {
1023 ret = 0;
1024 }
1025 } else if (ret == 0) {
1026 pr_err("%s: packet not transmitted\n", __func__);
1027 /* apr_send_pkt can return 0 when nothing is transmitted */
1028 ret = -EINVAL;
1029 }
1030
1031 pr_debug("%s: leave %d\n", __func__, ret);
1032 return ret;
1033}
1034
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001035/* This function shouldn't be called directly. Instead call q6afe_set_params. */
1036static int q6afe_set_params_v2(u16 port_id, int index,
1037 struct mem_mapping_hdr *mem_hdr,
1038 u8 *packed_param_data, u32 packed_data_size)
1039{
1040 struct afe_port_cmd_set_param_v2 *set_param = NULL;
1041 uint32_t size = sizeof(struct afe_port_cmd_set_param_v2);
1042 int rc = 0;
1043
1044 if (packed_param_data != NULL)
1045 size += packed_data_size;
1046 set_param = kzalloc(size, GFP_KERNEL);
1047 if (set_param == NULL)
1048 return -ENOMEM;
1049
1050 set_param->apr_hdr.hdr_field =
1051 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1052 APR_PKT_VER);
1053 set_param->apr_hdr.pkt_size = size;
1054 set_param->apr_hdr.src_port = 0;
1055 set_param->apr_hdr.dest_port = 0;
1056 set_param->apr_hdr.token = index;
1057 set_param->apr_hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1058 set_param->port_id = port_id;
1059 if (packed_data_size > U16_MAX) {
1060 pr_err("%s: Invalid data size for set params V2 %d\n", __func__,
1061 packed_data_size);
1062 rc = -EINVAL;
1063 goto done;
1064 }
1065 set_param->payload_size = packed_data_size;
1066 if (mem_hdr != NULL) {
1067 set_param->mem_hdr = *mem_hdr;
1068 } else if (packed_param_data != NULL) {
1069 memcpy(&set_param->param_data, packed_param_data,
1070 packed_data_size);
1071 } else {
1072 pr_err("%s: Both memory header and param data are NULL\n",
1073 __func__);
1074 rc = -EINVAL;
1075 goto done;
1076 }
1077
1078 rc = afe_apr_send_pkt(set_param, &this_afe.wait[index]);
1079done:
1080 kfree(set_param);
1081 return rc;
1082}
1083
1084/* This function shouldn't be called directly. Instead call q6afe_set_params. */
1085static int q6afe_set_params_v3(u16 port_id, int index,
1086 struct mem_mapping_hdr *mem_hdr,
1087 u8 *packed_param_data, u32 packed_data_size)
1088{
1089 struct afe_port_cmd_set_param_v3 *set_param = NULL;
1090 uint32_t size = sizeof(struct afe_port_cmd_set_param_v3);
1091 int rc = 0;
1092
1093 if (packed_param_data != NULL)
1094 size += packed_data_size;
1095 set_param = kzalloc(size, GFP_KERNEL);
1096 if (set_param == NULL)
1097 return -ENOMEM;
1098
1099 set_param->apr_hdr.hdr_field =
1100 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1101 APR_PKT_VER);
1102 set_param->apr_hdr.pkt_size = size;
1103 set_param->apr_hdr.src_port = 0;
1104 set_param->apr_hdr.dest_port = 0;
1105 set_param->apr_hdr.token = index;
1106 set_param->apr_hdr.opcode = AFE_PORT_CMD_SET_PARAM_V3;
1107 set_param->port_id = port_id;
1108 set_param->payload_size = packed_data_size;
1109 if (mem_hdr != NULL) {
1110 set_param->mem_hdr = *mem_hdr;
1111 } else if (packed_param_data != NULL) {
1112 memcpy(&set_param->param_data, packed_param_data,
1113 packed_data_size);
1114 } else {
1115 pr_err("%s: Both memory header and param data are NULL\n",
1116 __func__);
1117 rc = -EINVAL;
1118 goto done;
1119 }
1120
1121 rc = afe_apr_send_pkt(set_param, &this_afe.wait[index]);
1122done:
1123 kfree(set_param);
1124 return rc;
1125}
1126
1127static int q6afe_set_params(u16 port_id, int index,
1128 struct mem_mapping_hdr *mem_hdr,
1129 u8 *packed_param_data, u32 packed_data_size)
1130{
1131 int ret = 0;
1132
1133 ret = afe_q6_interface_prepare();
1134 if (ret != 0) {
1135 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
1136 return ret;
1137 }
1138
1139 port_id = q6audio_get_port_id(port_id);
1140 ret = q6audio_validate_port(port_id);
1141 if (ret < 0) {
1142 pr_err("%s: Not a valid port id = 0x%x ret %d\n", __func__,
1143 port_id, ret);
1144 return -EINVAL;
1145 }
1146
1147 if (index < 0 || index >= AFE_MAX_PORTS) {
1148 pr_err("%s: AFE port index[%d] invalid\n", __func__, index);
1149 return -EINVAL;
1150 }
1151
1152 if (q6common_is_instance_id_supported())
1153 return q6afe_set_params_v3(port_id, index, mem_hdr,
1154 packed_param_data, packed_data_size);
1155 else
1156 return q6afe_set_params_v2(port_id, index, mem_hdr,
1157 packed_param_data, packed_data_size);
1158}
1159
1160static int q6afe_pack_and_set_param_in_band(u16 port_id, int index,
1161 struct param_hdr_v3 param_hdr,
1162 u8 *param_data)
1163{
1164 u8 *packed_param_data = NULL;
1165 int packed_data_size = sizeof(union param_hdrs) + param_hdr.param_size;
1166 int ret;
1167
1168 packed_param_data = kzalloc(packed_data_size, GFP_KERNEL);
1169 if (packed_param_data == NULL)
1170 return -ENOMEM;
1171
1172 ret = q6common_pack_pp_params(packed_param_data, &param_hdr, param_data,
1173 &packed_data_size);
1174 if (ret) {
1175 pr_err("%s: Failed to pack param header and data, error %d\n",
1176 __func__, ret);
1177 goto fail_cmd;
1178 }
1179
1180 ret = q6afe_set_params(port_id, index, NULL, packed_param_data,
1181 packed_data_size);
1182
1183fail_cmd:
1184 kfree(packed_param_data);
1185 return ret;
1186}
1187
Sudheer Papothiaf431ad2018-05-04 05:06:11 +05301188static int q6afe_set_aanc_level(void)
1189{
1190 struct param_hdr_v3 param_hdr;
1191 struct afe_param_id_aanc_noise_reduction aanc_noise_level;
1192 int ret = 0;
1193 uint16_t tx_port = 0;
1194
1195 if (!this_afe.aanc_info.aanc_active)
1196 return -EINVAL;
1197
1198 pr_debug("%s: level: %d\n", __func__, this_afe.aanc_info.level);
1199 memset(&aanc_noise_level, 0, sizeof(aanc_noise_level));
1200 aanc_noise_level.minor_version = 1;
1201 aanc_noise_level.ad_beta = this_afe.aanc_info.level;
1202
1203 memset(&param_hdr, 0, sizeof(param_hdr));
1204 param_hdr.module_id = AFE_MODULE_AANC;
1205 param_hdr.instance_id = INSTANCE_ID_0;
1206 param_hdr.param_id = AFE_PARAM_ID_AANC_NOISE_REDUCTION;
1207 param_hdr.param_size = sizeof(struct afe_param_id_aanc_noise_reduction);
1208
1209 tx_port = this_afe.aanc_info.aanc_tx_port;
1210 ret = q6afe_pack_and_set_param_in_band(tx_port,
1211 q6audio_get_port_index(tx_port),
1212 param_hdr,
1213 (u8 *) &aanc_noise_level);
1214 if (ret)
1215 pr_err("%s: AANC noise level enable failed for tx_port 0x%x ret %d\n",
1216 __func__, tx_port, ret);
1217 return ret;
1218}
1219
1220/**
1221 * afe_set_aanc_noise_level - controls aanc noise reduction strength
1222 *
1223 * @level: Noise level to be controlled
1224 *
1225 * Returns 0 on success or error on failure.
1226 */
1227int afe_set_aanc_noise_level(int level)
1228{
1229 int ret = 0;
1230
1231 if (this_afe.aanc_info.level == level)
1232 return ret;
1233
1234 mutex_lock(&this_afe.afe_cmd_lock);
1235 this_afe.aanc_info.level = level;
1236 ret = q6afe_set_aanc_level();
1237 mutex_unlock(&this_afe.afe_cmd_lock);
1238
1239 return ret;
1240}
1241EXPORT_SYMBOL(afe_set_aanc_noise_level);
1242
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001243/* This function shouldn't be called directly. Instead call q6afe_get_param. */
1244static int q6afe_get_params_v2(u16 port_id, int index,
1245 struct mem_mapping_hdr *mem_hdr,
1246 struct param_hdr_v3 *param_hdr)
1247{
1248 struct afe_port_cmd_get_param_v2 afe_get_param;
1249 u32 param_size = param_hdr->param_size;
1250
1251 memset(&afe_get_param, 0, sizeof(afe_get_param));
1252 afe_get_param.apr_hdr.hdr_field =
1253 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1254 APR_PKT_VER);
1255 afe_get_param.apr_hdr.pkt_size = sizeof(afe_get_param) + param_size;
1256 afe_get_param.apr_hdr.src_port = 0;
1257 afe_get_param.apr_hdr.dest_port = 0;
1258 afe_get_param.apr_hdr.token = index;
1259 afe_get_param.apr_hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
1260 afe_get_param.port_id = port_id;
1261 afe_get_param.payload_size = sizeof(struct param_hdr_v1) + param_size;
1262 if (mem_hdr != NULL)
1263 afe_get_param.mem_hdr = *mem_hdr;
1264 /* Set MID and PID in command */
1265 afe_get_param.module_id = param_hdr->module_id;
1266 afe_get_param.param_id = param_hdr->param_id;
1267 /* Set param header in payload */
1268 afe_get_param.param_hdr.module_id = param_hdr->module_id;
1269 afe_get_param.param_hdr.param_id = param_hdr->param_id;
1270 afe_get_param.param_hdr.param_size = param_size;
1271
1272 return afe_apr_send_pkt(&afe_get_param, &this_afe.wait[index]);
1273}
1274
1275/* This function shouldn't be called directly. Instead call q6afe_get_param. */
1276static int q6afe_get_params_v3(u16 port_id, int index,
1277 struct mem_mapping_hdr *mem_hdr,
1278 struct param_hdr_v3 *param_hdr)
1279{
1280 struct afe_port_cmd_get_param_v3 afe_get_param;
1281
1282 memset(&afe_get_param, 0, sizeof(afe_get_param));
1283 afe_get_param.apr_hdr.hdr_field =
1284 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1285 APR_PKT_VER);
1286 afe_get_param.apr_hdr.pkt_size = sizeof(afe_get_param);
1287 afe_get_param.apr_hdr.src_port = 0;
1288 afe_get_param.apr_hdr.dest_port = 0;
1289 afe_get_param.apr_hdr.token = index;
1290 afe_get_param.apr_hdr.opcode = AFE_PORT_CMD_GET_PARAM_V3;
1291 afe_get_param.port_id = port_id;
1292 if (mem_hdr != NULL)
1293 afe_get_param.mem_hdr = *mem_hdr;
1294 /* Set param header in command, no payload in V3 */
1295 afe_get_param.param_hdr = *param_hdr;
1296
1297 return afe_apr_send_pkt(&afe_get_param, &this_afe.wait[index]);
1298}
1299
1300/*
1301 * Calling functions copy param data directly from this_afe. Do not copy data
1302 * back to caller here.
1303 */
1304static int q6afe_get_params(u16 port_id, struct mem_mapping_hdr *mem_hdr,
1305 struct param_hdr_v3 *param_hdr)
1306{
1307 int index;
1308 int ret;
1309
1310 ret = afe_q6_interface_prepare();
1311 if (ret != 0) {
1312 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
1313 return ret;
1314 }
1315
1316 port_id = q6audio_get_port_id(port_id);
1317 ret = q6audio_validate_port(port_id);
1318 if (ret < 0) {
1319 pr_err("%s: Not a valid port id = 0x%x ret %d\n", __func__,
1320 port_id, ret);
1321 return -EINVAL;
1322 }
1323
1324 index = q6audio_get_port_index(port_id);
1325 if (index < 0 || index >= AFE_MAX_PORTS) {
1326 pr_err("%s: AFE port index[%d] invalid\n", __func__, index);
1327 return -EINVAL;
1328 }
1329
1330 if (q6common_is_instance_id_supported())
1331 return q6afe_get_params_v3(port_id, index, NULL, param_hdr);
1332 else
1333 return q6afe_get_params_v2(port_id, index, NULL, param_hdr);
1334}
1335
1336/*
1337 * This function shouldn't be called directly. Instead call
1338 * q6afe_svc_set_params.
1339 */
1340static int q6afe_svc_set_params_v1(int index, struct mem_mapping_hdr *mem_hdr,
1341 u8 *packed_param_data, u32 packed_data_size)
1342{
1343 struct afe_svc_cmd_set_param_v1 *svc_set_param = NULL;
1344 uint32_t size = sizeof(struct afe_svc_cmd_set_param_v1);
1345 int rc = 0;
1346
1347 if (packed_param_data != NULL)
1348 size += packed_data_size;
1349 svc_set_param = kzalloc(size, GFP_KERNEL);
1350 if (svc_set_param == NULL)
1351 return -ENOMEM;
1352
1353 svc_set_param->apr_hdr.hdr_field =
1354 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1355 APR_PKT_VER);
1356 svc_set_param->apr_hdr.pkt_size = size;
1357 svc_set_param->apr_hdr.src_port = 0;
1358 svc_set_param->apr_hdr.dest_port = 0;
Vignesh Kulothungan87f926a2018-03-04 22:47:50 -08001359 svc_set_param->apr_hdr.token = index;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001360 svc_set_param->apr_hdr.opcode = AFE_SVC_CMD_SET_PARAM;
1361 svc_set_param->payload_size = packed_data_size;
1362
1363 if (mem_hdr != NULL) {
1364 /* Out of band case. */
1365 svc_set_param->mem_hdr = *mem_hdr;
1366 } else if (packed_param_data != NULL) {
1367 /* In band case. */
1368 memcpy(&svc_set_param->param_data, packed_param_data,
1369 packed_data_size);
1370 } else {
1371 pr_err("%s: Both memory header and param data are NULL\n",
1372 __func__);
1373 rc = -EINVAL;
1374 goto done;
1375 }
1376
1377 rc = afe_apr_send_pkt(svc_set_param, &this_afe.wait[index]);
1378done:
1379 kfree(svc_set_param);
1380 return rc;
1381}
1382
1383/*
1384 * This function shouldn't be called directly. Instead call
1385 * q6afe_svc_set_params.
1386 */
1387static int q6afe_svc_set_params_v2(int index, struct mem_mapping_hdr *mem_hdr,
1388 u8 *packed_param_data, u32 packed_data_size)
1389{
1390 struct afe_svc_cmd_set_param_v2 *svc_set_param = NULL;
1391 uint16_t size = sizeof(struct afe_svc_cmd_set_param_v2);
1392 int rc = 0;
1393
1394 if (packed_param_data != NULL)
1395 size += packed_data_size;
1396 svc_set_param = kzalloc(size, GFP_KERNEL);
1397 if (svc_set_param == NULL)
1398 return -ENOMEM;
1399
1400 svc_set_param->apr_hdr.hdr_field =
1401 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1402 APR_PKT_VER);
1403 svc_set_param->apr_hdr.pkt_size = size;
1404 svc_set_param->apr_hdr.src_port = 0;
1405 svc_set_param->apr_hdr.dest_port = 0;
Vignesh Kulothungan87f926a2018-03-04 22:47:50 -08001406 svc_set_param->apr_hdr.token = index;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001407 svc_set_param->apr_hdr.opcode = AFE_SVC_CMD_SET_PARAM_V2;
1408 svc_set_param->payload_size = packed_data_size;
1409
1410 if (mem_hdr != NULL) {
1411 /* Out of band case. */
1412 svc_set_param->mem_hdr = *mem_hdr;
1413 } else if (packed_param_data != NULL) {
1414 /* In band case. */
1415 memcpy(&svc_set_param->param_data, packed_param_data,
1416 packed_data_size);
1417 } else {
1418 pr_err("%s: Both memory header and param data are NULL\n",
1419 __func__);
1420 rc = -EINVAL;
1421 goto done;
1422 }
1423
1424 rc = afe_apr_send_pkt(svc_set_param, &this_afe.wait[index]);
1425done:
1426 kfree(svc_set_param);
1427 return rc;
1428}
1429
1430static int q6afe_svc_set_params(int index, struct mem_mapping_hdr *mem_hdr,
1431 u8 *packed_param_data, u32 packed_data_size)
1432{
1433 int ret;
1434
1435 ret = afe_q6_interface_prepare();
1436 if (ret != 0) {
1437 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
1438 return ret;
1439 }
1440
1441 if (q6common_is_instance_id_supported())
1442 return q6afe_svc_set_params_v2(index, mem_hdr,
1443 packed_param_data,
1444 packed_data_size);
1445 else
1446 return q6afe_svc_set_params_v1(index, mem_hdr,
1447 packed_param_data,
1448 packed_data_size);
1449}
1450
1451static int q6afe_svc_pack_and_set_param_in_band(int index,
1452 struct param_hdr_v3 param_hdr,
1453 u8 *param_data)
1454{
1455 u8 *packed_param_data = NULL;
1456 u32 packed_data_size =
1457 sizeof(struct param_hdr_v3) + param_hdr.param_size;
1458 int ret = 0;
1459
1460 packed_param_data = kzalloc(packed_data_size, GFP_KERNEL);
1461 if (!packed_param_data)
1462 return -ENOMEM;
1463
1464 ret = q6common_pack_pp_params(packed_param_data, &param_hdr, param_data,
1465 &packed_data_size);
1466 if (ret) {
1467 pr_err("%s: Failed to pack parameter header and data, error %d\n",
1468 __func__, ret);
1469 goto done;
1470 }
1471
1472 ret = q6afe_svc_set_params(index, NULL, packed_param_data,
1473 packed_data_size);
1474
1475done:
1476 kfree(packed_param_data);
1477 return ret;
1478}
1479
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301480static int afe_send_cal_block(u16 port_id, struct cal_block_data *cal_block)
1481{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001482 struct mem_mapping_hdr mem_hdr;
1483 int payload_size = 0;
1484 int result = 0;
1485
1486 memset(&mem_hdr, 0, sizeof(mem_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301487
1488 if (!cal_block) {
1489 pr_debug("%s: No AFE cal to send!\n", __func__);
1490 result = -EINVAL;
1491 goto done;
1492 }
1493 if (cal_block->cal_data.size <= 0) {
1494 pr_debug("%s: AFE cal has invalid size!\n", __func__);
1495 result = -EINVAL;
1496 goto done;
1497 }
1498
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001499 payload_size = cal_block->cal_data.size;
1500 mem_hdr.data_payload_addr_lsw =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301501 lower_32_bits(cal_block->cal_data.paddr);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001502 mem_hdr.data_payload_addr_msw =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301503 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001504 mem_hdr.mem_map_handle = cal_block->map_data.q6map_handle;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301505
1506 pr_debug("%s: AFE cal sent for device port = 0x%x, cal size = %zd, cal addr = 0x%pK\n",
1507 __func__, port_id,
1508 cal_block->cal_data.size, &cal_block->cal_data.paddr);
1509
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001510 result = q6afe_set_params(port_id, q6audio_get_port_index(port_id),
1511 &mem_hdr, NULL, payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301512 if (result)
1513 pr_err("%s: AFE cal for port 0x%x failed %d\n",
1514 __func__, port_id, result);
1515
1516done:
1517 return result;
1518}
1519
1520
1521static int afe_send_custom_topology_block(struct cal_block_data *cal_block)
1522{
1523 int result = 0;
1524 int index = 0;
1525 struct cmd_set_topologies afe_cal;
1526
1527 if (!cal_block) {
1528 pr_err("%s: No AFE SVC cal to send!\n", __func__);
1529 return -EINVAL;
1530 }
1531 if (cal_block->cal_data.size <= 0) {
1532 pr_err("%s: AFE SVC cal has invalid size: %zd!\n",
1533 __func__, cal_block->cal_data.size);
1534 return -EINVAL;
1535 }
1536
1537 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1538 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1539 afe_cal.hdr.pkt_size = sizeof(afe_cal);
1540 afe_cal.hdr.src_port = 0;
1541 afe_cal.hdr.dest_port = 0;
1542 afe_cal.hdr.token = index;
1543 afe_cal.hdr.opcode = AFE_CMD_ADD_TOPOLOGIES;
1544
1545 afe_cal.payload_size = cal_block->cal_data.size;
1546 afe_cal.payload_addr_lsw =
1547 lower_32_bits(cal_block->cal_data.paddr);
1548 afe_cal.payload_addr_msw =
1549 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
1550 afe_cal.mem_map_handle = cal_block->map_data.q6map_handle;
1551
1552 pr_debug("%s:cmd_id:0x%x calsize:%zd memmap_hdl:0x%x caladdr:0x%pK",
1553 __func__, AFE_CMD_ADD_TOPOLOGIES, cal_block->cal_data.size,
1554 afe_cal.mem_map_handle, &cal_block->cal_data.paddr);
1555
1556 result = afe_apr_send_pkt(&afe_cal, &this_afe.wait[index]);
1557 if (result)
1558 pr_err("%s: AFE send topology for command 0x%x failed %d\n",
1559 __func__, AFE_CMD_ADD_TOPOLOGIES, result);
1560
1561 return result;
1562}
1563
1564static void afe_send_custom_topology(void)
1565{
1566 struct cal_block_data *cal_block = NULL;
1567 int cal_index = AFE_CUST_TOPOLOGY_CAL;
1568 int ret;
1569
1570 if (this_afe.cal_data[cal_index] == NULL) {
1571 pr_err("%s: cal_index %d not allocated!\n",
1572 __func__, cal_index);
1573 return;
1574 }
1575 mutex_lock(&this_afe.cal_data[cal_index]->lock);
1576
1577 if (!this_afe.set_custom_topology)
1578 goto unlock;
1579 this_afe.set_custom_topology = 0;
1580 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07001581 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301582 pr_err("%s cal_block not found!!\n", __func__);
1583 goto unlock;
1584 }
1585
1586 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
1587
1588 ret = remap_cal_data(cal_block, cal_index);
1589 if (ret) {
1590 pr_err("%s: Remap_cal_data failed for cal %d!\n",
1591 __func__, cal_index);
1592 goto unlock;
1593 }
1594 ret = afe_send_custom_topology_block(cal_block);
1595 if (ret < 0) {
1596 pr_err("%s: No cal sent for cal_index %d! ret %d\n",
1597 __func__, cal_index, ret);
1598 goto unlock;
1599 }
1600 pr_debug("%s:sent custom topology for AFE\n", __func__);
1601unlock:
1602 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
1603}
1604
1605static int afe_spk_ramp_dn_cfg(int port)
1606{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001607 struct param_hdr_v3 param_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301608 int ret = -EINVAL;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001609
1610 memset(&param_info, 0, sizeof(param_info));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301611
1612 if (afe_get_port_type(port) != MSM_AFE_PORT_TYPE_RX) {
1613 pr_debug("%s: port doesn't match 0x%x\n", __func__, port);
1614 return 0;
1615 }
1616 if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_DISABLED ||
1617 (this_afe.vi_rx_port != port)) {
1618 pr_debug("%s: spkr protection disabled port 0x%x %d 0x%x\n",
1619 __func__, port, ret, this_afe.vi_rx_port);
1620 return 0;
1621 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001622 param_info.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
1623 param_info.instance_id = INSTANCE_ID_0;
1624 param_info.param_id = AFE_PARAM_ID_FBSP_PTONE_RAMP_CFG;
1625 param_info.param_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301626
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001627 ret = q6afe_pack_and_set_param_in_band(port,
1628 q6audio_get_port_index(port),
1629 param_info, NULL);
1630 if (ret) {
1631 pr_err("%s: Failed to set speaker ramp duration param, err %d\n",
1632 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301633 goto fail_cmd;
1634 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001635
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301636 /* dsp needs atleast 15ms to ramp down pilot tone*/
1637 usleep_range(15000, 15010);
1638 ret = 0;
1639fail_cmd:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001640 pr_debug("%s: config.pdata.param_id 0x%x status %d\n", __func__,
1641 param_info.param_id, ret);
1642 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301643}
1644
1645static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id,
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001646 union afe_spkr_prot_config *prot_config)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301647{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001648 struct param_hdr_v3 param_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301649 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301650
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001651 memset(&param_info, 0, sizeof(param_info));
1652
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301653 ret = q6audio_validate_port(src_port);
1654 if (ret < 0) {
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001655 pr_err("%s: Invalid src port 0x%x ret %d", __func__, src_port,
1656 ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301657 ret = -EINVAL;
1658 goto fail_cmd;
1659 }
1660 ret = q6audio_validate_port(dst_port);
1661 if (ret < 0) {
1662 pr_err("%s: Invalid dst port 0x%x ret %d", __func__,
1663 dst_port, ret);
1664 ret = -EINVAL;
1665 goto fail_cmd;
1666 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001667
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301668 switch (param_id) {
1669 case AFE_PARAM_ID_FBSP_MODE_RX_CFG:
Xiaojun Sang12120ab2017-09-28 18:21:21 +08001670 case AFE_PARAM_ID_SP_RX_LIMITER_TH:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001671 param_info.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301672 break;
1673 case AFE_PARAM_ID_FEEDBACK_PATH_CFG:
1674 this_afe.vi_tx_port = src_port;
1675 this_afe.vi_rx_port = dst_port;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001676 param_info.module_id = AFE_MODULE_FEEDBACK;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301677 break;
1678 /*
1679 * AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2 is same as
Laxminath Kasam2e13d952019-02-20 15:05:39 +05301680 * AFE_PARAM_ID_SP_V2_TH_VI_MODE_CFG. V_VALI_CFG uses
1681 * same module TH_VI.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301682 */
1683 case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2:
1684 case AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG:
Laxminath Kasam2e13d952019-02-20 15:05:39 +05301685 case AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_CFG:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001686 param_info.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301687 break;
1688 case AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG:
1689 case AFE_PARAM_ID_SP_V2_EX_VI_FTM_CFG:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001690 param_info.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301691 break;
1692 default:
1693 pr_err("%s: default case 0x%x\n", __func__, param_id);
1694 goto fail_cmd;
1695 }
1696
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001697 param_info.instance_id = INSTANCE_ID_0;
1698 param_info.param_id = param_id;
1699 param_info.param_size = sizeof(union afe_spkr_prot_config);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301700
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001701 ret = q6afe_pack_and_set_param_in_band(src_port,
1702 q6audio_get_port_index(src_port),
1703 param_info, (u8 *) prot_config);
1704 if (ret)
1705 pr_err("%s: port = 0x%x param = 0x%x failed %d\n", __func__,
1706 src_port, param_id, ret);
1707
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301708fail_cmd:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001709 pr_debug("%s: config.pdata.param_id 0x%x status %d 0x%x\n", __func__,
1710 param_info.param_id, ret, src_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301711 return ret;
1712}
1713
Vidyakumar Athota94bd8732018-02-28 17:13:35 -08001714static int afe_spkr_prot_reg_event_cfg(u16 port_id)
1715{
1716 struct afe_port_cmd_event_cfg *config;
1717 struct afe_port_cmd_mod_evt_cfg_payload pl;
1718 int index;
1719 int ret;
1720 int num_events = 1;
1721 int cmd_size = sizeof(struct afe_port_cmd_event_cfg) +
1722 (num_events * sizeof(struct afe_port_cmd_mod_evt_cfg_payload));
1723
1724 config = kzalloc(cmd_size, GFP_KERNEL);
1725 if (!config)
1726 return -ENOMEM;
1727
1728 index = q6audio_get_port_index(port_id);
1729 if (index < 0) {
1730 pr_err("%s: Invalid index number: %d\n", __func__, index);
1731 ret = -EINVAL;
1732 goto fail_idx;
1733 }
1734
1735 memset(&pl, 0, sizeof(pl));
1736 pl.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
1737 pl.event_id = AFE_PORT_SP_DC_DETECTION_EVENT;
1738 pl.reg_flag = AFE_MODULE_REGISTER_EVENT_FLAG;
1739
1740
1741 config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1742 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1743 config->hdr.pkt_size = cmd_size;
1744 config->hdr.src_port = 0;
1745 config->hdr.dest_port = 0;
1746 config->hdr.token = index;
1747
1748 config->hdr.opcode = AFE_PORT_CMD_MOD_EVENT_CFG;
1749 config->port_id = q6audio_get_port_id(port_id);
1750 config->num_events = num_events;
1751 config->version = 1;
1752 memcpy(config->payload, &pl, sizeof(pl));
1753 atomic_set(&this_afe.state, 1);
1754 atomic_set(&this_afe.status, 0);
1755 ret = apr_send_pkt(this_afe.apr, (uint32_t *) config);
1756 if (ret < 0) {
1757 pr_err("%s: port = 0x%x failed %d\n",
1758 __func__, port_id, ret);
1759 goto fail_cmd;
1760 }
1761 ret = wait_event_timeout(this_afe.wait[index],
1762 (atomic_read(&this_afe.state) == 0),
1763 msecs_to_jiffies(TIMEOUT_MS));
1764 if (!ret) {
1765 pr_err("%s: wait_event timeout\n", __func__);
1766 ret = -EINVAL;
1767 goto fail_cmd;
1768 }
1769 if (atomic_read(&this_afe.status) > 0) {
1770 pr_err("%s: config cmd failed [%s]\n",
1771 __func__, adsp_err_get_err_str(
1772 atomic_read(&this_afe.status)));
1773 ret = adsp_err_get_lnx_err_code(
1774 atomic_read(&this_afe.status));
1775 goto fail_idx;
1776 }
1777 ret = 0;
1778fail_cmd:
1779 pr_debug("%s: config.opcode 0x%x status %d\n",
1780 __func__, config->hdr.opcode, ret);
1781
1782fail_idx:
1783 kfree(config);
1784 return ret;
1785}
1786
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301787static void afe_send_cal_spkr_prot_tx(int port_id)
1788{
1789 union afe_spkr_prot_config afe_spk_config;
1790
1791 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL ||
1792 this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
1793 this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL)
1794 return;
1795
1796 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1797 if ((this_afe.prot_cfg.mode != MSM_SPKR_PROT_DISABLED) &&
1798 (this_afe.vi_tx_port == port_id)) {
1799 if (this_afe.prot_cfg.mode ==
1800 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
1801 afe_spk_config.vi_proc_cfg.operation_mode =
1802 Q6AFE_MSM_SPKR_CALIBRATION;
1803 afe_spk_config.vi_proc_cfg.quick_calib_flag =
1804 this_afe.prot_cfg.quick_calib_flag;
1805 } else {
1806 afe_spk_config.vi_proc_cfg.operation_mode =
1807 Q6AFE_MSM_SPKR_PROCESSING;
1808 }
1809
1810 if (this_afe.th_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE)
1811 afe_spk_config.vi_proc_cfg.operation_mode =
1812 Q6AFE_MSM_SPKR_FTM_MODE;
Laxminath Kasam2e13d952019-02-20 15:05:39 +05301813 else if (this_afe.v_vali_cfg.mode ==
1814 MSM_SPKR_PROT_IN_V_VALI_MODE)
1815 afe_spk_config.vi_proc_cfg.operation_mode =
1816 Q6AFE_MSM_SPKR_V_VALI_MODE;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301817 afe_spk_config.vi_proc_cfg.minor_version = 1;
1818 afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_1] =
1819 (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1];
1820 afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_2] =
1821 (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_2];
1822 afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_1] =
1823 (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_1];
1824 afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_2] =
1825 (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_2];
1826 if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_NOT_CALIBRATED) {
1827 struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg;
1828
1829 vi_proc_cfg = &afe_spk_config.vi_proc_cfg;
1830 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] =
1831 USE_CALIBRATED_R0TO;
1832 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] =
1833 USE_CALIBRATED_R0TO;
1834 } else {
1835 struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg;
1836
1837 vi_proc_cfg = &afe_spk_config.vi_proc_cfg;
1838 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] =
1839 USE_SAFE_R0TO;
1840 vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] =
1841 USE_SAFE_R0TO;
1842 }
1843 if (afe_spk_prot_prepare(port_id, 0,
1844 AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2,
1845 &afe_spk_config))
1846 pr_err("%s: SPKR_CALIB_VI_PROC_CFG failed\n",
1847 __func__);
1848 }
1849 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1850
1851 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
1852 if ((this_afe.th_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE) &&
1853 (this_afe.vi_tx_port == port_id)) {
1854 afe_spk_config.th_vi_ftm_cfg.minor_version = 1;
1855 afe_spk_config.th_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_1] =
1856 this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_1];
1857 afe_spk_config.th_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_2] =
1858 this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_2];
1859 afe_spk_config.th_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_1] =
1860 this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_1];
1861 afe_spk_config.th_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_2] =
1862 this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_2];
1863
1864 if (afe_spk_prot_prepare(port_id, 0,
1865 AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG,
1866 &afe_spk_config))
1867 pr_err("%s: th vi ftm cfg failed\n", __func__);
1868 this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
Laxminath Kasam2e13d952019-02-20 15:05:39 +05301869 } else if ((this_afe.v_vali_cfg.mode ==
1870 MSM_SPKR_PROT_IN_V_VALI_MODE) &&
1871 (this_afe.vi_tx_port == port_id)) {
1872 afe_spk_config.th_vi_v_vali_cfg.minor_version = 1;
1873 afe_spk_config.th_vi_v_vali_cfg.wait_time_ms[SP_V2_SPKR_1] =
1874 this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_1];
1875 afe_spk_config.th_vi_v_vali_cfg.wait_time_ms[SP_V2_SPKR_2] =
1876 this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_2];
1877 afe_spk_config.th_vi_v_vali_cfg.vali_time_ms[SP_V2_SPKR_1] =
1878 this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_1];
1879 afe_spk_config.th_vi_v_vali_cfg.vali_time_ms[SP_V2_SPKR_2] =
1880 this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_2];
1881
1882 if (afe_spk_prot_prepare(port_id, 0,
1883 AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_CFG,
1884 &afe_spk_config))
1885 pr_err("%s: th vi v-vali cfg failed\n", __func__);
1886
1887 this_afe.v_vali_cfg.mode = MSM_SPKR_PROT_DISABLED;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301888 }
1889 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
1890
1891 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
1892 if ((this_afe.ex_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE) &&
1893 (this_afe.vi_tx_port == port_id)) {
1894 afe_spk_config.ex_vi_mode_cfg.minor_version = 1;
1895 afe_spk_config.ex_vi_mode_cfg.operation_mode =
1896 Q6AFE_MSM_SPKR_FTM_MODE;
1897 if (afe_spk_prot_prepare(port_id, 0,
1898 AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG,
1899 &afe_spk_config))
1900 pr_err("%s: ex vi mode cfg failed\n", __func__);
1901
1902 afe_spk_config.ex_vi_ftm_cfg.minor_version = 1;
1903 afe_spk_config.ex_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_1] =
1904 this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_1];
1905 afe_spk_config.ex_vi_ftm_cfg.wait_time_ms[SP_V2_SPKR_2] =
1906 this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_2];
1907 afe_spk_config.ex_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_1] =
1908 this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_1];
1909 afe_spk_config.ex_vi_ftm_cfg.ftm_time_ms[SP_V2_SPKR_2] =
1910 this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_2];
1911
1912 if (afe_spk_prot_prepare(port_id, 0,
1913 AFE_PARAM_ID_SP_V2_EX_VI_FTM_CFG,
1914 &afe_spk_config))
1915 pr_err("%s: ex vi ftm cfg failed\n", __func__);
1916 this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
1917 }
1918 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
1919
Vignesh Kulothungan0ffc6082018-08-03 10:46:42 -07001920 /* Register for DC detection event if speaker protection is enabled */
1921 if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_DISABLED &&
1922 (this_afe.vi_tx_port == port_id)) {
1923 afe_spkr_prot_reg_event_cfg(port_id);
1924 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301925}
1926
1927static void afe_send_cal_spkr_prot_rx(int port_id)
1928{
1929 union afe_spkr_prot_config afe_spk_config;
Xiaojun Sang12120ab2017-09-28 18:21:21 +08001930 union afe_spkr_prot_config afe_spk_limiter_config;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301931
1932 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
1933 goto done;
1934
1935 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1936
1937 if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_DISABLED &&
1938 (this_afe.vi_rx_port == port_id)) {
1939 if (this_afe.prot_cfg.mode ==
1940 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
1941 afe_spk_config.mode_rx_cfg.mode =
1942 Q6AFE_MSM_SPKR_CALIBRATION;
1943 else
1944 afe_spk_config.mode_rx_cfg.mode =
1945 Q6AFE_MSM_SPKR_PROCESSING;
1946 afe_spk_config.mode_rx_cfg.minor_version = 1;
1947 if (afe_spk_prot_prepare(port_id, 0,
1948 AFE_PARAM_ID_FBSP_MODE_RX_CFG,
1949 &afe_spk_config))
1950 pr_err("%s: RX MODE_VI_PROC_CFG failed\n",
1951 __func__);
Xiaojun Sang12120ab2017-09-28 18:21:21 +08001952
1953 if (afe_spk_config.mode_rx_cfg.mode ==
1954 Q6AFE_MSM_SPKR_PROCESSING) {
1955 if (this_afe.prot_cfg.sp_version >=
1956 AFE_API_VERSION_SUPPORT_SPV3) {
1957 afe_spk_limiter_config.limiter_th_cfg.
1958 minor_version = 1;
1959 afe_spk_limiter_config.limiter_th_cfg.
1960 lim_thr_per_calib_q27[SP_V2_SPKR_1] =
1961 this_afe.prot_cfg.limiter_th[SP_V2_SPKR_1];
1962 afe_spk_limiter_config.limiter_th_cfg.
1963 lim_thr_per_calib_q27[SP_V2_SPKR_2] =
1964 this_afe.prot_cfg.limiter_th[SP_V2_SPKR_2];
1965 if (afe_spk_prot_prepare(port_id, 0,
1966 AFE_PARAM_ID_SP_RX_LIMITER_TH,
1967 &afe_spk_limiter_config))
1968 pr_err("%s: SP_RX_LIMITER_TH failed.\n",
1969 __func__);
1970 } else {
1971 pr_debug("%s: SPv3 failed to apply on AFE API version=%d.\n",
1972 __func__,
1973 this_afe.prot_cfg.sp_version);
1974 }
1975 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301976 }
1977 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
1978done:
1979 return;
1980}
1981
1982static int afe_send_hw_delay(u16 port_id, u32 rate)
1983{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001984 struct audio_cal_hw_delay_entry delay_entry;
1985 struct afe_param_id_device_hw_delay_cfg hw_delay;
1986 struct param_hdr_v3 param_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301987 int ret = -EINVAL;
1988
1989 pr_debug("%s:\n", __func__);
1990
1991 memset(&delay_entry, 0, sizeof(delay_entry));
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08001992 memset(&param_info, 0, sizeof(param_info));
1993
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301994 delay_entry.sample_rate = rate;
1995 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
1996 ret = afe_get_cal_hw_delay(TX_DEVICE, &delay_entry);
1997 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
1998 ret = afe_get_cal_hw_delay(RX_DEVICE, &delay_entry);
1999
2000 /*
2001 * HW delay is only used for IMS calls to sync audio with video
2002 * It is only needed for devices & sample rates used for IMS video
2003 * calls. Values are received from ACDB calbration files
2004 */
2005 if (ret != 0) {
2006 pr_debug("%s: debug: HW delay info not available %d\n",
2007 __func__, ret);
2008 goto fail_cmd;
2009 }
2010
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002011 param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2012 param_info.instance_id = INSTANCE_ID_0;
2013 param_info.param_id = AFE_PARAM_ID_DEVICE_HW_DELAY;
2014 param_info.param_size = sizeof(hw_delay);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302015
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002016 hw_delay.delay_in_us = delay_entry.delay_usec;
2017 hw_delay.device_hw_delay_minor_version =
2018 AFE_API_VERSION_DEVICE_HW_DELAY;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302019
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002020 ret = q6afe_pack_and_set_param_in_band(port_id,
2021 q6audio_get_port_index(port_id),
2022 param_info, (u8 *) &hw_delay);
2023 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302024 pr_err("%s: AFE hw delay for port 0x%x failed %d\n",
2025 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302026
2027fail_cmd:
2028 pr_debug("%s: port_id 0x%x rate %u delay_usec %d status %d\n",
2029 __func__, port_id, rate, delay_entry.delay_usec, ret);
2030 return ret;
2031}
2032
2033static struct cal_block_data *afe_find_cal_topo_id_by_port(
2034 struct cal_type_data *cal_type, u16 port_id)
2035{
2036 struct list_head *ptr, *next;
2037 struct cal_block_data *cal_block = NULL;
2038 int32_t path;
2039 struct audio_cal_info_afe_top *afe_top;
2040 int afe_port_index = q6audio_get_port_index(port_id);
2041
2042 if (afe_port_index < 0)
2043 goto err_exit;
2044
2045 list_for_each_safe(ptr, next,
2046 &cal_type->cal_blocks) {
2047 cal_block = list_entry(ptr,
2048 struct cal_block_data, list);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002049 /* Skip cal_block if it is already marked stale */
2050 if (cal_utils_is_cal_stale(cal_block))
2051 continue;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302052 path = ((afe_get_port_type(port_id) ==
2053 MSM_AFE_PORT_TYPE_TX)?(TX_DEVICE):(RX_DEVICE));
2054 afe_top =
2055 (struct audio_cal_info_afe_top *)cal_block->cal_info;
2056 if (afe_top->path == path) {
2057 if (this_afe.dev_acdb_id[afe_port_index] > 0) {
2058 if (afe_top->acdb_id ==
2059 this_afe.dev_acdb_id[afe_port_index]) {
2060 pr_debug("%s: top_id:%x acdb_id:%d afe_port_id:%d\n",
2061 __func__, afe_top->topology,
2062 afe_top->acdb_id,
2063 q6audio_get_port_id(port_id));
2064 return cal_block;
2065 }
2066 } else {
2067 pr_debug("%s: top_id:%x acdb_id:%d afe_port:%d\n",
2068 __func__, afe_top->topology, afe_top->acdb_id,
2069 q6audio_get_port_id(port_id));
2070 return cal_block;
2071 }
2072 }
2073 }
2074
2075err_exit:
2076 return NULL;
2077}
2078
Vikram Panduranga770b8382017-09-27 12:17:36 -07002079/*
2080 * Retrieving cal_block will mark cal_block as stale.
2081 * Hence it cannot be reused or resent unless the flag
2082 * is reset.
2083 */
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302084static int afe_get_cal_topology_id(u16 port_id, u32 *topology_id,
2085 int cal_type_index)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302086{
2087 int ret = 0;
2088
2089 struct cal_block_data *cal_block = NULL;
2090 struct audio_cal_info_afe_top *afe_top_info = NULL;
2091
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302092 if (this_afe.cal_data[cal_type_index] == NULL) {
Vikram Panduranga770b8382017-09-27 12:17:36 -07002093 pr_err("%s: cal_type %d not initialized\n", __func__,
2094 cal_type_index);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302095 return -EINVAL;
2096 }
2097 if (topology_id == NULL) {
2098 pr_err("%s: topology_id is NULL\n", __func__);
2099 return -EINVAL;
2100 }
2101 *topology_id = 0;
2102
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302103 mutex_lock(&this_afe.cal_data[cal_type_index]->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302104 cal_block = afe_find_cal_topo_id_by_port(
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302105 this_afe.cal_data[cal_type_index], port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302106 if (cal_block == NULL) {
Vikram Panduranga770b8382017-09-27 12:17:36 -07002107 pr_err("%s: cal_type %d not initialized for this port %d\n",
2108 __func__, cal_type_index, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302109 ret = -EINVAL;
2110 goto unlock;
2111 }
2112
2113 afe_top_info = ((struct audio_cal_info_afe_top *)
2114 cal_block->cal_info);
2115 if (!afe_top_info->topology) {
2116 pr_err("%s: invalid topology id : [%d, %d]\n",
2117 __func__, afe_top_info->acdb_id, afe_top_info->topology);
2118 ret = -EINVAL;
2119 goto unlock;
2120 }
2121 *topology_id = (u32)afe_top_info->topology;
Vikram Panduranga770b8382017-09-27 12:17:36 -07002122 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302123
2124 pr_debug("%s: port_id = %u acdb_id = %d topology_id = %u ret=%d\n",
2125 __func__, port_id, afe_top_info->acdb_id,
2126 afe_top_info->topology, ret);
2127unlock:
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302128 mutex_unlock(&this_afe.cal_data[cal_type_index]->lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302129 return ret;
2130}
2131
2132static int afe_send_port_topology_id(u16 port_id)
2133{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002134 struct afe_param_id_set_topology_cfg topology;
2135 struct param_hdr_v3 param_info;
2136 u32 topology_id = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302137 int index = 0;
2138 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302139
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002140 memset(&topology, 0, sizeof(topology));
2141 memset(&param_info, 0, sizeof(param_info));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302142 index = q6audio_get_port_index(port_id);
2143 if (index < 0 || index >= AFE_MAX_PORTS) {
2144 pr_err("%s: AFE port index[%d] invalid!\n",
2145 __func__, index);
2146 return -EINVAL;
2147 }
2148
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302149 ret = afe_get_cal_topology_id(port_id, &topology_id, AFE_TOPOLOGY_CAL);
2150 if (ret < 0) {
2151 pr_debug("%s: Check for LSM topology\n", __func__);
2152 ret = afe_get_cal_topology_id(port_id, &topology_id,
2153 AFE_LSM_TOPOLOGY_CAL);
2154 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302155 if (ret || !topology_id) {
2156 pr_debug("%s: AFE port[%d] get_cal_topology[%d] invalid!\n",
2157 __func__, port_id, topology_id);
2158 goto done;
2159 }
2160
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002161 param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2162 param_info.instance_id = INSTANCE_ID_0;
2163 param_info.param_id = AFE_PARAM_ID_SET_TOPOLOGY;
2164 param_info.param_size = sizeof(topology);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302165
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002166 topology.minor_version = AFE_API_VERSION_TOPOLOGY_V1;
2167 topology.topology_id = topology_id;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302168
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002169 ret = q6afe_pack_and_set_param_in_band(port_id,
2170 q6audio_get_port_index(port_id),
2171 param_info, (u8 *) &topology);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302172 if (ret) {
2173 pr_err("%s: AFE set topology id enable for port 0x%x failed %d\n",
2174 __func__, port_id, ret);
2175 goto done;
2176 }
2177
2178 this_afe.topology[index] = topology_id;
2179 rtac_update_afe_topology(port_id);
2180done:
2181 pr_debug("%s: AFE set topology id 0x%x enable for port 0x%x ret %d\n",
2182 __func__, topology_id, port_id, ret);
2183 return ret;
2184
2185}
2186
Mangesh Kunchamwar4e1e7182018-04-26 17:58:58 +05302187
2188static int afe_get_island_mode(u16 port_id, u32 *island_mode)
2189{
2190 int ret = 0;
2191 int index = 0;
2192 *island_mode = 0;
2193
2194 index = q6audio_get_port_index(port_id);
2195 if (index < 0 || index >= AFE_MAX_PORTS) {
2196 pr_err("%s: AFE port index[%d] invalid!\n",
2197 __func__, index);
2198 return -EINVAL;
2199 }
2200
2201 *island_mode = this_afe.island_mode[index];
2202 return ret;
2203}
2204
2205/*
2206 * afe_send_port_island_mode -
2207 * for sending island mode to AFE
2208 *
2209 * @port_id: AFE port id number
2210 *
2211 * Returns 0 on success or error on failure.
2212 */
2213int afe_send_port_island_mode(u16 port_id)
2214{
2215 struct afe_param_id_island_cfg_t island_cfg;
2216 struct param_hdr_v3 param_info;
2217 u32 island_mode = 0;
2218 int ret = 0;
2219
2220 memset(&island_cfg, 0, sizeof(island_cfg));
2221 memset(&param_info, 0, sizeof(param_info));
2222
2223 ret = afe_get_island_mode(port_id, &island_mode);
2224 if (ret) {
2225 pr_err("%s: AFE port[%d] get island mode is invalid!\n",
2226 __func__, port_id);
2227 return ret;
2228 }
2229 param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2230 param_info.instance_id = INSTANCE_ID_0;
2231 param_info.param_id = AFE_PARAM_ID_ISLAND_CONFIG;
2232 param_info.param_size = sizeof(island_cfg);
2233
2234 island_cfg.island_cfg_minor_version = AFE_API_VERSION_ISLAND_CONFIG;
2235 island_cfg.island_enable = island_mode;
2236
2237 ret = q6afe_pack_and_set_param_in_band(port_id,
2238 q6audio_get_port_index(port_id),
2239 param_info, (u8 *) &island_cfg);
2240 if (ret) {
2241 pr_err("%s: AFE set island mode enable for port 0x%x failed %d\n",
2242 __func__, port_id, ret);
2243 return ret;
2244 }
2245 pr_debug("%s: AFE set island mode 0x%x enable for port 0x%x ret %d\n",
2246 __func__, island_mode, port_id, ret);
2247 return ret;
2248}
2249EXPORT_SYMBOL(afe_send_port_island_mode);
2250
2251static int afe_get_vad_preroll_cfg(u16 port_id, u32 *preroll_cfg)
2252{
2253 int ret = 0;
2254 int index = 0;
2255 *preroll_cfg = 0;
2256
2257 index = q6audio_get_port_index(port_id);
2258 if (index < 0 || index >= AFE_MAX_PORTS) {
2259 pr_err("%s: AFE port index[%d] invalid!\n",
2260 __func__, index);
2261 return -EINVAL;
2262 }
2263
2264 *preroll_cfg = this_afe.vad_cfg[index].pre_roll;
2265 return ret;
2266}
2267
2268static int afe_send_port_vad_cfg_params(u16 port_id)
2269{
2270 struct afe_param_id_vad_cfg_t vad_cfg;
2271 struct param_hdr_v3 param_info;
2272 u32 pre_roll_cfg = 0;
2273 struct firmware_cal *hwdep_cal = NULL;
2274 int ret = 0;
2275
2276 memset(&vad_cfg, 0, sizeof(vad_cfg));
2277 memset(&param_info, 0, sizeof(param_info));
2278
2279 ret = afe_get_vad_preroll_cfg(port_id, &pre_roll_cfg);
2280 if (ret) {
2281 pr_err("%s: AFE port[%d] get preroll cfg is invalid!\n",
2282 __func__, port_id);
2283 return ret;
2284 }
2285 param_info.module_id = AFE_MODULE_VAD;
2286 param_info.instance_id = INSTANCE_ID_0;
2287 param_info.param_id = AFE_PARAM_ID_VAD_CFG;
2288 param_info.param_size = sizeof(vad_cfg);
2289
2290 vad_cfg.vad_cfg_minor_version = AFE_API_VERSION_VAD_CFG;
2291 vad_cfg.pre_roll_in_ms = pre_roll_cfg;
2292
2293 ret = q6afe_pack_and_set_param_in_band(port_id,
2294 q6audio_get_port_index(port_id),
2295 param_info, (u8 *) &vad_cfg);
2296 if (ret) {
2297 pr_err("%s: AFE set vad cfg for port 0x%x failed %d\n",
2298 __func__, port_id, ret);
2299 return ret;
2300 }
2301
2302 memset(&param_info, 0, sizeof(param_info));
2303
2304 hwdep_cal = q6afecal_get_fw_cal(this_afe.fw_data, Q6AFE_VAD_CORE_CAL);
2305 if (!hwdep_cal) {
2306 pr_err("%s: error in retrieving vad core calibration",
2307 __func__);
2308 return -EINVAL;
2309 }
2310
2311 param_info.module_id = AFE_MODULE_VAD;
2312 param_info.instance_id = INSTANCE_ID_0;
2313 param_info.param_id = AFE_PARAM_ID_VAD_CORE_CFG;
2314 param_info.param_size = hwdep_cal->size;
2315
2316 ret = q6afe_pack_and_set_param_in_band(port_id,
2317 q6audio_get_port_index(port_id),
2318 param_info, (u8 *) hwdep_cal->data);
2319 if (ret) {
2320 pr_err("%s: AFE set vad cfg for port 0x%x failed %d\n",
2321 __func__, port_id, ret);
2322 return ret;
2323 }
2324 pr_debug("%s: AFE set preroll cfg %d vad core cfg port 0x%x ret %d\n",
2325 __func__, pre_roll_cfg, port_id, ret);
2326 return ret;
2327}
2328
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302329static int remap_cal_data(struct cal_block_data *cal_block, int cal_index)
2330{
2331 int ret = 0;
2332
Banajit Goswami08bb7362017-11-03 22:48:23 -07002333 if (cal_block->map_data.dma_buf == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302334 pr_err("%s: No ION allocation for cal index %d!\n",
2335 __func__, cal_index);
2336 ret = -EINVAL;
2337 goto done;
2338 }
2339
2340 if ((cal_block->map_data.map_size > 0) &&
2341 (cal_block->map_data.q6map_handle == 0)) {
2342 atomic_set(&this_afe.mem_map_cal_index, cal_index);
2343 ret = afe_cmd_memory_map(cal_block->cal_data.paddr,
2344 cal_block->map_data.map_size);
2345 atomic_set(&this_afe.mem_map_cal_index, -1);
2346 if (ret < 0) {
2347 pr_err("%s: mmap did not work! size = %zd ret %d\n",
2348 __func__,
2349 cal_block->map_data.map_size, ret);
2350 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
2351 __func__,
2352 &cal_block->cal_data.paddr,
2353 cal_block->map_data.map_size);
2354 goto done;
2355 }
2356 cal_block->map_data.q6map_handle = atomic_read(&this_afe.
2357 mem_map_cal_handles[cal_index]);
2358 }
2359done:
2360 return ret;
2361}
2362
2363static struct cal_block_data *afe_find_cal(int cal_index, int port_id)
2364{
2365 struct list_head *ptr, *next;
2366 struct cal_block_data *cal_block = NULL;
2367 struct audio_cal_info_afe *afe_cal_info = NULL;
2368 int afe_port_index = q6audio_get_port_index(port_id);
2369
2370 pr_debug("%s: cal_index %d port_id %d port_index %d\n", __func__,
2371 cal_index, port_id, afe_port_index);
2372 if (afe_port_index < 0) {
2373 pr_err("%s: Error getting AFE port index %d\n",
2374 __func__, afe_port_index);
2375 goto exit;
2376 }
2377
2378 list_for_each_safe(ptr, next,
2379 &this_afe.cal_data[cal_index]->cal_blocks) {
2380 cal_block = list_entry(ptr, struct cal_block_data, list);
2381 afe_cal_info = cal_block->cal_info;
2382 if ((afe_cal_info->acdb_id ==
2383 this_afe.dev_acdb_id[afe_port_index]) &&
2384 (afe_cal_info->sample_rate ==
2385 this_afe.afe_sample_rates[afe_port_index])) {
2386 pr_debug("%s: cal block is a match, size is %zd\n",
2387 __func__, cal_block->cal_data.size);
2388 goto exit;
2389 }
2390 }
Xiaojun Sangf27e3512018-05-23 17:14:31 +08002391 pr_debug("%s: no matching cal_block found\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302392 cal_block = NULL;
2393
2394exit:
2395 return cal_block;
2396}
2397
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302398static int send_afe_cal_type(int cal_index, int port_id)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302399{
2400 struct cal_block_data *cal_block = NULL;
2401 int ret;
2402 int afe_port_index = q6audio_get_port_index(port_id);
2403
2404 pr_debug("%s:\n", __func__);
2405
2406 if (this_afe.cal_data[cal_index] == NULL) {
2407 pr_warn("%s: cal_index %d not allocated!\n",
2408 __func__, cal_index);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302409 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302410 goto done;
2411 }
2412
2413 if (afe_port_index < 0) {
2414 pr_err("%s: Error getting AFE port index %d\n",
2415 __func__, afe_port_index);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302416 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302417 goto done;
2418 }
2419
2420 mutex_lock(&this_afe.cal_data[cal_index]->lock);
2421
2422 if (((cal_index == AFE_COMMON_RX_CAL) ||
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302423 (cal_index == AFE_COMMON_TX_CAL) ||
2424 (cal_index == AFE_LSM_TX_CAL)) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302425 (this_afe.dev_acdb_id[afe_port_index] > 0))
2426 cal_block = afe_find_cal(cal_index, port_id);
2427 else
2428 cal_block = cal_utils_get_only_cal_block(
2429 this_afe.cal_data[cal_index]);
2430
Vikram Panduranga770b8382017-09-27 12:17:36 -07002431 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302432 pr_err("%s cal_block not found!!\n", __func__);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302433 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302434 goto unlock;
2435 }
2436
2437 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
2438
2439 ret = remap_cal_data(cal_block, cal_index);
2440 if (ret) {
2441 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2442 __func__, cal_index);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302443 ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302444 goto unlock;
2445 }
2446 ret = afe_send_cal_block(port_id, cal_block);
2447 if (ret < 0)
2448 pr_debug("%s: No cal sent for cal_index %d, port_id = 0x%x! ret %d\n",
2449 __func__, cal_index, port_id, ret);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002450
2451 cal_utils_mark_cal_used(cal_block);
2452
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302453unlock:
2454 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
2455done:
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302456 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302457}
2458
2459void afe_send_cal(u16 port_id)
2460{
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302461 int ret;
2462
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302463 pr_debug("%s: port_id=0x%x\n", __func__, port_id);
2464
2465 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) {
2466 afe_send_cal_spkr_prot_tx(port_id);
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05302467 ret = send_afe_cal_type(AFE_COMMON_TX_CAL, port_id);
2468 if (ret < 0)
2469 send_afe_cal_type(AFE_LSM_TX_CAL, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302470 } else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302471 send_afe_cal_type(AFE_COMMON_RX_CAL, port_id);
Xiaojun Sang092e0ed2017-12-11 16:13:32 +08002472 afe_send_cal_spkr_prot_rx(port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302473 }
2474}
2475
2476int afe_turn_onoff_hw_mad(u16 mad_type, u16 enable)
2477{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002478 struct afe_param_hw_mad_ctrl mad_enable_param;
2479 struct param_hdr_v3 param_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302480 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302481
2482 pr_debug("%s: enter\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302483
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002484 memset(&mad_enable_param, 0, sizeof(mad_enable_param));
2485 memset(&param_info, 0, sizeof(param_info));
2486 param_info.module_id = AFE_MODULE_HW_MAD;
2487 param_info.instance_id = INSTANCE_ID_0;
2488 param_info.param_id = AFE_PARAM_ID_HW_MAD_CTRL;
2489 param_info.param_size = sizeof(mad_enable_param);
2490
2491 mad_enable_param.minor_version = 1;
2492 mad_enable_param.mad_type = mad_type;
2493 mad_enable_param.mad_enable = enable;
2494
2495 ret = q6afe_pack_and_set_param_in_band(SLIMBUS_5_TX, IDX_GLOBAL_CFG,
2496 param_info,
2497 (u8 *) &mad_enable_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302498 if (ret)
2499 pr_err("%s: AFE_PARAM_ID_HW_MAD_CTRL failed %d\n", __func__,
2500 ret);
2501 return ret;
2502}
2503
2504static int afe_send_slimbus_slave_cfg(
2505 struct afe_param_cdc_slimbus_slave_cfg *sb_slave_cfg)
2506{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002507 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302508 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302509
2510 pr_debug("%s: enter\n", __func__);
2511
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002512 memset(&param_hdr, 0, sizeof(param_hdr));
2513 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2514 param_hdr.instance_id = INSTANCE_ID_0;
2515 param_hdr.param_id = AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG;
2516 param_hdr.param_size = sizeof(struct afe_param_cdc_slimbus_slave_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302517
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002518 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
2519 (u8 *) sb_slave_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302520 if (ret)
2521 pr_err("%s: AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG failed %d\n",
2522 __func__, ret);
2523
2524 pr_debug("%s: leave %d\n", __func__, ret);
2525 return ret;
2526}
2527
2528static int afe_send_codec_reg_page_config(
2529 struct afe_param_cdc_reg_page_cfg *cdc_reg_page_cfg)
2530{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002531 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302532 int ret;
2533
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002534 memset(&param_hdr, 0, sizeof(param_hdr));
2535 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2536 param_hdr.instance_id = INSTANCE_ID_0;
2537 param_hdr.param_id = AFE_PARAM_ID_CDC_REG_PAGE_CFG;
2538 param_hdr.param_size = sizeof(struct afe_param_cdc_reg_page_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302539
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002540 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
2541 (u8 *) cdc_reg_page_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302542 if (ret)
2543 pr_err("%s: AFE_PARAM_ID_CDC_REG_PAGE_CFG failed %d\n",
2544 __func__, ret);
2545
2546 return ret;
2547}
2548
2549static int afe_send_codec_reg_config(
2550 struct afe_param_cdc_reg_cfg_data *cdc_reg_cfg)
2551{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002552 u8 *packed_param_data = NULL;
2553 u32 packed_data_size = 0;
2554 u32 single_param_size = 0;
2555 u32 max_data_size = 0;
2556 u32 max_single_param = 0;
2557 struct param_hdr_v3 param_hdr;
2558 int idx = 0;
2559 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302560
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002561 memset(&param_hdr, 0, sizeof(param_hdr));
2562 max_single_param = sizeof(struct param_hdr_v3) +
2563 sizeof(struct afe_param_cdc_reg_cfg);
2564 max_data_size = APR_MAX_BUF - sizeof(struct afe_svc_cmd_set_param_v2);
2565 packed_param_data = kzalloc(max_data_size, GFP_KERNEL);
2566 if (!packed_param_data)
2567 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302568
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002569 /* param_hdr is the same for all params sent, set once at top */
2570 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2571 param_hdr.instance_id = INSTANCE_ID_0;
2572 param_hdr.param_id = AFE_PARAM_ID_CDC_REG_CFG;
2573 param_hdr.param_size = sizeof(struct afe_param_cdc_reg_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302574
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002575 while (idx < cdc_reg_cfg->num_registers) {
2576 memset(packed_param_data, 0, max_data_size);
2577 packed_data_size = 0;
2578 single_param_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302579
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002580 while (packed_data_size + max_single_param < max_data_size &&
2581 idx < cdc_reg_cfg->num_registers) {
2582 ret = q6common_pack_pp_params(
2583 packed_param_data + packed_data_size,
2584 &param_hdr, (u8 *) &cdc_reg_cfg->reg_data[idx],
2585 &single_param_size);
2586 if (ret) {
2587 pr_err("%s: Failed to pack parameters with error %d\n",
2588 __func__, ret);
2589 goto done;
2590 }
2591 packed_data_size += single_param_size;
2592 idx++;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302593 }
2594
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002595 ret = q6afe_svc_set_params(IDX_GLOBAL_CFG, NULL,
2596 packed_param_data, packed_data_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302597 if (ret) {
2598 pr_err("%s: AFE_PARAM_ID_CDC_REG_CFG failed %d\n",
2599 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302600 break;
2601 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302602 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002603done:
2604 kfree(packed_param_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302605 return ret;
2606}
2607
2608static int afe_init_cdc_reg_config(void)
2609{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002610 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302611 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302612
2613 pr_debug("%s: enter\n", __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002614 memset(&param_hdr, 0, sizeof(param_hdr));
2615 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2616 param_hdr.instance_id = INSTANCE_ID_0;
2617 param_hdr.param_id = AFE_PARAM_ID_CDC_REG_CFG_INIT;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302618
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002619 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
2620 NULL);
2621 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302622 pr_err("%s: AFE_PARAM_ID_CDC_INIT_REG_CFG failed %d\n",
2623 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302624
2625 return ret;
2626}
2627
2628static int afe_send_slimbus_slave_port_cfg(
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002629 struct afe_param_slimbus_slave_port_cfg *slim_slave_config, u16 port_id)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302630{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002631 struct param_hdr_v3 param_hdr;
2632 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302633
2634 pr_debug("%s: enter, port_id = 0x%x\n", __func__, port_id);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002635 memset(&param_hdr, 0, sizeof(param_hdr));
2636 param_hdr.module_id = AFE_MODULE_HW_MAD;
2637 param_hdr.instance_id = INSTANCE_ID_0;
2638 param_hdr.reserved = 0;
2639 param_hdr.param_id = AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG;
2640 param_hdr.param_size = sizeof(struct afe_param_slimbus_slave_port_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302641
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002642 ret = q6afe_pack_and_set_param_in_band(port_id,
2643 q6audio_get_port_index(port_id),
2644 param_hdr,
2645 (u8 *) slim_slave_config);
2646 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302647 pr_err("%s: AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG failed %d\n",
2648 __func__, ret);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002649
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302650 pr_debug("%s: leave %d\n", __func__, ret);
2651 return ret;
2652}
2653static int afe_aanc_port_cfg(void *apr, uint16_t tx_port, uint16_t rx_port)
2654{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002655 struct afe_param_aanc_port_cfg aanc_port_cfg;
2656 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302657 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302658
2659 pr_debug("%s: tx_port 0x%x, rx_port 0x%x\n",
2660 __func__, tx_port, rx_port);
2661
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002662 pr_debug("%s: AANC sample rate tx rate: %d rx rate %d\n", __func__,
2663 this_afe.aanc_info.aanc_tx_port_sample_rate,
2664 this_afe.aanc_info.aanc_rx_port_sample_rate);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302665
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002666 memset(&aanc_port_cfg, 0, sizeof(aanc_port_cfg));
2667 memset(&param_hdr, 0, sizeof(param_hdr));
2668
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302669 /*
2670 * If aanc tx sample rate or rx sample rate is zero, skip aanc
2671 * configuration as AFE resampler will fail for invalid sample
2672 * rates.
2673 */
2674 if (!this_afe.aanc_info.aanc_tx_port_sample_rate ||
2675 !this_afe.aanc_info.aanc_rx_port_sample_rate) {
2676 return -EINVAL;
2677 }
2678
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002679 param_hdr.module_id = AFE_MODULE_AANC;
2680 param_hdr.instance_id = INSTANCE_ID_0;
2681 param_hdr.param_id = AFE_PARAM_ID_AANC_PORT_CONFIG;
2682 param_hdr.param_size = sizeof(struct afe_param_aanc_port_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302683
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002684 aanc_port_cfg.aanc_port_cfg_minor_version =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302685 AFE_API_VERSION_AANC_PORT_CONFIG;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002686 aanc_port_cfg.tx_port_sample_rate =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302687 this_afe.aanc_info.aanc_tx_port_sample_rate;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002688 aanc_port_cfg.tx_port_channel_map[0] = AANC_TX_VOICE_MIC;
2689 aanc_port_cfg.tx_port_channel_map[1] = AANC_TX_NOISE_MIC;
2690 aanc_port_cfg.tx_port_channel_map[2] = AANC_TX_ERROR_MIC;
2691 aanc_port_cfg.tx_port_channel_map[3] = AANC_TX_MIC_UNUSED;
2692 aanc_port_cfg.tx_port_channel_map[4] = AANC_TX_MIC_UNUSED;
2693 aanc_port_cfg.tx_port_channel_map[5] = AANC_TX_MIC_UNUSED;
2694 aanc_port_cfg.tx_port_channel_map[6] = AANC_TX_MIC_UNUSED;
2695 aanc_port_cfg.tx_port_channel_map[7] = AANC_TX_MIC_UNUSED;
2696 aanc_port_cfg.tx_port_num_channels = 3;
2697 aanc_port_cfg.rx_path_ref_port_id = rx_port;
2698 aanc_port_cfg.ref_port_sample_rate =
2699 this_afe.aanc_info.aanc_rx_port_sample_rate;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302700
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002701 ret = q6afe_pack_and_set_param_in_band(tx_port,
2702 q6audio_get_port_index(tx_port),
2703 param_hdr,
2704 (u8 *) &aanc_port_cfg);
2705 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302706 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 -08002707 __func__, tx_port, rx_port, ret);
Sudheer Papothiaf431ad2018-05-04 05:06:11 +05302708 else
2709 q6afe_set_aanc_level();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302710
2711 return ret;
2712}
2713
2714static int afe_aanc_mod_enable(void *apr, uint16_t tx_port, uint16_t enable)
2715{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002716 struct afe_mod_enable_param mod_enable;
2717 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302718 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302719
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002720 pr_debug("%s: tx_port 0x%x\n", __func__, tx_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302721
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002722 memset(&mod_enable, 0, sizeof(mod_enable));
2723 memset(&param_hdr, 0, sizeof(param_hdr));
2724 param_hdr.module_id = AFE_MODULE_AANC;
2725 param_hdr.instance_id = INSTANCE_ID_0;
2726 param_hdr.param_id = AFE_PARAM_ID_ENABLE;
2727 param_hdr.param_size = sizeof(struct afe_mod_enable_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302728
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002729 mod_enable.enable = enable;
2730 mod_enable.reserved = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302731
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002732 ret = q6afe_pack_and_set_param_in_band(tx_port,
2733 q6audio_get_port_index(tx_port),
2734 param_hdr, (u8 *) &mod_enable);
2735 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302736 pr_err("%s: AFE AANC enable failed for tx_port 0x%x ret %d\n",
2737 __func__, tx_port, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302738 return ret;
2739}
2740
2741static int afe_send_bank_selection_clip(
2742 struct afe_param_id_clip_bank_sel *param)
2743{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002744 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302745 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302746
2747 if (!param) {
2748 pr_err("%s: Invalid params", __func__);
2749 return -EINVAL;
2750 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002751 memset(&param_hdr, 0, sizeof(param_hdr));
2752 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2753 param_hdr.instance_id = INSTANCE_ID_0;
2754 param_hdr.param_id = AFE_PARAM_ID_CLIP_BANK_SEL_CFG;
2755 param_hdr.param_size = sizeof(struct afe_param_id_clip_bank_sel);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302756
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002757 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
2758 (u8 *) param);
2759 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302760 pr_err("%s: AFE_PARAM_ID_CLIP_BANK_SEL_CFG failed %d\n",
2761 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302762 return ret;
2763}
2764int afe_send_aanc_version(
2765 struct afe_param_id_cdc_aanc_version *version_cfg)
2766{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002767 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302768 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302769
2770 pr_debug("%s: enter\n", __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002771 memset(&param_hdr, 0, sizeof(param_hdr));
2772 param_hdr.module_id = AFE_MODULE_CDC_DEV_CFG;
2773 param_hdr.instance_id = INSTANCE_ID_0;
2774 param_hdr.param_id = AFE_PARAM_ID_CDC_AANC_VERSION;
2775 param_hdr.param_size = sizeof(struct afe_param_id_cdc_aanc_version);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302776
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002777 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
2778 (u8 *) version_cfg);
2779 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302780 pr_err("%s: AFE_PARAM_ID_CDC_AANC_VERSION failed %d\n",
2781 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302782 return ret;
2783}
2784
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302785/**
2786 * afe_port_set_mad_type -
2787 * to update mad type
2788 *
2789 * @port_id: AFE port id number
2790 * @mad_type: MAD type enum value
2791 *
2792 * Returns 0 on success or error on failure.
2793 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302794int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type)
2795{
2796 int i;
2797
2798 if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
Aditya Bavanarie9454c62018-08-23 23:45:20 +05302799 port_id == AFE_PORT_ID_INT3_MI2S_TX ||
2800 port_id == AFE_PORT_ID_TX_CODEC_DMA_TX_3) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302801 mad_type = MAD_SW_AUDIO;
2802 return 0;
2803 }
2804
2805 i = port_id - SLIMBUS_0_RX;
2806 if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
2807 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2808 return -EINVAL;
2809 }
2810 atomic_set(&afe_ports_mad_type[i], mad_type);
2811 return 0;
2812}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302813EXPORT_SYMBOL(afe_port_set_mad_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302814
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302815/**
2816 * afe_port_get_mad_type -
2817 * to retrieve mad type
2818 *
2819 * @port_id: AFE port id number
2820 *
2821 * Returns valid enum value on success or MAD_HW_NONE on failure.
2822 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302823enum afe_mad_type afe_port_get_mad_type(u16 port_id)
2824{
2825 int i;
2826
2827 if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
Aditya Bavanarie9454c62018-08-23 23:45:20 +05302828 port_id == AFE_PORT_ID_INT3_MI2S_TX ||
2829 port_id == AFE_PORT_ID_TX_CODEC_DMA_TX_3)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302830 return MAD_SW_AUDIO;
2831
2832 i = port_id - SLIMBUS_0_RX;
2833 if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
2834 pr_debug("%s: Non Slimbus port_id 0x%x\n", __func__, port_id);
2835 return MAD_HW_NONE;
2836 }
2837 return (enum afe_mad_type) atomic_read(&afe_ports_mad_type[i]);
2838}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302839EXPORT_SYMBOL(afe_port_get_mad_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302840
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302841/**
2842 * afe_set_config -
2843 * to configure AFE session with
2844 * specified configuration for given config type
2845 *
2846 * @config_type: config type
2847 * @config_data: configuration to pass to AFE session
2848 * @arg: argument used in specific config types
2849 *
2850 * Returns 0 on success or error value on port start failure.
2851 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302852int afe_set_config(enum afe_config_type config_type, void *config_data, int arg)
2853{
2854 int ret;
2855
2856 pr_debug("%s: enter config_type %d\n", __func__, config_type);
2857 ret = afe_q6_interface_prepare();
2858 if (ret) {
2859 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
2860 return ret;
2861 }
2862
2863 switch (config_type) {
2864 case AFE_SLIMBUS_SLAVE_CONFIG:
2865 ret = afe_send_slimbus_slave_cfg(config_data);
2866 if (!ret)
2867 ret = afe_init_cdc_reg_config();
2868 else
2869 pr_err("%s: Sending slimbus slave config failed %d\n",
2870 __func__, ret);
2871 break;
2872 case AFE_CDC_REGISTERS_CONFIG:
2873 ret = afe_send_codec_reg_config(config_data);
2874 break;
2875 case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
2876 ret = afe_send_slimbus_slave_port_cfg(config_data, arg);
2877 break;
2878 case AFE_AANC_VERSION:
2879 ret = afe_send_aanc_version(config_data);
2880 break;
2881 case AFE_CLIP_BANK_SEL:
2882 ret = afe_send_bank_selection_clip(config_data);
2883 break;
2884 case AFE_CDC_CLIP_REGISTERS_CONFIG:
2885 ret = afe_send_codec_reg_config(config_data);
2886 break;
2887 case AFE_CDC_REGISTER_PAGE_CONFIG:
2888 ret = afe_send_codec_reg_page_config(config_data);
2889 break;
2890 default:
2891 pr_err("%s: unknown configuration type %d",
2892 __func__, config_type);
2893 ret = -EINVAL;
2894 }
2895
2896 if (!ret)
2897 set_bit(config_type, &afe_configured_cmd);
2898
2899 return ret;
2900}
2901EXPORT_SYMBOL(afe_set_config);
2902
2903/*
2904 * afe_clear_config - If SSR happens ADSP loses AFE configs, let AFE driver know
2905 * about the state so client driver can wait until AFE is
2906 * reconfigured.
2907 */
2908void afe_clear_config(enum afe_config_type config)
2909{
2910 clear_bit(config, &afe_configured_cmd);
2911}
2912EXPORT_SYMBOL(afe_clear_config);
2913
2914bool afe_has_config(enum afe_config_type config)
2915{
2916 return !!test_bit(config, &afe_configured_cmd);
2917}
2918
2919int afe_send_spdif_clk_cfg(struct afe_param_id_spdif_clk_cfg *cfg,
2920 u16 port_id)
2921{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002922 struct afe_param_id_spdif_clk_cfg clk_cfg;
2923 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302924 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302925
2926 if (!cfg) {
2927 pr_err("%s: Error, no configuration data\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302928 return -EINVAL;
2929 }
2930
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002931 memset(&clk_cfg, 0, sizeof(clk_cfg));
2932 memset(&param_hdr, 0, sizeof(param_hdr));
2933 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2934 param_hdr.instance_id = INSTANCE_ID_0;
2935 param_hdr.param_id = AFE_PARAM_ID_SPDIF_CLK_CONFIG;
2936 param_hdr.param_size = sizeof(struct afe_param_id_spdif_clk_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302937
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002938 pr_debug("%s: Minor version = 0x%x clk val = %d clk root = 0x%x port id = 0x%x\n",
2939 __func__, clk_cfg.clk_cfg_minor_version, clk_cfg.clk_value,
2940 clk_cfg.clk_root, q6audio_get_port_id(port_id));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302941
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002942 ret = q6afe_pack_and_set_param_in_band(port_id,
2943 q6audio_get_port_index(port_id),
2944 param_hdr, (u8 *) &clk_cfg);
2945 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302946 pr_err("%s: AFE send clock config for port 0x%x failed ret = %d\n",
2947 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302948 return ret;
2949}
2950
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302951/**
2952 * afe_send_spdif_ch_status_cfg -
2953 * to configure AFE session with
2954 * specified channel status configuration
2955 *
2956 * @ch_status_cfg: channel status configutation
2957 * @port_id: AFE port id number
2958 *
2959 * Returns 0 on success or error value on port start failure.
2960 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302961int afe_send_spdif_ch_status_cfg(struct afe_param_id_spdif_ch_status_cfg
2962 *ch_status_cfg, u16 port_id)
2963{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002964 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302965 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302966
Karthikeyan Mani0253cb92018-11-30 11:14:36 -08002967 if (!ch_status_cfg) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302968 pr_err("%s: Error, no configuration data\n", __func__);
Karthikeyan Mani0253cb92018-11-30 11:14:36 -08002969 return -EINVAL;
2970 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302971
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002972 memset(&param_hdr, 0, sizeof(param_hdr));
2973 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
2974 param_hdr.instance_id = INSTANCE_ID_0;
2975 param_hdr.param_id = AFE_PARAM_ID_SPDIF_CLK_CONFIG;
2976 param_hdr.param_size = sizeof(struct afe_param_id_spdif_ch_status_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302977
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08002978 ret = q6afe_pack_and_set_param_in_band(port_id,
2979 q6audio_get_port_index(port_id),
2980 param_hdr, (u8 *) ch_status_cfg);
2981 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302982 pr_err("%s: AFE send channel status for port 0x%x failed ret = %d\n",
2983 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302984 return ret;
2985}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302986EXPORT_SYMBOL(afe_send_spdif_ch_status_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302987
Ramprasad Katkam250075f2018-08-31 03:31:54 +05302988int afe_send_cmd_wakeup_register(void *handle, bool enable)
2989{
2990 struct afe_svc_cmd_evt_cfg_payload wakeup_irq;
Aditya Bavanari91674b52018-11-23 17:02:49 +05302991 int ret = 0;
Ramprasad Katkam250075f2018-08-31 03:31:54 +05302992
2993 pr_debug("%s: enter\n", __func__);
2994
2995 wakeup_irq.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2996 APR_HDR_LEN(APR_HDR_SIZE),
2997 APR_PKT_VER);
2998 wakeup_irq.hdr.pkt_size = sizeof(wakeup_irq);
2999 wakeup_irq.hdr.src_port = 0;
3000 wakeup_irq.hdr.dest_port = 0;
3001 wakeup_irq.hdr.token = 0x0;
3002 wakeup_irq.hdr.opcode = AFE_SVC_CMD_EVENT_CFG;
3003 wakeup_irq.event_id = AFE_EVENT_ID_MBHC_DETECTION_SW_WA;
3004 wakeup_irq.reg_flag = enable;
Aditya Bavanari91674b52018-11-23 17:02:49 +05303005 pr_debug("%s: cmd wakeup register opcode[0x%x] register:%d\n",
Ramprasad Katkam250075f2018-08-31 03:31:54 +05303006 __func__, wakeup_irq.hdr.opcode, wakeup_irq.reg_flag);
3007
3008 ret = afe_apr_send_pkt(&wakeup_irq, &this_afe.wait_wakeup);
Aditya Bavanari91674b52018-11-23 17:02:49 +05303009 if (ret)
Ramprasad Katkam250075f2018-08-31 03:31:54 +05303010 pr_err("%s: AFE wakeup command register %d failed %d\n",
3011 __func__, enable, ret);
Ramprasad Katkam250075f2018-08-31 03:31:54 +05303012
3013 return ret;
3014}
3015EXPORT_SYMBOL(afe_send_cmd_wakeup_register);
3016
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303017static int afe_send_cmd_port_start(u16 port_id)
3018{
3019 struct afe_port_cmd_device_start start;
3020 int ret, index;
3021
3022 pr_debug("%s: enter\n", __func__);
3023 index = q6audio_get_port_index(port_id);
3024 if (index < 0 || index >= AFE_MAX_PORTS) {
3025 pr_err("%s: AFE port index[%d] invalid!\n",
3026 __func__, index);
3027 return -EINVAL;
3028 }
3029 ret = q6audio_validate_port(port_id);
3030 if (ret < 0) {
3031 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
3032 return -EINVAL;
3033 }
3034
3035 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3036 APR_HDR_LEN(APR_HDR_SIZE),
3037 APR_PKT_VER);
3038 start.hdr.pkt_size = sizeof(start);
3039 start.hdr.src_port = 0;
3040 start.hdr.dest_port = 0;
3041 start.hdr.token = index;
3042 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
3043 start.port_id = q6audio_get_port_id(port_id);
3044 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
3045 __func__, start.hdr.opcode, start.port_id);
3046
3047 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
Aditya Bavanari91674b52018-11-23 17:02:49 +05303048 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303049 pr_err("%s: AFE enable for port 0x%x failed %d\n", __func__,
3050 port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303051
3052 return ret;
3053}
3054
3055static int afe_aanc_start(uint16_t tx_port_id, uint16_t rx_port_id)
3056{
3057 int ret;
3058
3059 pr_debug("%s: Tx port is 0x%x, Rx port is 0x%x\n",
3060 __func__, tx_port_id, rx_port_id);
3061 ret = afe_aanc_port_cfg(this_afe.apr, tx_port_id, rx_port_id);
3062 if (ret) {
3063 pr_err("%s: Send AANC Port Config failed %d\n",
3064 __func__, ret);
3065 goto fail_cmd;
3066 }
3067 send_afe_cal_type(AFE_AANC_CAL, tx_port_id);
3068
3069fail_cmd:
3070 return ret;
3071}
3072
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303073/**
3074 * afe_spdif_port_start - to configure AFE session with
3075 * specified port configuration
3076 *
3077 * @port_id: AFE port id number
3078 * @spdif_port: spdif port configutation
3079 * @rate: sampling rate of port
3080 *
3081 * Returns 0 on success or error value on port start failure.
3082 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303083int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port,
3084 u32 rate)
3085{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003086 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303087 uint16_t port_index;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003088 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303089
3090 if (!spdif_port) {
3091 pr_err("%s: Error, no configuration data\n", __func__);
3092 ret = -EINVAL;
3093 return ret;
3094 }
3095
3096 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
3097
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003098 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303099 ret = q6audio_validate_port(port_id);
3100 if (ret < 0) {
3101 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
3102 return -EINVAL;
3103 }
3104
3105 afe_send_cal(port_id);
3106 afe_send_hw_delay(port_id, rate);
3107
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003108 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3109 param_hdr.instance_id = INSTANCE_ID_0;
3110 param_hdr.param_id = AFE_PARAM_ID_SPDIF_CONFIG;
3111 param_hdr.param_size = sizeof(struct afe_spdif_port_config);
3112
3113 ret = q6afe_pack_and_set_param_in_band(port_id,
3114 q6audio_get_port_index(port_id),
3115 param_hdr, (u8 *) spdif_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303116 if (ret) {
3117 pr_err("%s: AFE enable for port 0x%x failed ret = %d\n",
Ralf Herzcc29b9e2018-07-17 20:19:04 +05303118 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303119 goto fail_cmd;
3120 }
3121
3122 port_index = afe_get_port_index(port_id);
3123 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3124 this_afe.afe_sample_rates[port_index] = rate;
3125 } else {
3126 pr_err("%s: Invalid port index %d\n", __func__, port_index);
3127 ret = -EINVAL;
3128 goto fail_cmd;
3129 }
3130
Ralf Herzcc29b9e2018-07-17 20:19:04 +05303131 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) {
3132 ret = afe_send_spdif_ch_status_cfg(&spdif_port->ch_status,
3133 port_id);
3134 if (ret < 0) {
3135 pr_err("%s: afe send failed %d\n", __func__, ret);
3136 goto fail_cmd;
3137 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303138 }
3139
3140 return afe_send_cmd_port_start(port_id);
3141
3142fail_cmd:
3143 return ret;
3144}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303145EXPORT_SYMBOL(afe_spdif_port_start);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303146
Ralf Herzcc29b9e2018-07-17 20:19:04 +05303147/**
3148 * afe_spdif_reg_event_cfg -
3149 * register for event from AFE spdif port
3150 *
3151 * @port_id: Port ID to register event
3152 * @reg_flag: register or unregister
3153 * @cb: callback function to invoke for events from module
3154 * @private_data: private data to sent back in callback fn
3155 *
3156 * Returns 0 on success or error on failure
3157 */
3158int afe_spdif_reg_event_cfg(u16 port_id, u16 reg_flag,
3159 void (*cb)(uint32_t opcode,
3160 uint32_t token, uint32_t *payload, void *priv),
3161 void *private_data)
3162{
3163 struct afe_port_cmd_event_cfg *config;
3164 struct afe_port_cmd_mod_evt_cfg_payload pl;
3165 int index;
3166 int ret;
3167 int num_events = 1;
3168 int cmd_size = sizeof(struct afe_port_cmd_event_cfg) +
3169 (num_events * sizeof(struct afe_port_cmd_mod_evt_cfg_payload));
3170
3171 config = kzalloc(cmd_size, GFP_KERNEL);
3172 if (!config)
3173 return -ENOMEM;
3174
3175 if (port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) {
3176 this_afe.pri_spdif_tx_cb = cb;
3177 this_afe.pri_spdif_tx_private_data = private_data;
3178 } else if (port_id == AFE_PORT_ID_SECONDARY_SPDIF_TX) {
3179 this_afe.sec_spdif_tx_cb = cb;
3180 this_afe.sec_spdif_tx_private_data = private_data;
3181 } else {
3182 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
3183 ret = -EINVAL;
3184 goto fail_idx;
3185 }
3186
3187 index = q6audio_get_port_index(port_id);
3188 if (index < 0) {
3189 pr_err("%s: Invalid index number: %d\n", __func__, index);
3190 ret = -EINVAL;
3191 goto fail_idx;
3192 }
3193
3194 memset(&pl, 0, sizeof(pl));
3195 pl.module_id = AFE_MODULE_CUSTOM_EVENTS;
3196 pl.event_id = AFE_PORT_FMT_UPDATE_EVENT;
3197 pl.reg_flag = reg_flag;
3198
3199 config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3200 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3201 config->hdr.pkt_size = cmd_size;
3202 config->hdr.src_port = 1;
3203 config->hdr.dest_port = 1;
3204 config->hdr.token = index;
3205
3206 config->hdr.opcode = AFE_PORT_CMD_MOD_EVENT_CFG;
3207 config->port_id = q6audio_get_port_id(port_id);
3208 config->num_events = num_events;
3209 config->version = 1;
3210 memcpy(config->payload, &pl, sizeof(pl));
3211 atomic_set(&this_afe.state, 1);
3212 atomic_set(&this_afe.status, 0);
3213 ret = apr_send_pkt(this_afe.apr, (uint32_t *) config);
3214 if (ret < 0) {
3215 pr_err("%s: port = 0x%x failed %d\n",
3216 __func__, port_id, ret);
3217 goto fail_cmd;
3218 }
3219 ret = wait_event_timeout(this_afe.wait[index],
3220 (atomic_read(&this_afe.state) == 0),
3221 msecs_to_jiffies(TIMEOUT_MS));
3222 if (!ret) {
3223 pr_err("%s: wait_event timeout\n", __func__);
3224 ret = -EINVAL;
3225 goto fail_cmd;
3226 }
3227 if (atomic_read(&this_afe.status) > 0) {
3228 pr_err("%s: config cmd failed [%s]\n",
3229 __func__, adsp_err_get_err_str(
3230 atomic_read(&this_afe.status)));
3231 ret = adsp_err_get_lnx_err_code(
3232 atomic_read(&this_afe.status));
3233 goto fail_idx;
3234 }
3235 ret = 0;
3236fail_cmd:
3237 pr_debug("%s: config.opcode 0x%x status %d\n",
3238 __func__, config->hdr.opcode, ret);
3239
3240fail_idx:
3241 kfree(config);
3242 return ret;
3243}
3244EXPORT_SYMBOL(afe_spdif_reg_event_cfg);
3245
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303246int afe_send_slot_mapping_cfg(
3247 struct afe_param_id_slot_mapping_cfg *slot_mapping_cfg,
3248 u16 port_id)
3249{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003250 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303251 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303252
3253 if (!slot_mapping_cfg) {
3254 pr_err("%s: Error, no configuration data\n", __func__);
3255 return -EINVAL;
3256 }
3257
3258 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
3259
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003260 memset(&param_hdr, 0, sizeof(param_hdr));
3261 param_hdr.module_id = AFE_MODULE_TDM;
3262 param_hdr.instance_id = INSTANCE_ID_0;
3263 param_hdr.param_id = AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG;
3264 param_hdr.param_size = sizeof(struct afe_param_id_slot_mapping_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303265
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003266 ret = q6afe_pack_and_set_param_in_band(port_id,
3267 q6audio_get_port_index(port_id),
3268 param_hdr,
3269 (u8 *) slot_mapping_cfg);
3270 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303271 pr_err("%s: AFE send slot mapping for port 0x%x failed ret = %d\n",
3272 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303273 return ret;
3274}
3275
3276int afe_send_custom_tdm_header_cfg(
3277 struct afe_param_id_custom_tdm_header_cfg *custom_tdm_header_cfg,
3278 u16 port_id)
3279{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003280 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303281 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303282
3283 if (!custom_tdm_header_cfg) {
3284 pr_err("%s: Error, no configuration data\n", __func__);
3285 return -EINVAL;
3286 }
3287
3288 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
3289
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003290 memset(&param_hdr, 0, sizeof(param_hdr));
3291 param_hdr.module_id = AFE_MODULE_TDM;
3292 param_hdr.instance_id = INSTANCE_ID_0;
3293 param_hdr.param_id = AFE_PARAM_ID_CUSTOM_TDM_HEADER_CONFIG;
3294 param_hdr.param_size =
3295 sizeof(struct afe_param_id_custom_tdm_header_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303296
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003297 ret = q6afe_pack_and_set_param_in_band(port_id,
3298 q6audio_get_port_index(port_id),
3299 param_hdr,
3300 (u8 *) custom_tdm_header_cfg);
3301 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303302 pr_err("%s: AFE send custom tdm header for port 0x%x failed ret = %d\n",
3303 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303304 return ret;
3305}
3306
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303307/**
3308 * afe_tdm_port_start - to configure AFE session with
3309 * specified port configuration
3310 *
3311 * @port_id: AFE port id number
3312 * @tdm_port: TDM port configutation
3313 * @rate: sampling rate of port
3314 * @num_groups: number of TDM groups
3315 *
3316 * Returns 0 on success or error value on port start failure.
3317 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303318int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
3319 u32 rate, u16 num_groups)
3320{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003321 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303322 int index = 0;
3323 uint16_t port_index = 0;
3324 enum afe_mad_type mad_type = MAD_HW_NONE;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003325 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303326
3327 if (!tdm_port) {
3328 pr_err("%s: Error, no configuration data\n", __func__);
3329 return -EINVAL;
3330 }
3331
3332 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
3333
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003334 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303335 index = q6audio_get_port_index(port_id);
3336 if (index < 0 || index >= AFE_MAX_PORTS) {
3337 pr_err("%s: AFE port index[%d] invalid!\n",
3338 __func__, index);
3339 return -EINVAL;
3340 }
3341 ret = q6audio_validate_port(port_id);
3342 if (ret < 0) {
3343 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
3344 return -EINVAL;
3345 }
3346
3347 ret = afe_q6_interface_prepare();
3348 if (ret != 0) {
3349 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
3350 return ret;
3351 }
3352
3353 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
3354 this_afe.afe_sample_rates[index] = rate;
3355
3356 if (this_afe.rt_cb)
3357 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
3358 }
3359
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303360 port_index = afe_get_port_index(port_id);
Mangesh Kunchamwarbc81e3a2018-10-09 11:38:02 +05303361
3362 if (q6core_get_avcs_api_version_per_service(
3363 APRV2_IDS_SERVICE_ID_ADSP_AFE_V) >= AFE_API_VERSION_V4) {
3364 /* send VAD configuration if enabled */
3365 if (this_afe.vad_cfg[port_index].is_enable) {
3366 ret = afe_send_port_vad_cfg_params(port_id);
3367 if (ret) {
3368 pr_err("%s: afe send VAD config failed %d\n",
3369 __func__, ret);
3370 goto fail_cmd;
3371 }
3372 }
3373 }
3374
3375 /* Also send the topology id here: */
Xiaoyu Ye13da4822017-09-18 17:46:30 -07003376 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303377 /* One time call: only for first time */
3378 afe_send_custom_topology();
3379 afe_send_port_topology_id(port_id);
3380 afe_send_cal(port_id);
3381 afe_send_hw_delay(port_id, rate);
3382 }
3383
3384 /* Start SW MAD module */
3385 mad_type = afe_port_get_mad_type(port_id);
3386 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
3387 mad_type);
3388 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
3389 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
3390 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
3391 pr_err("%s: AFE isn't configured yet for\n"
3392 "HW MAD try Again\n", __func__);
3393 ret = -EAGAIN;
3394 goto fail_cmd;
3395 }
3396 ret = afe_turn_onoff_hw_mad(mad_type, true);
3397 if (ret) {
3398 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
3399 __func__, ret);
3400 goto fail_cmd;
3401 }
3402 }
3403
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003404 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3405 param_hdr.instance_id = INSTANCE_ID_0;
3406 param_hdr.param_id = AFE_PARAM_ID_TDM_CONFIG;
3407 param_hdr.param_size = sizeof(struct afe_param_id_tdm_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303408
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003409 ret = q6afe_pack_and_set_param_in_band(port_id,
3410 q6audio_get_port_index(port_id),
3411 param_hdr,
3412 (u8 *) &tdm_port->tdm);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303413 if (ret) {
3414 pr_err("%s: AFE enable for port 0x%x failed ret = %d\n",
3415 __func__, port_id, ret);
3416 goto fail_cmd;
3417 }
3418
3419 port_index = afe_get_port_index(port_id);
3420 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
3421 this_afe.afe_sample_rates[port_index] = rate;
3422 } else {
3423 pr_err("%s: Invalid port index %d\n", __func__, port_index);
3424 ret = -EINVAL;
3425 goto fail_cmd;
3426 }
Xiaoyu Ye13da4822017-09-18 17:46:30 -07003427
3428 ret = afe_send_slot_mapping_cfg(&tdm_port->slot_mapping,
3429 port_id);
3430 if (ret < 0) {
3431 pr_err("%s: afe send failed %d\n", __func__, ret);
3432 goto fail_cmd;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303433 }
3434
3435 if (tdm_port->custom_tdm_header.header_type) {
3436 ret = afe_send_custom_tdm_header_cfg(
3437 &tdm_port->custom_tdm_header, port_id);
3438 if (ret < 0) {
3439 pr_err("%s: afe send failed %d\n", __func__, ret);
3440 goto fail_cmd;
3441 }
3442 }
3443
3444 ret = afe_send_cmd_port_start(port_id);
3445
3446fail_cmd:
3447 return ret;
3448}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303449EXPORT_SYMBOL(afe_tdm_port_start);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303450
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303451/**
3452 * afe_set_cal_mode -
3453 * set cal mode for AFE calibration
3454 *
3455 * @port_id: AFE port id number
3456 * @afe_cal_mode: AFE calib mode
3457 *
3458 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303459void afe_set_cal_mode(u16 port_id, enum afe_cal_mode afe_cal_mode)
3460{
3461 uint16_t port_index;
3462
3463 port_index = afe_get_port_index(port_id);
3464 this_afe.afe_cal_mode[port_index] = afe_cal_mode;
3465}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303466EXPORT_SYMBOL(afe_set_cal_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303467
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303468/**
Mangesh Kunchamwar4e1e7182018-04-26 17:58:58 +05303469 * afe_set_vad_cfg -
3470 * set configuration for VAD
3471 *
3472 * @port_id: AFE port id number
3473 * @vad_enable: enable/disable vad
3474 * @preroll_config: Preroll configuration
3475 *
3476 */
3477void afe_set_vad_cfg(u32 vad_enable, u32 preroll_config,
3478 u32 port_id)
3479{
3480 uint16_t port_index;
3481
3482 port_index = afe_get_port_index(port_id);
3483 this_afe.vad_cfg[port_index].is_enable = vad_enable;
3484 this_afe.vad_cfg[port_index].pre_roll = preroll_config;
3485}
3486EXPORT_SYMBOL(afe_set_vad_cfg);
3487
3488/**
Mangesh Kunchamwar07b8dc92018-07-16 19:46:25 +05303489 * afe_get_island_mode_cfg -
3490 * get island mode configuration
3491 *
3492 * @port_id: AFE port id number
3493 * @enable_flag: Enable or Disable
3494 *
3495 */
3496void afe_get_island_mode_cfg(u16 port_id, u32 *enable_flag)
3497{
3498 uint16_t port_index;
3499
3500 if (enable_flag) {
3501 port_index = afe_get_port_index(port_id);
3502 *enable_flag = this_afe.island_mode[port_index];
3503 }
3504}
3505EXPORT_SYMBOL(afe_get_island_mode_cfg);
3506
3507/**
Mangesh Kunchamwar4e1e7182018-04-26 17:58:58 +05303508 * afe_set_island_mode_cfg -
3509 * set island mode configuration
3510 *
3511 * @port_id: AFE port id number
3512 * @enable_flag: Enable or Disable
3513 *
3514 */
3515void afe_set_island_mode_cfg(u16 port_id, u32 enable_flag)
3516{
3517 uint16_t port_index;
3518
3519 port_index = afe_get_port_index(port_id);
3520 this_afe.island_mode[port_index] = enable_flag;
3521
3522}
3523EXPORT_SYMBOL(afe_set_island_mode_cfg);
3524
3525/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303526 * afe_set_routing_callback -
3527 * Update callback function for routing
3528 *
3529 * @cb: callback function to update with
3530 *
3531 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303532void afe_set_routing_callback(routing_cb cb)
3533{
3534 this_afe.rt_cb = cb;
3535}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303536EXPORT_SYMBOL(afe_set_routing_callback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303537
3538int afe_port_send_usb_dev_param(u16 port_id, union afe_port_config *afe_config)
3539{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003540 struct afe_param_id_usb_audio_dev_params usb_dev;
3541 struct afe_param_id_usb_audio_dev_lpcm_fmt lpcm_fmt;
Garmond Leung6b3f4182018-05-11 12:29:34 -07003542 struct afe_param_id_usb_audio_svc_interval svc_int;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003543 struct param_hdr_v3 param_hdr;
Garmond Leung6b3f4182018-05-11 12:29:34 -07003544 int ret = 0, index = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303545
3546 if (!afe_config) {
3547 pr_err("%s: Error, no configuration data\n", __func__);
3548 ret = -EINVAL;
3549 goto exit;
3550 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303551
Garmond Leung6b3f4182018-05-11 12:29:34 -07003552 index = q6audio_get_port_index(port_id);
3553
3554 if (index < 0 || index >= AFE_MAX_PORTS) {
3555 pr_err("%s: AFE port index[%d] invalid!\n",
3556 __func__, index);
3557 return -EINVAL;
3558 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003559 memset(&usb_dev, 0, sizeof(usb_dev));
3560 memset(&lpcm_fmt, 0, sizeof(lpcm_fmt));
3561 memset(&param_hdr, 0, sizeof(param_hdr));
3562 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
3563 param_hdr.instance_id = INSTANCE_ID_0;
3564
3565 param_hdr.param_id = AFE_PARAM_ID_USB_AUDIO_DEV_PARAMS;
3566 param_hdr.param_size = sizeof(usb_dev);
Garmond Leung6b3f4182018-05-11 12:29:34 -07003567 usb_dev.cfg_minor_version = AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003568 usb_dev.dev_token = afe_config->usb_audio.dev_token;
3569
3570 ret = q6afe_pack_and_set_param_in_band(port_id,
3571 q6audio_get_port_index(port_id),
3572 param_hdr, (u8 *) &usb_dev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303573 if (ret) {
3574 pr_err("%s: AFE device param cmd failed %d\n",
3575 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303576 goto exit;
3577 }
3578
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003579 param_hdr.param_id = AFE_PARAM_ID_USB_AUDIO_DEV_LPCM_FMT;
3580 param_hdr.param_size = sizeof(lpcm_fmt);
Garmond Leung6b3f4182018-05-11 12:29:34 -07003581 lpcm_fmt.cfg_minor_version = AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003582 lpcm_fmt.endian = afe_config->usb_audio.endian;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303583
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003584 ret = q6afe_pack_and_set_param_in_band(port_id,
3585 q6audio_get_port_index(port_id),
3586 param_hdr, (u8 *) &lpcm_fmt);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303587 if (ret) {
3588 pr_err("%s: AFE device param cmd LPCM_FMT failed %d\n",
3589 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303590 goto exit;
3591 }
Garmond Leung6b3f4182018-05-11 12:29:34 -07003592 param_hdr.param_id = AFE_PARAM_ID_USB_AUDIO_SVC_INTERVAL;
3593 param_hdr.param_size = sizeof(svc_int);
3594 svc_int.cfg_minor_version =
3595 AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG;
3596 svc_int.svc_interval = afe_config->usb_audio.service_interval;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303597
Garmond Leung6b3f4182018-05-11 12:29:34 -07003598 pr_debug("%s: AFE device param cmd sending SVC_INTERVAL %d\n",
3599 __func__, svc_int.svc_interval);
3600
3601 ret = q6afe_pack_and_set_param_in_band(port_id,
3602 q6audio_get_port_index(port_id),
3603 param_hdr, (u8 *) &svc_int);
3604
3605 if (ret) {
3606 pr_err("%s: AFE device param cmd svc_interval failed %d\n",
3607 __func__, ret);
3608 ret = -EINVAL;
3609 goto exit;
3610 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303611exit:
3612 return ret;
3613}
3614
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003615static int q6afe_send_dec_config(u16 port_id,
3616 union afe_port_config afe_config,
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003617 struct afe_dec_config *cfg,
3618 u32 format,
3619 u16 afe_in_channels, u16 afe_in_bit_width)
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003620{
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003621 struct afe_dec_media_fmt_t dec_media_fmt;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003622 struct avs_dec_depacketizer_id_param_t dec_depkt_id_param;
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003623 struct avs_dec_congestion_buffer_param_t dec_buffer_id_param;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003624 struct afe_enc_dec_imc_info_param_t imc_info_param;
3625 struct afe_port_media_type_t media_type;
3626 struct param_hdr_v3 param_hdr;
3627 int ret;
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003628 u32 dec_fmt;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003629
3630 memset(&dec_depkt_id_param, 0, sizeof(dec_depkt_id_param));
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003631 memset(&dec_media_fmt, 0, sizeof(dec_media_fmt));
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003632 memset(&imc_info_param, 0, sizeof(imc_info_param));
3633 memset(&media_type, 0, sizeof(media_type));
3634 memset(&param_hdr, 0, sizeof(param_hdr));
3635
3636 param_hdr.module_id = AFE_MODULE_ID_DECODER;
3637 param_hdr.instance_id = INSTANCE_ID_0;
3638
3639 pr_debug("%s: sending AFE_DECODER_PARAM_ID_DEPACKETIZER to DSP payload\n",
3640 __func__);
3641 param_hdr.param_id = AFE_DECODER_PARAM_ID_DEPACKETIZER_ID;
3642 param_hdr.param_size = sizeof(struct avs_dec_depacketizer_id_param_t);
3643 dec_depkt_id_param.dec_depacketizer_id =
Sharad Sangle82777e52018-06-20 19:06:08 +05303644 AFE_MODULE_ID_DEPACKETIZER_COP_V1;
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003645 if (cfg->format == ENC_CODEC_TYPE_LDAC)
3646 dec_depkt_id_param.dec_depacketizer_id =
3647 AFE_MODULE_ID_DEPACKETIZER_COP;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003648 ret = q6afe_pack_and_set_param_in_band(port_id,
3649 q6audio_get_port_index(port_id),
3650 param_hdr,
3651 (u8 *) &dec_depkt_id_param);
3652 if (ret) {
3653 pr_err("%s: AFE_DECODER_PARAM_ID_DEPACKETIZER for port 0x%x failed %d\n",
3654 __func__, port_id, ret);
3655 goto exit;
3656 }
3657
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003658 switch (cfg->format) {
3659 case ASM_MEDIA_FMT_SBC:
3660 case ASM_MEDIA_FMT_AAC_V2:
3661 case ASM_MEDIA_FMT_MP3:
3662 if (port_id == SLIMBUS_9_TX) {
3663 dec_buffer_id_param.max_nr_buffers = 200;
3664 dec_buffer_id_param.pre_buffer_size = 200;
3665 } else {
3666 dec_buffer_id_param.max_nr_buffers = 0;
3667 dec_buffer_id_param.pre_buffer_size = 0;
3668 }
3669 pr_debug("%s: sending AFE_DECODER_PARAM_ID_CONGESTION_BUFFER_SIZE to DSP payload\n",
3670 __func__);
3671 param_hdr.param_id =
3672 AFE_DECODER_PARAM_ID_CONGESTION_BUFFER_SIZE;
3673 param_hdr.param_size =
3674 sizeof(struct avs_dec_congestion_buffer_param_t);
3675 dec_buffer_id_param.version = 0;
3676 ret = q6afe_pack_and_set_param_in_band(port_id,
3677 q6audio_get_port_index(port_id),
3678 param_hdr,
3679 (u8 *) &dec_buffer_id_param);
3680 if (ret) {
3681 pr_err("%s: AFE_DECODER_PARAM_ID_CONGESTION_BUFFER_SIZE for port 0x%x failed %d\n",
3682 __func__, port_id, ret);
3683 goto exit;
3684 }
3685 break;
Chaithanya Krishna Bacharaju4a466532019-01-21 10:59:51 +05303686 case ASM_MEDIA_FMT_APTX_ADAPTIVE:
3687 if (!cfg->abr_dec_cfg.is_abr_enabled) {
3688 pr_debug("%s: sending aptx adaptive congestion buffer size to dsp\n",
3689 __func__);
3690 param_hdr.param_id =
3691 AFE_DECODER_PARAM_ID_CONGESTION_BUFFER_SIZE;
3692 param_hdr.param_size =
3693 sizeof(struct avs_dec_congestion_buffer_param_t);
3694 dec_buffer_id_param.version = 0;
3695 dec_buffer_id_param.max_nr_buffers = 226;
3696 dec_buffer_id_param.pre_buffer_size = 226;
3697 ret = q6afe_pack_and_set_param_in_band(port_id,
3698 q6audio_get_port_index(port_id),
3699 param_hdr,
3700 (u8 *) &dec_buffer_id_param);
3701 if (ret) {
3702 pr_err("%s: aptx adaptive congestion buffer size for port 0x%x failed %d\n",
3703 __func__, port_id, ret);
3704 goto exit;
3705 }
3706 break;
3707 }
3708 /* fall through for abr enabled case */
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003709 default:
3710 pr_debug("%s:sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload\n",
3711 __func__);
3712 param_hdr.param_id =
3713 AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION;
3714 param_hdr.param_size =
3715 sizeof(struct afe_enc_dec_imc_info_param_t);
3716 imc_info_param.imc_info = cfg->abr_dec_cfg.imc_info;
3717 ret = q6afe_pack_and_set_param_in_band(port_id,
3718 q6audio_get_port_index(port_id),
3719 param_hdr,
3720 (u8 *) &imc_info_param);
3721 if (ret) {
3722 pr_err("%s: AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION for port 0x%x failed %d\n",
3723 __func__, port_id, ret);
3724 goto exit;
3725 }
3726 break;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003727 }
3728
Chaithanya Krishna Bacharaju4a466532019-01-21 10:59:51 +05303729 pr_debug("%s: Send AFE_API_VERSION_PORT_MEDIA_TYPE to DSP\n", __func__);
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003730 param_hdr.module_id = AFE_MODULE_PORT;
3731 param_hdr.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
3732 param_hdr.param_size = sizeof(struct afe_port_media_type_t);
3733 media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003734 switch (cfg->format) {
3735 case ASM_MEDIA_FMT_AAC_V2:
3736 media_type.sample_rate =
3737 cfg->data.aac_config.sample_rate;
3738 break;
Florian Pfisterf4fd5f32018-11-05 15:32:13 +01003739 case ASM_MEDIA_FMT_SBC:
3740 media_type.sample_rate =
3741 cfg->data.sbc_config.sample_rate;
3742 break;
Chaithanya Krishna Bacharaju4a466532019-01-21 10:59:51 +05303743 case ASM_MEDIA_FMT_APTX_ADAPTIVE:
3744 if (!cfg->abr_dec_cfg.is_abr_enabled) {
3745 media_type.sample_rate =
3746 (cfg->data.aptx_ad_config.sample_rate == APTX_AD_44_1) ?
3747 AFE_PORT_SAMPLE_RATE_44_1K :
3748 AFE_PORT_SAMPLE_RATE_48K;
3749 break;
3750 }
3751 /* fall through for abr enabled case */
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003752 default:
3753 media_type.sample_rate =
3754 afe_config.slim_sch.sample_rate;
3755 }
3756 if (afe_in_bit_width)
3757 media_type.bit_width = afe_in_bit_width;
3758 else
3759 media_type.bit_width = afe_config.slim_sch.bit_width;
3760
3761 if (afe_in_channels)
3762 media_type.num_channels = afe_in_channels;
3763 else
3764 media_type.num_channels = afe_config.slim_sch.num_channels;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003765 media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
3766 media_type.reserved = 0;
3767
3768 ret = q6afe_pack_and_set_param_in_band(port_id,
3769 q6audio_get_port_index(port_id),
3770 param_hdr, (u8 *) &media_type);
3771 if (ret) {
3772 pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
3773 __func__, port_id, ret);
3774 goto exit;
3775 }
3776
Chaithanya Krishna Bacharaju4a466532019-01-21 10:59:51 +05303777 if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 &&
3778 format != ASM_MEDIA_FMT_APTX_ADAPTIVE) {
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003779 pr_debug("%s:Unsuppported dec format. Ignore AFE config %u\n",
3780 __func__, format);
3781 goto exit;
3782 }
Chaithanya Krishna Bacharaju4a466532019-01-21 10:59:51 +05303783
3784 if (format == ASM_MEDIA_FMT_APTX_ADAPTIVE &&
3785 cfg->abr_dec_cfg.is_abr_enabled) {
3786 pr_debug("%s: Ignore AFE config for abr case\n", __func__);
3787 goto exit;
3788 }
3789
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003790 pr_debug("%s: sending AFE_DECODER_PARAM_ID_DEC_MEDIA_FMT to DSP payload\n",
3791 __func__);
3792 param_hdr.module_id = AFE_MODULE_ID_DECODER;
3793 param_hdr.instance_id = INSTANCE_ID_0;
3794 param_hdr.param_id = AFE_DECODER_PARAM_ID_DEC_FMT_ID;
3795 param_hdr.param_size = sizeof(dec_fmt);
3796 dec_fmt = format;
3797 ret = q6afe_pack_and_set_param_in_band(port_id,
3798 q6audio_get_port_index(port_id),
3799 param_hdr, (u8 *) &dec_fmt);
3800 if (ret) {
3801 pr_err("%s: AFE_DECODER_PARAM_ID_DEC_MEDIA_FMT for port 0x%x failed %d\n",
3802 __func__, port_id, ret);
3803 goto exit;
3804 }
3805
3806 switch (cfg->format) {
3807 case ASM_MEDIA_FMT_AAC_V2:
Chaithanya Krishna Bacharaju4a466532019-01-21 10:59:51 +05303808 case ASM_MEDIA_FMT_APTX_ADAPTIVE:
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003809 param_hdr.param_size = sizeof(struct afe_dec_media_fmt_t);
3810
Chaithanya Krishna Bacharaju4a466532019-01-21 10:59:51 +05303811 pr_debug("%s:send AVS_DECODER_PARAM_ID DEC_MEDIA_FMT to DSP payload\n",
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003812 __func__);
3813 param_hdr.param_id = AVS_DECODER_PARAM_ID_DEC_MEDIA_FMT;
3814 dec_media_fmt.dec_media_config = cfg->data;
3815 ret = q6afe_pack_and_set_param_in_band(port_id,
3816 q6audio_get_port_index(port_id),
3817 param_hdr,
3818 (u8 *) &dec_media_fmt);
3819 if (ret) {
Chaithanya Krishna Bacharaju4a466532019-01-21 10:59:51 +05303820 pr_err("%s: AVS_DECODER_PARAM_ID DEC_MEDIA_FMT for port 0x%x failed %d\n",
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003821 __func__, port_id, ret);
3822 goto exit;
3823 }
3824 break;
3825 default:
3826 pr_debug("%s:No need to send DEC_MEDIA_FMT to DSP payload\n",
3827 __func__);
3828 }
3829
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003830exit:
3831 return ret;
3832}
3833
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303834static int q6afe_send_enc_config(u16 port_id,
3835 union afe_enc_config_data *cfg, u32 format,
3836 union afe_port_config afe_config,
Preetam Singh Ranawatf746a872017-10-20 18:13:14 +05303837 u16 afe_in_channels, u16 afe_in_bit_width,
Manisha Agarwald99fac02018-11-04 15:46:02 +05303838 u32 scrambler_mode, u32 mono_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303839{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003840 u32 enc_fmt;
3841 struct afe_enc_cfg_blk_param_t enc_blk_param;
3842 struct afe_param_id_aptx_sync_mode sync_mode_param;
Sharad Sangle82777e52018-06-20 19:06:08 +05303843 struct afe_id_aptx_adaptive_enc_init aptx_adaptive_enc_init;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003844 struct avs_enc_packetizer_id_param_t enc_pkt_id_param;
3845 struct avs_enc_set_scrambler_param_t enc_set_scrambler_param;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003846 struct afe_enc_level_to_bitrate_map_param_t map_param;
3847 struct afe_enc_dec_imc_info_param_t imc_info_param;
Aniket Kumar Latabe837352018-06-20 14:57:05 -07003848 struct asm_aac_frame_size_control_t frame_ctl_param;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003849 struct afe_port_media_type_t media_type;
Manisha Agarwald99fac02018-11-04 15:46:02 +05303850 struct aptx_channel_mode_param_t channel_mode_param;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003851 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303852 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303853
3854 pr_debug("%s:update DSP for enc format = %d\n", __func__, format);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003855
3856 memset(&enc_blk_param, 0, sizeof(enc_blk_param));
3857 memset(&sync_mode_param, 0, sizeof(sync_mode_param));
Sharad Sangle82777e52018-06-20 19:06:08 +05303858 memset(&aptx_adaptive_enc_init, 0, sizeof(aptx_adaptive_enc_init));
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003859 memset(&enc_pkt_id_param, 0, sizeof(enc_pkt_id_param));
3860 memset(&enc_set_scrambler_param, 0, sizeof(enc_set_scrambler_param));
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003861 memset(&map_param, 0, sizeof(map_param));
3862 memset(&imc_info_param, 0, sizeof(imc_info_param));
Aniket Kumar Latabe837352018-06-20 14:57:05 -07003863 memset(&frame_ctl_param, 0, sizeof(frame_ctl_param));
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003864 memset(&media_type, 0, sizeof(media_type));
3865 memset(&param_hdr, 0, sizeof(param_hdr));
3866
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303867 if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 &&
Sharad Sangle82777e52018-06-20 19:06:08 +05303868 format != ASM_MEDIA_FMT_APTX && format != ASM_MEDIA_FMT_APTX_HD &&
3869 format != ASM_MEDIA_FMT_CELT && format != ASM_MEDIA_FMT_LDAC &&
3870 format != ASM_MEDIA_FMT_APTX_ADAPTIVE) {
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003871 pr_err("%s:Unsuppported enc format. Ignore AFE config\n",
3872 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303873 return 0;
3874 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303875
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003876 param_hdr.module_id = AFE_MODULE_ID_ENCODER;
3877 param_hdr.instance_id = INSTANCE_ID_0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303878
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003879 param_hdr.param_id = AFE_ENCODER_PARAM_ID_ENC_FMT_ID;
3880 param_hdr.param_size = sizeof(enc_fmt);
3881 enc_fmt = format;
3882 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENC_FMT_ID payload\n",
3883 __func__);
3884 ret = q6afe_pack_and_set_param_in_band(port_id,
3885 q6audio_get_port_index(port_id),
3886 param_hdr, (u8 *) &enc_fmt);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303887 if (ret) {
3888 pr_err("%s:unable to send AFE_ENCODER_PARAM_ID_ENC_FMT_ID",
3889 __func__);
3890 goto exit;
3891 }
3892
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003893 if (format == ASM_MEDIA_FMT_LDAC) {
3894 param_hdr.param_size = sizeof(struct afe_enc_cfg_blk_param_t)
3895 - sizeof(struct afe_abr_enc_cfg_t);
3896 enc_blk_param.enc_cfg_blk_size =
3897 sizeof(union afe_enc_config_data)
3898 - sizeof(struct afe_abr_enc_cfg_t);
Aniket Kumar Latabe837352018-06-20 14:57:05 -07003899 } else if (format == ASM_MEDIA_FMT_AAC_V2) {
3900 param_hdr.param_size = sizeof(enc_blk_param)
3901 - sizeof(struct asm_aac_frame_size_control_t);
3902 enc_blk_param.enc_cfg_blk_size =
3903 sizeof(enc_blk_param.enc_blk_config)
3904 - sizeof(struct asm_aac_frame_size_control_t);
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08003905 } else {
3906 param_hdr.param_size = sizeof(struct afe_enc_cfg_blk_param_t);
3907 enc_blk_param.enc_cfg_blk_size =
3908 sizeof(union afe_enc_config_data);
3909 }
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02003910 pr_debug("%s:send AFE_ENCODER_PARAM_ID_ENC_CFG_BLK to DSP payload\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003911 __func__);
3912 param_hdr.param_id = AFE_ENCODER_PARAM_ID_ENC_CFG_BLK;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003913 enc_blk_param.enc_blk_config = *cfg;
3914 ret = q6afe_pack_and_set_param_in_band(port_id,
3915 q6audio_get_port_index(port_id),
3916 param_hdr,
3917 (u8 *) &enc_blk_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303918 if (ret) {
3919 pr_err("%s: AFE_ENCODER_PARAM_ID_ENC_CFG_BLK for port 0x%x failed %d\n",
3920 __func__, port_id, ret);
3921 goto exit;
3922 }
3923
Aniket Kumar Latabe837352018-06-20 14:57:05 -07003924 if (format == ASM_MEDIA_FMT_AAC_V2) {
3925 uint32_t frame_size_ctl_value = enc_blk_param.enc_blk_config.
3926 aac_config.frame_ctl.ctl_value;
3927 if (frame_size_ctl_value > 0) {
3928 param_hdr.param_id =
3929 AFE_PARAM_ID_AAC_FRM_SIZE_CONTROL;
3930 param_hdr.param_size = sizeof(frame_ctl_param);
3931 frame_ctl_param.ctl_type = enc_blk_param.
3932 enc_blk_config.aac_config.frame_ctl.ctl_type;
3933 frame_ctl_param.ctl_value = frame_size_ctl_value;
3934 pr_debug("%s: send AFE_PARAM_ID_AAC_FRM_SIZE_CONTROL\n",
3935 __func__);
3936 ret = q6afe_pack_and_set_param_in_band(port_id,
3937 q6audio_get_port_index(port_id),
3938 param_hdr,
3939 (u8 *) &frame_ctl_param);
3940 if (ret) {
3941 pr_err("%s: AAC_FRM_SIZE_CONTROL failed %d\n",
3942 __func__, ret);
3943 goto exit;
3944 }
3945 }
3946 }
3947
Preetam Singh Ranawat899b78b2017-09-07 12:36:06 -07003948 if (format == ASM_MEDIA_FMT_APTX) {
Preetam Singh Ranawat899b78b2017-09-07 12:36:06 -07003949 pr_debug("%s: sending AFE_PARAM_ID_APTX_SYNC_MODE to DSP",
3950 __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003951 param_hdr.param_id = AFE_PARAM_ID_APTX_SYNC_MODE;
3952 param_hdr.param_size =
3953 sizeof(struct afe_param_id_aptx_sync_mode);
3954 sync_mode_param.sync_mode =
3955 enc_blk_param.enc_blk_config.aptx_config.
Preetam Singh Ranawat899b78b2017-09-07 12:36:06 -07003956 aptx_v2_cfg.sync_mode;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003957 ret = q6afe_pack_and_set_param_in_band(port_id,
3958 q6audio_get_port_index(port_id),
3959 param_hdr,
3960 (u8 *) &sync_mode_param);
Preetam Singh Ranawat899b78b2017-09-07 12:36:06 -07003961 if (ret) {
3962 pr_err("%s: AFE_PARAM_ID_APTX_SYNC_MODE for port 0x%x failed %d\n",
3963 __func__, port_id, ret);
3964 goto exit;
3965 }
3966 }
Sharad Sangle82777e52018-06-20 19:06:08 +05303967 if (format == ASM_MEDIA_FMT_APTX_ADAPTIVE) {
3968 pr_debug("%s: sending AFE_ID_APTX_ADAPTIVE_ENC_INIT to DSP\n",
3969 __func__);
3970 param_hdr.param_id = AFE_ID_APTX_ADAPTIVE_ENC_INIT;
3971 param_hdr.param_size =
3972 sizeof(struct afe_id_aptx_adaptive_enc_init);
3973 aptx_adaptive_enc_init =
3974 enc_blk_param.enc_blk_config.aptx_ad_config.
3975 aptx_ad_cfg;
3976 ret = q6afe_pack_and_set_param_in_band(port_id,
3977 q6audio_get_port_index(port_id),
3978 param_hdr,
3979 (u8 *) &aptx_adaptive_enc_init);
3980 if (ret) {
3981 pr_err("%s: AFE_ID_APTX_ADAPTIVE_ENC_INIT for port 0x%x failed %d\n",
3982 __func__, port_id, ret);
3983 goto exit;
3984 }
3985 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08003986 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_PACKETIZER to DSP\n",
3987 __func__);
3988 param_hdr.param_id = AFE_ENCODER_PARAM_ID_PACKETIZER_ID;
3989 param_hdr.param_size = sizeof(struct avs_enc_packetizer_id_param_t);
3990 enc_pkt_id_param.enc_packetizer_id = AFE_MODULE_ID_PACKETIZER_COP;
3991 ret = q6afe_pack_and_set_param_in_band(port_id,
3992 q6audio_get_port_index(port_id),
3993 param_hdr,
3994 (u8 *) &enc_pkt_id_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303995 if (ret) {
3996 pr_err("%s: AFE_ENCODER_PARAM_ID_PACKETIZER for port 0x%x failed %d\n",
3997 __func__, port_id, ret);
3998 goto exit;
3999 }
4000
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004001 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING mode= %d to DSP payload\n",
4002 __func__, scrambler_mode);
4003 param_hdr.param_id = AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING;
4004 param_hdr.param_size = sizeof(struct avs_enc_set_scrambler_param_t);
4005 enc_set_scrambler_param.enable_scrambler = scrambler_mode;
4006 ret = q6afe_pack_and_set_param_in_band(port_id,
4007 q6audio_get_port_index(port_id),
4008 param_hdr,
4009 (u8 *) &enc_set_scrambler_param);
Preetam Singh Ranawatf746a872017-10-20 18:13:14 +05304010 if (ret) {
4011 pr_err("%s: AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING for port 0x%x failed %d\n",
4012 __func__, port_id, ret);
4013 goto exit;
4014 }
4015
Manisha Agarwald99fac02018-11-04 15:46:02 +05304016 if (format == ASM_MEDIA_FMT_APTX) {
4017 pr_debug("%s:sending CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO mode= %d to DSP payload\n",
4018 __func__, mono_mode);
4019 param_hdr.param_id = CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO;
4020 param_hdr.param_size = sizeof(channel_mode_param);
4021 channel_mode_param.channel_mode = mono_mode;
4022 ret = q6afe_pack_and_set_param_in_band(port_id,
4023 q6audio_get_port_index(port_id),
4024 param_hdr,
4025 (u8 *) &channel_mode_param);
4026
4027 if (ret) {
4028 pr_err("%s: CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO for port 0x%x failed %d\n",
4029 __func__, port_id, ret);
4030 }
4031 }
4032
Aniket Kumar Lata9dce5042018-08-16 16:23:46 -07004033 if ((format == ASM_MEDIA_FMT_LDAC &&
4034 cfg->ldac_config.abr_config.is_abr_enabled) ||
4035 format == ASM_MEDIA_FMT_APTX_ADAPTIVE) {
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004036 pr_debug("%s:sending AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP to DSP payload",
4037 __func__);
4038 param_hdr.param_id = AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP;
4039 param_hdr.param_size =
4040 sizeof(struct afe_enc_level_to_bitrate_map_param_t);
4041 map_param.mapping_table =
4042 cfg->ldac_config.abr_config.mapping_info;
4043 ret = q6afe_pack_and_set_param_in_band(port_id,
4044 q6audio_get_port_index(port_id),
4045 param_hdr,
4046 (u8 *) &map_param);
4047 if (ret) {
4048 pr_err("%s: AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP for port 0x%x failed %d\n",
4049 __func__, port_id, ret);
4050 goto exit;
4051 }
4052
4053 pr_debug("%s: sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload",
4054 __func__);
4055 param_hdr.param_id =
4056 AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION;
4057 param_hdr.param_size =
4058 sizeof(struct afe_enc_dec_imc_info_param_t);
Sharad Sangle82777e52018-06-20 19:06:08 +05304059 if (format == ASM_MEDIA_FMT_APTX_ADAPTIVE)
4060 imc_info_param.imc_info =
4061 cfg->aptx_ad_config.abr_cfg.imc_info;
4062 else
4063 imc_info_param.imc_info =
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004064 cfg->ldac_config.abr_config.imc_info;
4065 ret = q6afe_pack_and_set_param_in_band(port_id,
4066 q6audio_get_port_index(port_id),
4067 param_hdr,
4068 (u8 *) &imc_info_param);
4069 if (ret) {
4070 pr_err("%s: AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION for port 0x%x failed %d\n",
4071 __func__, port_id, ret);
4072 goto exit;
4073 }
4074 }
4075
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304076 pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP", __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004077 param_hdr.module_id = AFE_MODULE_PORT;
4078 param_hdr.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
4079 param_hdr.param_size = sizeof(struct afe_port_media_type_t);
4080 media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004081 if (format == ASM_MEDIA_FMT_LDAC)
4082 media_type.sample_rate =
4083 cfg->ldac_config.custom_config.sample_rate;
Aniket Kumar Lata1c9ae8f2018-10-10 18:22:04 -07004084 else if (format == ASM_MEDIA_FMT_APTX_ADAPTIVE)
4085 media_type.sample_rate =
4086 cfg->aptx_ad_config.custom_cfg.sample_rate;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004087 else
4088 media_type.sample_rate =
4089 afe_config.slim_sch.sample_rate;
4090
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304091 if (afe_in_bit_width)
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004092 media_type.bit_width = afe_in_bit_width;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304093 else
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004094 media_type.bit_width = afe_config.slim_sch.bit_width;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304095
4096 if (afe_in_channels)
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004097 media_type.num_channels = afe_in_channels;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304098 else
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004099 media_type.num_channels = afe_config.slim_sch.num_channels;
4100 media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
4101 media_type.reserved = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304102
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004103 ret = q6afe_pack_and_set_param_in_band(port_id,
4104 q6audio_get_port_index(port_id),
4105 param_hdr, (u8 *) &media_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304106 if (ret) {
4107 pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
4108 __func__, port_id, ret);
4109 goto exit;
4110 }
4111
4112exit:
4113 return ret;
4114}
4115
Manisha Agarwald99fac02018-11-04 15:46:02 +05304116int afe_set_tws_channel_mode(u16 port_id, u32 channel_mode)
4117{
4118 struct aptx_channel_mode_param_t channel_mode_param;
4119 struct param_hdr_v3 param_info;
4120 int ret = 0;
4121
4122 memset(&param_info, 0, sizeof(param_info));
4123 memset(&channel_mode_param, 0, sizeof(channel_mode_param));
4124
4125 param_info.module_id = AFE_MODULE_ID_ENCODER;
4126 param_info.instance_id = INSTANCE_ID_0;
4127 param_info.param_id = CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO;
4128 param_info.param_size = sizeof(channel_mode_param);
4129
4130 channel_mode_param.channel_mode = channel_mode;
4131
4132 ret = q6afe_pack_and_set_param_in_band(port_id,
4133 q6audio_get_port_index(port_id),
4134 param_info,
4135 (u8 *) &channel_mode_param);
4136 if (ret)
4137 pr_err("%s: AFE set channel mode cfg for port 0x%x failed %d\n",
4138 __func__, port_id, ret);
4139
4140 return ret;
4141}
4142EXPORT_SYMBOL(afe_set_tws_channel_mode);
4143
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304144static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
4145 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004146 union afe_enc_config_data *enc_cfg,
Manisha Agarwald99fac02018-11-04 15:46:02 +05304147 u32 codec_format, u32 scrambler_mode, u32 mono_mode,
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004148 struct afe_dec_config *dec_cfg)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304149{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004150 union afe_port_config port_cfg;
4151 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304152 int ret = 0;
4153 int cfg_type;
4154 int index = 0;
4155 enum afe_mad_type mad_type;
4156 uint16_t port_index;
4157
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004158 memset(&param_hdr, 0, sizeof(param_hdr));
4159 memset(&port_cfg, 0, sizeof(port_cfg));
4160
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304161 if (!afe_config) {
4162 pr_err("%s: Error, no configuration data\n", __func__);
4163 ret = -EINVAL;
4164 return ret;
4165 }
4166
4167 if ((port_id == RT_PROXY_DAI_001_RX) ||
4168 (port_id == RT_PROXY_DAI_002_TX)) {
4169 pr_debug("%s: before incrementing pcm_afe_instance %d port_id 0x%x\n",
4170 __func__,
4171 pcm_afe_instance[port_id & 0x1], port_id);
4172 port_id = VIRTUAL_ID_TO_PORTID(port_id);
4173 pcm_afe_instance[port_id & 0x1]++;
4174 return 0;
4175 }
4176 if ((port_id == RT_PROXY_DAI_002_RX) ||
4177 (port_id == RT_PROXY_DAI_001_TX)) {
4178 pr_debug("%s: before incrementing proxy_afe_instance %d port_id 0x%x\n",
4179 __func__,
4180 proxy_afe_instance[port_id & 0x1], port_id);
4181
4182 if (!afe_close_done[port_id & 0x1]) {
4183 /*close pcm dai corresponding to the proxy dai*/
4184 afe_close(port_id - 0x10);
4185 pcm_afe_instance[port_id & 0x1]++;
4186 pr_debug("%s: reconfigure afe port again\n", __func__);
4187 }
4188 proxy_afe_instance[port_id & 0x1]++;
4189 afe_close_done[port_id & 0x1] = false;
4190 port_id = VIRTUAL_ID_TO_PORTID(port_id);
4191 }
4192
4193 pr_debug("%s: port id: 0x%x\n", __func__, port_id);
4194
4195 index = q6audio_get_port_index(port_id);
4196 if (index < 0 || index >= AFE_MAX_PORTS) {
4197 pr_err("%s: AFE port index[%d] invalid!\n",
4198 __func__, index);
4199 return -EINVAL;
4200 }
4201 ret = q6audio_validate_port(port_id);
4202 if (ret < 0) {
4203 pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
4204 return -EINVAL;
4205 }
4206
4207 ret = afe_q6_interface_prepare();
4208 if (ret != 0) {
4209 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4210 return ret;
4211 }
4212
4213 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
4214 this_afe.afe_sample_rates[index] = rate;
4215
4216 if (this_afe.rt_cb)
4217 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
4218 }
4219
4220 mutex_lock(&this_afe.afe_cmd_lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304221 port_index = afe_get_port_index(port_id);
Mangesh Kunchamwar4e1e7182018-04-26 17:58:58 +05304222
4223 if (q6core_get_avcs_api_version_per_service(
4224 APRV2_IDS_SERVICE_ID_ADSP_AFE_V) >= AFE_API_VERSION_V4) {
4225 /* send VAD configuration if is enabled */
4226 if (this_afe.vad_cfg[port_index].is_enable) {
4227 ret = afe_send_port_vad_cfg_params(port_id);
Mangesh Kunchamwar2d84e4a2018-07-10 17:50:35 +05304228 if (ret) {
Mangesh Kunchamwar4e1e7182018-04-26 17:58:58 +05304229 pr_err("%s: afe send VAD config failed %d\n",
4230 __func__, ret);
4231 goto fail_cmd;
Mangesh Kunchamwar2d84e4a2018-07-10 17:50:35 +05304232 }
Mangesh Kunchamwar4e1e7182018-04-26 17:58:58 +05304233 }
4234 }
4235
4236 /* Also send the topology id here: */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304237 if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
4238 /* One time call: only for first time */
4239 afe_send_custom_topology();
4240 afe_send_port_topology_id(port_id);
4241 afe_send_cal(port_id);
4242 afe_send_hw_delay(port_id, rate);
4243 }
4244
4245 /* Start SW MAD module */
4246 mad_type = afe_port_get_mad_type(port_id);
4247 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
4248 mad_type);
4249 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
4250 if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
4251 !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
4252 pr_err("%s: AFE isn't configured yet for\n"
4253 "HW MAD try Again\n", __func__);
4254 ret = -EAGAIN;
4255 goto fail_cmd;
4256 }
4257 ret = afe_turn_onoff_hw_mad(mad_type, true);
4258 if (ret) {
4259 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
4260 __func__, ret);
4261 goto fail_cmd;
4262 }
4263 }
4264
4265 if ((this_afe.aanc_info.aanc_active) &&
4266 (this_afe.aanc_info.aanc_tx_port == port_id)) {
4267 this_afe.aanc_info.aanc_tx_port_sample_rate = rate;
4268 port_index =
4269 afe_get_port_index(this_afe.aanc_info.aanc_rx_port);
4270 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
4271 this_afe.aanc_info.aanc_rx_port_sample_rate =
4272 this_afe.afe_sample_rates[port_index];
4273 } else {
4274 pr_err("%s: Invalid port index %d\n",
4275 __func__, port_index);
4276 ret = -EINVAL;
4277 goto fail_cmd;
4278 }
4279 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
4280 this_afe.aanc_info.aanc_rx_port);
4281 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
4282 }
4283
4284 if ((port_id == AFE_PORT_ID_USB_RX) ||
4285 (port_id == AFE_PORT_ID_USB_TX)) {
4286 ret = afe_port_send_usb_dev_param(port_id, afe_config);
4287 if (ret) {
4288 pr_err("%s: AFE device param for port 0x%x failed %d\n",
4289 __func__, port_id, ret);
4290 ret = -EINVAL;
4291 goto fail_cmd;
4292 }
4293 }
4294
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304295 switch (port_id) {
4296 case AFE_PORT_ID_PRIMARY_PCM_RX:
4297 case AFE_PORT_ID_PRIMARY_PCM_TX:
4298 case AFE_PORT_ID_SECONDARY_PCM_RX:
4299 case AFE_PORT_ID_SECONDARY_PCM_TX:
4300 case AFE_PORT_ID_TERTIARY_PCM_RX:
4301 case AFE_PORT_ID_TERTIARY_PCM_TX:
4302 case AFE_PORT_ID_QUATERNARY_PCM_RX:
4303 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304304 case AFE_PORT_ID_QUINARY_PCM_RX:
4305 case AFE_PORT_ID_QUINARY_PCM_TX:
Dieter Lueckingfa7687b2018-09-28 14:21:44 +02004306 case AFE_PORT_ID_SENARY_PCM_RX:
4307 case AFE_PORT_ID_SENARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304308 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
4309 break;
4310 case PRIMARY_I2S_RX:
4311 case PRIMARY_I2S_TX:
4312 case SECONDARY_I2S_RX:
4313 case SECONDARY_I2S_TX:
4314 case MI2S_RX:
4315 case MI2S_TX:
4316 case AFE_PORT_ID_PRIMARY_MI2S_RX:
4317 case AFE_PORT_ID_PRIMARY_MI2S_TX:
4318 case AFE_PORT_ID_SECONDARY_MI2S_RX:
4319 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
4320 case AFE_PORT_ID_SECONDARY_MI2S_TX:
4321 case AFE_PORT_ID_TERTIARY_MI2S_RX:
4322 case AFE_PORT_ID_TERTIARY_MI2S_TX:
4323 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
4324 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
4325 case AFE_PORT_ID_QUINARY_MI2S_RX:
4326 case AFE_PORT_ID_QUINARY_MI2S_TX:
4327 case AFE_PORT_ID_SENARY_MI2S_TX:
4328 case AFE_PORT_ID_INT0_MI2S_RX:
4329 case AFE_PORT_ID_INT0_MI2S_TX:
4330 case AFE_PORT_ID_INT1_MI2S_RX:
4331 case AFE_PORT_ID_INT1_MI2S_TX:
4332 case AFE_PORT_ID_INT2_MI2S_RX:
4333 case AFE_PORT_ID_INT2_MI2S_TX:
4334 case AFE_PORT_ID_INT3_MI2S_RX:
4335 case AFE_PORT_ID_INT3_MI2S_TX:
4336 case AFE_PORT_ID_INT4_MI2S_RX:
4337 case AFE_PORT_ID_INT4_MI2S_TX:
4338 case AFE_PORT_ID_INT5_MI2S_RX:
4339 case AFE_PORT_ID_INT5_MI2S_TX:
4340 case AFE_PORT_ID_INT6_MI2S_RX:
4341 case AFE_PORT_ID_INT6_MI2S_TX:
4342 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
4343 break;
4344 case HDMI_RX:
4345 case DISPLAY_PORT_RX:
4346 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
4347 break;
4348 case VOICE_PLAYBACK_TX:
4349 case VOICE2_PLAYBACK_TX:
4350 case VOICE_RECORD_RX:
4351 case VOICE_RECORD_TX:
4352 cfg_type = AFE_PARAM_ID_PSEUDO_PORT_CONFIG;
4353 break;
4354 case SLIMBUS_0_RX:
4355 case SLIMBUS_0_TX:
4356 case SLIMBUS_1_RX:
4357 case SLIMBUS_1_TX:
4358 case SLIMBUS_2_RX:
4359 case SLIMBUS_2_TX:
4360 case SLIMBUS_3_RX:
4361 case SLIMBUS_3_TX:
4362 case SLIMBUS_4_RX:
4363 case SLIMBUS_4_TX:
4364 case SLIMBUS_5_RX:
4365 case SLIMBUS_5_TX:
4366 case SLIMBUS_6_RX:
4367 case SLIMBUS_6_TX:
4368 case SLIMBUS_7_RX:
4369 case SLIMBUS_7_TX:
4370 case SLIMBUS_8_RX:
4371 case SLIMBUS_8_TX:
Surendar Karkab0dd21f2018-09-28 18:53:50 +05304372 case SLIMBUS_9_RX:
4373 case SLIMBUS_9_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304374 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
4375 break;
4376 case AFE_PORT_ID_USB_RX:
4377 case AFE_PORT_ID_USB_TX:
4378 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
4379 break;
4380 case RT_PROXY_PORT_001_RX:
4381 case RT_PROXY_PORT_001_TX:
4382 cfg_type = AFE_PARAM_ID_RT_PROXY_CONFIG;
4383 break;
4384 case INT_BT_SCO_RX:
4385 case INT_BT_A2DP_RX:
4386 case INT_BT_SCO_TX:
4387 case INT_FM_RX:
4388 case INT_FM_TX:
4389 cfg_type = AFE_PARAM_ID_INTERNAL_BT_FM_CONFIG;
4390 break;
Mangesh Kunchamwar8c706ab2018-04-04 17:48:46 +05304391 case AFE_PORT_ID_WSA_CODEC_DMA_RX_0:
4392 case AFE_PORT_ID_WSA_CODEC_DMA_TX_0:
4393 case AFE_PORT_ID_WSA_CODEC_DMA_RX_1:
4394 case AFE_PORT_ID_WSA_CODEC_DMA_TX_1:
4395 case AFE_PORT_ID_WSA_CODEC_DMA_TX_2:
4396 case AFE_PORT_ID_VA_CODEC_DMA_TX_0:
4397 case AFE_PORT_ID_VA_CODEC_DMA_TX_1:
Xiaoyu Ye8341eef2019-01-03 14:57:47 -08004398 case AFE_PORT_ID_VA_CODEC_DMA_TX_2:
Aditya Bavanari348a4a62018-05-16 21:48:45 +05304399 case AFE_PORT_ID_RX_CODEC_DMA_RX_0:
4400 case AFE_PORT_ID_TX_CODEC_DMA_TX_0:
4401 case AFE_PORT_ID_RX_CODEC_DMA_RX_1:
4402 case AFE_PORT_ID_TX_CODEC_DMA_TX_1:
4403 case AFE_PORT_ID_RX_CODEC_DMA_RX_2:
4404 case AFE_PORT_ID_TX_CODEC_DMA_TX_2:
4405 case AFE_PORT_ID_RX_CODEC_DMA_RX_3:
4406 case AFE_PORT_ID_TX_CODEC_DMA_TX_3:
4407 case AFE_PORT_ID_RX_CODEC_DMA_RX_4:
4408 case AFE_PORT_ID_TX_CODEC_DMA_TX_4:
4409 case AFE_PORT_ID_RX_CODEC_DMA_RX_5:
4410 case AFE_PORT_ID_TX_CODEC_DMA_TX_5:
4411 case AFE_PORT_ID_RX_CODEC_DMA_RX_6:
4412 case AFE_PORT_ID_RX_CODEC_DMA_RX_7:
Mangesh Kunchamwar8c706ab2018-04-04 17:48:46 +05304413 cfg_type = AFE_PARAM_ID_CODEC_DMA_CONFIG;
4414 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304415 default:
4416 pr_err("%s: Invalid port id 0x%x\n", __func__, port_id);
4417 ret = -EINVAL;
4418 goto fail_cmd;
4419 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304420
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004421 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
4422 param_hdr.instance_id = INSTANCE_ID_0;
4423 param_hdr.param_id = cfg_type;
4424 param_hdr.param_size = sizeof(union afe_port_config);
4425
4426 port_cfg = *afe_config;
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004427 if (((enc_cfg != NULL) || (dec_cfg != NULL)) &&
4428 (codec_format != ASM_MEDIA_FMT_NONE) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304429 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004430 port_cfg.slim_sch.data_format =
4431 AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304432 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004433 ret = q6afe_pack_and_set_param_in_band(port_id,
4434 q6audio_get_port_index(port_id),
4435 param_hdr, (u8 *) &port_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304436 if (ret) {
4437 pr_err("%s: AFE enable for port 0x%x failed %d\n",
4438 __func__, port_id, ret);
4439 goto fail_cmd;
4440 }
4441
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004442 if ((codec_format != ASM_MEDIA_FMT_NONE) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304443 (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004444 if (enc_cfg != NULL) {
4445 pr_debug("%s: Found AFE encoder support for SLIMBUS format = %d\n",
4446 __func__, codec_format);
4447 ret = q6afe_send_enc_config(port_id, enc_cfg,
4448 codec_format, *afe_config,
4449 afe_in_channels,
4450 afe_in_bit_width,
Manisha Agarwald99fac02018-11-04 15:46:02 +05304451 scrambler_mode, mono_mode);
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004452 if (ret) {
4453 pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
4454 __func__, port_id, ret);
4455 goto fail_cmd;
4456 }
4457 }
4458 if (dec_cfg != NULL) {
4459 pr_debug("%s: Found AFE decoder support for SLIMBUS format = %d\n",
4460 __func__, codec_format);
4461 ret = q6afe_send_dec_config(port_id, *afe_config,
Florian Pfisterf1b8d5b2018-09-26 15:45:18 +02004462 dec_cfg, codec_format,
4463 afe_in_channels,
4464 afe_in_bit_width);
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004465 if (ret) {
4466 pr_err("%s: AFE decoder config for port 0x%x failed %d\n",
4467 __func__, port_id, ret);
4468 goto fail_cmd;
4469 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304470 }
4471 }
4472
4473 port_index = afe_get_port_index(port_id);
4474 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
4475 /*
4476 * If afe_port_start() for tx port called before
4477 * rx port, then aanc rx sample rate is zero. So,
4478 * AANC state machine in AFE will not get triggered.
4479 * Make sure to check whether aanc is active during
4480 * afe_port_start() for rx port and if aanc rx
4481 * sample rate is zero, call afe_aanc_start to configure
4482 * aanc with valid sample rates.
4483 */
4484 if (this_afe.aanc_info.aanc_active &&
4485 !this_afe.aanc_info.aanc_rx_port_sample_rate) {
4486 this_afe.aanc_info.aanc_rx_port_sample_rate =
4487 this_afe.afe_sample_rates[port_index];
4488 ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
4489 this_afe.aanc_info.aanc_rx_port);
4490 pr_debug("%s: afe_aanc_start ret %d\n", __func__, ret);
4491 }
4492 } else {
4493 pr_err("%s: Invalid port index %d\n", __func__, port_index);
4494 ret = -EINVAL;
4495 goto fail_cmd;
4496 }
4497 ret = afe_send_cmd_port_start(port_id);
4498
4499fail_cmd:
4500 mutex_unlock(&this_afe.afe_cmd_lock);
4501 return ret;
4502}
4503
4504/**
4505 * afe_port_start - to configure AFE session with
4506 * specified port configuration
4507 *
4508 * @port_id: AFE port id number
4509 * @afe_config: port configutation
4510 * @rate: sampling rate of port
4511 *
4512 * Returns 0 on success or error value on port start failure.
4513 */
4514int afe_port_start(u16 port_id, union afe_port_config *afe_config,
4515 u32 rate)
4516{
4517 return __afe_port_start(port_id, afe_config, rate,
Manisha Agarwald99fac02018-11-04 15:46:02 +05304518 0, 0, NULL, ASM_MEDIA_FMT_NONE, 0, 0, NULL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304519}
4520EXPORT_SYMBOL(afe_port_start);
4521
4522/**
4523 * afe_port_start_v2 - to configure AFE session with
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004524 * specified port configuration and encoder /decoder params
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304525 *
4526 * @port_id: AFE port id number
4527 * @afe_config: port configutation
4528 * @rate: sampling rate of port
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004529 * @enc_cfg: AFE enc configuration information to setup encoder
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304530 * @afe_in_channels: AFE input channel configuration, this needs
4531 * update only if input channel is differ from AFE output
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004532 * @dec_cfg: AFE dec configuration information to set up decoder
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304533 *
4534 * Returns 0 on success or error value on port start failure.
4535 */
4536int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
4537 u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004538 struct afe_enc_config *enc_cfg,
4539 struct afe_dec_config *dec_cfg)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304540{
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004541 int ret = 0;
4542
4543 if (enc_cfg != NULL)
4544 ret = __afe_port_start(port_id, afe_config, rate,
4545 afe_in_channels, afe_in_bit_width,
4546 &enc_cfg->data, enc_cfg->format,
Manisha Agarwald99fac02018-11-04 15:46:02 +05304547 enc_cfg->scrambler_mode,
4548 enc_cfg->mono_mode, dec_cfg);
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004549 else if (dec_cfg != NULL)
4550 ret = __afe_port_start(port_id, afe_config, rate,
4551 afe_in_channels, afe_in_bit_width,
Manisha Agarwald99fac02018-11-04 15:46:02 +05304552 NULL, dec_cfg->format, 0, 0, dec_cfg);
Aniket Kumar Latac0c31472018-02-22 14:46:09 -08004553
4554 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304555}
4556EXPORT_SYMBOL(afe_port_start_v2);
4557
4558int afe_get_port_index(u16 port_id)
4559{
4560 switch (port_id) {
4561 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
4562 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
4563 case AFE_PORT_ID_PRIMARY_PCM_RX:
4564 return IDX_AFE_PORT_ID_PRIMARY_PCM_RX;
4565 case AFE_PORT_ID_PRIMARY_PCM_TX:
4566 return IDX_AFE_PORT_ID_PRIMARY_PCM_TX;
4567 case AFE_PORT_ID_SECONDARY_PCM_RX:
4568 return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
4569 case AFE_PORT_ID_SECONDARY_PCM_TX:
4570 return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
4571 case AFE_PORT_ID_TERTIARY_PCM_RX:
4572 return IDX_AFE_PORT_ID_TERTIARY_PCM_RX;
4573 case AFE_PORT_ID_TERTIARY_PCM_TX:
4574 return IDX_AFE_PORT_ID_TERTIARY_PCM_TX;
4575 case AFE_PORT_ID_QUATERNARY_PCM_RX:
4576 return IDX_AFE_PORT_ID_QUATERNARY_PCM_RX;
4577 case AFE_PORT_ID_QUATERNARY_PCM_TX:
4578 return IDX_AFE_PORT_ID_QUATERNARY_PCM_TX;
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304579 case AFE_PORT_ID_QUINARY_PCM_RX:
4580 return IDX_AFE_PORT_ID_QUINARY_PCM_RX;
4581 case AFE_PORT_ID_QUINARY_PCM_TX:
4582 return IDX_AFE_PORT_ID_QUINARY_PCM_TX;
Dieter Lueckingfa7687b2018-09-28 14:21:44 +02004583 case AFE_PORT_ID_SENARY_PCM_RX:
4584 return IDX_AFE_PORT_ID_SENARY_PCM_RX;
4585 case AFE_PORT_ID_SENARY_PCM_TX:
4586 return IDX_AFE_PORT_ID_SENARY_PCM_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304587 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
4588 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
4589 case MI2S_RX: return IDX_MI2S_RX;
4590 case MI2S_TX: return IDX_MI2S_TX;
4591 case HDMI_RX: return IDX_HDMI_RX;
4592 case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX;
Ralf Herzcc29b9e2018-07-17 20:19:04 +05304593 case AFE_PORT_ID_PRIMARY_SPDIF_RX: return IDX_PRIMARY_SPDIF_RX;
4594 case AFE_PORT_ID_PRIMARY_SPDIF_TX: return IDX_PRIMARY_SPDIF_TX;
4595 case AFE_PORT_ID_SECONDARY_SPDIF_RX: return IDX_SECONDARY_SPDIF_RX;
4596 case AFE_PORT_ID_SECONDARY_SPDIF_TX: return IDX_SECONDARY_SPDIF_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304597 case RSVD_2: return IDX_RSVD_2;
4598 case RSVD_3: return IDX_RSVD_3;
4599 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
4600 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
4601 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
4602 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
4603 case VOICE2_PLAYBACK_TX: return IDX_VOICE2_PLAYBACK_TX;
4604 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
4605 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
4606 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
4607 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
4608 case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
4609 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
4610 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
4611 case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
4612 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
4613 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
4614 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
4615 case INT_FM_RX: return IDX_INT_FM_RX;
4616 case INT_FM_TX: return IDX_INT_FM_TX;
4617 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
4618 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
4619 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
4620 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
4621 case SLIMBUS_5_RX: return IDX_SLIMBUS_5_RX;
4622 case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX;
4623 case SLIMBUS_6_RX: return IDX_SLIMBUS_6_RX;
4624 case SLIMBUS_6_TX: return IDX_SLIMBUS_6_TX;
4625 case SLIMBUS_7_RX: return IDX_SLIMBUS_7_RX;
4626 case SLIMBUS_7_TX: return IDX_SLIMBUS_7_TX;
4627 case SLIMBUS_8_RX: return IDX_SLIMBUS_8_RX;
4628 case SLIMBUS_8_TX: return IDX_SLIMBUS_8_TX;
Surendar Karkab0dd21f2018-09-28 18:53:50 +05304629 case SLIMBUS_9_RX: return IDX_SLIMBUS_9_RX;
4630 case SLIMBUS_9_TX: return IDX_SLIMBUS_9_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304631 case AFE_PORT_ID_USB_RX: return IDX_AFE_PORT_ID_USB_RX;
4632 case AFE_PORT_ID_USB_TX: return IDX_AFE_PORT_ID_USB_TX;
4633 case AFE_PORT_ID_PRIMARY_MI2S_RX:
4634 return IDX_AFE_PORT_ID_PRIMARY_MI2S_RX;
4635 case AFE_PORT_ID_PRIMARY_MI2S_TX:
4636 return IDX_AFE_PORT_ID_PRIMARY_MI2S_TX;
4637 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
4638 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
4639 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
4640 return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX;
4641 case AFE_PORT_ID_SECONDARY_MI2S_RX:
4642 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX;
4643 case AFE_PORT_ID_SECONDARY_MI2S_TX:
4644 return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX;
4645 case AFE_PORT_ID_TERTIARY_MI2S_RX:
4646 return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX;
4647 case AFE_PORT_ID_TERTIARY_MI2S_TX:
4648 return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX;
4649 case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1:
4650 return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_SD1;
4651 case AFE_PORT_ID_QUINARY_MI2S_RX:
4652 return IDX_AFE_PORT_ID_QUINARY_MI2S_RX;
4653 case AFE_PORT_ID_QUINARY_MI2S_TX:
4654 return IDX_AFE_PORT_ID_QUINARY_MI2S_TX;
4655 case AFE_PORT_ID_SENARY_MI2S_TX:
4656 return IDX_AFE_PORT_ID_SENARY_MI2S_TX;
4657 case AFE_PORT_ID_PRIMARY_TDM_RX:
4658 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_0;
4659 case AFE_PORT_ID_PRIMARY_TDM_TX:
4660 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_0;
4661 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
4662 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_1;
4663 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
4664 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_1;
4665 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
4666 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_2;
4667 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
4668 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_2;
4669 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
4670 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_3;
4671 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
4672 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_3;
4673 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
4674 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_4;
4675 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
4676 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_4;
4677 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
4678 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_5;
4679 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
4680 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_5;
4681 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
4682 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_6;
4683 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
4684 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_6;
4685 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
4686 return IDX_AFE_PORT_ID_PRIMARY_TDM_RX_7;
4687 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
4688 return IDX_AFE_PORT_ID_PRIMARY_TDM_TX_7;
4689 case AFE_PORT_ID_SECONDARY_TDM_RX:
4690 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_0;
4691 case AFE_PORT_ID_SECONDARY_TDM_TX:
4692 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_0;
4693 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
4694 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_1;
4695 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
4696 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_1;
4697 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
4698 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_2;
4699 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
4700 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_2;
4701 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
4702 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_3;
4703 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
4704 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_3;
4705 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
4706 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_4;
4707 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
4708 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_4;
4709 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
4710 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_5;
4711 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
4712 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_5;
4713 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
4714 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_6;
4715 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
4716 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_6;
4717 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
4718 return IDX_AFE_PORT_ID_SECONDARY_TDM_RX_7;
4719 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
4720 return IDX_AFE_PORT_ID_SECONDARY_TDM_TX_7;
4721 case AFE_PORT_ID_TERTIARY_TDM_RX:
4722 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_0;
4723 case AFE_PORT_ID_TERTIARY_TDM_TX:
4724 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_0;
4725 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
4726 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_1;
4727 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
4728 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_1;
4729 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
4730 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_2;
4731 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
4732 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_2;
4733 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
4734 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_3;
4735 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
4736 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_3;
4737 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
4738 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_4;
4739 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
4740 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_4;
4741 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
4742 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_5;
4743 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
4744 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_5;
4745 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
4746 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_6;
4747 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
4748 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_6;
4749 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
4750 return IDX_AFE_PORT_ID_TERTIARY_TDM_RX_7;
4751 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
4752 return IDX_AFE_PORT_ID_TERTIARY_TDM_TX_7;
4753 case AFE_PORT_ID_QUATERNARY_TDM_RX:
4754 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_0;
4755 case AFE_PORT_ID_QUATERNARY_TDM_TX:
4756 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_0;
4757 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
4758 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_1;
4759 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
4760 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_1;
4761 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
4762 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_2;
4763 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
4764 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_2;
4765 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
4766 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_3;
4767 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
4768 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_3;
4769 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
4770 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_4;
4771 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
4772 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_4;
4773 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
4774 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_5;
4775 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
4776 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_5;
4777 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
4778 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_6;
4779 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
4780 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_6;
4781 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
4782 return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_7;
4783 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
4784 return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_7;
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304785 case AFE_PORT_ID_QUINARY_TDM_RX:
4786 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_0;
4787 case AFE_PORT_ID_QUINARY_TDM_TX:
4788 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_0;
4789 case AFE_PORT_ID_QUINARY_TDM_RX_1:
4790 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_1;
4791 case AFE_PORT_ID_QUINARY_TDM_TX_1:
4792 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_1;
4793 case AFE_PORT_ID_QUINARY_TDM_RX_2:
4794 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_2;
4795 case AFE_PORT_ID_QUINARY_TDM_TX_2:
4796 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_2;
4797 case AFE_PORT_ID_QUINARY_TDM_RX_3:
4798 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_3;
4799 case AFE_PORT_ID_QUINARY_TDM_TX_3:
4800 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_3;
4801 case AFE_PORT_ID_QUINARY_TDM_RX_4:
4802 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_4;
4803 case AFE_PORT_ID_QUINARY_TDM_TX_4:
4804 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_4;
4805 case AFE_PORT_ID_QUINARY_TDM_RX_5:
4806 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_5;
4807 case AFE_PORT_ID_QUINARY_TDM_TX_5:
4808 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_5;
4809 case AFE_PORT_ID_QUINARY_TDM_RX_6:
4810 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_6;
4811 case AFE_PORT_ID_QUINARY_TDM_TX_6:
4812 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_6;
4813 case AFE_PORT_ID_QUINARY_TDM_RX_7:
4814 return IDX_AFE_PORT_ID_QUINARY_TDM_RX_7;
4815 case AFE_PORT_ID_QUINARY_TDM_TX_7:
4816 return IDX_AFE_PORT_ID_QUINARY_TDM_TX_7;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304817 case AFE_PORT_ID_INT0_MI2S_RX:
4818 return IDX_AFE_PORT_ID_INT0_MI2S_RX;
4819 case AFE_PORT_ID_INT0_MI2S_TX:
4820 return IDX_AFE_PORT_ID_INT0_MI2S_TX;
4821 case AFE_PORT_ID_INT1_MI2S_RX:
4822 return IDX_AFE_PORT_ID_INT1_MI2S_RX;
4823 case AFE_PORT_ID_INT1_MI2S_TX:
4824 return IDX_AFE_PORT_ID_INT1_MI2S_TX;
4825 case AFE_PORT_ID_INT2_MI2S_RX:
4826 return IDX_AFE_PORT_ID_INT2_MI2S_RX;
4827 case AFE_PORT_ID_INT2_MI2S_TX:
4828 return IDX_AFE_PORT_ID_INT2_MI2S_TX;
4829 case AFE_PORT_ID_INT3_MI2S_RX:
4830 return IDX_AFE_PORT_ID_INT3_MI2S_RX;
4831 case AFE_PORT_ID_INT3_MI2S_TX:
4832 return IDX_AFE_PORT_ID_INT3_MI2S_TX;
4833 case AFE_PORT_ID_INT4_MI2S_RX:
4834 return IDX_AFE_PORT_ID_INT4_MI2S_RX;
4835 case AFE_PORT_ID_INT4_MI2S_TX:
4836 return IDX_AFE_PORT_ID_INT4_MI2S_TX;
4837 case AFE_PORT_ID_INT5_MI2S_RX:
4838 return IDX_AFE_PORT_ID_INT5_MI2S_RX;
4839 case AFE_PORT_ID_INT5_MI2S_TX:
4840 return IDX_AFE_PORT_ID_INT5_MI2S_TX;
4841 case AFE_PORT_ID_INT6_MI2S_RX:
4842 return IDX_AFE_PORT_ID_INT6_MI2S_RX;
4843 case AFE_PORT_ID_INT6_MI2S_TX:
4844 return IDX_AFE_PORT_ID_INT6_MI2S_TX;
Mangesh Kunchamwar1274b762018-06-28 15:40:57 +05304845 case AFE_PORT_ID_VA_CODEC_DMA_TX_0:
4846 return IDX_AFE_PORT_ID_VA_CODEC_DMA_TX_0;
4847 case AFE_PORT_ID_VA_CODEC_DMA_TX_1:
4848 return IDX_AFE_PORT_ID_VA_CODEC_DMA_TX_1;
Xiaoyu Ye8341eef2019-01-03 14:57:47 -08004849 case AFE_PORT_ID_VA_CODEC_DMA_TX_2:
4850 return IDX_AFE_PORT_ID_VA_CODEC_DMA_TX_2;
Mangesh Kunchamwar1274b762018-06-28 15:40:57 +05304851 case AFE_PORT_ID_WSA_CODEC_DMA_RX_0:
4852 return IDX_AFE_PORT_ID_WSA_CODEC_DMA_RX_0;
4853 case AFE_PORT_ID_WSA_CODEC_DMA_TX_0:
4854 return IDX_AFE_PORT_ID_WSA_CODEC_DMA_TX_0;
4855 case AFE_PORT_ID_WSA_CODEC_DMA_RX_1:
4856 return IDX_AFE_PORT_ID_WSA_CODEC_DMA_RX_1;
4857 case AFE_PORT_ID_WSA_CODEC_DMA_TX_1:
4858 return IDX_AFE_PORT_ID_WSA_CODEC_DMA_TX_1;
4859 case AFE_PORT_ID_WSA_CODEC_DMA_TX_2:
4860 return IDX_AFE_PORT_ID_WSA_CODEC_DMA_TX_2;
Aditya Bavanari54ca7d12018-08-08 13:59:54 +05304861 case AFE_PORT_ID_RX_CODEC_DMA_RX_0:
4862 return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_0;
4863 case AFE_PORT_ID_TX_CODEC_DMA_TX_0:
4864 return IDX_AFE_PORT_ID_TX_CODEC_DMA_TX_0;
4865 case AFE_PORT_ID_RX_CODEC_DMA_RX_1:
4866 return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_1;
4867 case AFE_PORT_ID_TX_CODEC_DMA_TX_1:
4868 return IDX_AFE_PORT_ID_TX_CODEC_DMA_TX_1;
4869 case AFE_PORT_ID_RX_CODEC_DMA_RX_2:
4870 return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_2;
4871 case AFE_PORT_ID_TX_CODEC_DMA_TX_2:
4872 return IDX_AFE_PORT_ID_TX_CODEC_DMA_TX_2;
4873 case AFE_PORT_ID_RX_CODEC_DMA_RX_3:
4874 return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_3;
4875 case AFE_PORT_ID_TX_CODEC_DMA_TX_3:
4876 return IDX_AFE_PORT_ID_TX_CODEC_DMA_TX_3;
4877 case AFE_PORT_ID_RX_CODEC_DMA_RX_4:
4878 return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_4;
4879 case AFE_PORT_ID_TX_CODEC_DMA_TX_4:
4880 return IDX_AFE_PORT_ID_TX_CODEC_DMA_TX_4;
4881 case AFE_PORT_ID_RX_CODEC_DMA_RX_5:
4882 return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_5;
4883 case AFE_PORT_ID_TX_CODEC_DMA_TX_5:
4884 return IDX_AFE_PORT_ID_TX_CODEC_DMA_TX_5;
4885 case AFE_PORT_ID_RX_CODEC_DMA_RX_6:
4886 return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_6;
4887 case AFE_PORT_ID_RX_CODEC_DMA_RX_7:
4888 return IDX_AFE_PORT_ID_RX_CODEC_DMA_RX_7;
Surendar Karkad47fda42018-05-20 19:21:10 +05304889 case AFE_LOOPBACK_TX:
4890 return IDX_AFE_LOOPBACK_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304891 default:
4892 pr_err("%s: port 0x%x\n", __func__, port_id);
4893 return -EINVAL;
4894 }
4895}
4896
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304897/**
4898 * afe_open -
4899 * command to open AFE port
4900 *
4901 * @port_id: AFE port id
4902 * @afe_config: AFE port config to pass
4903 * @rate: sample rate
4904 *
4905 * Returns 0 on success or error on failure
4906 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304907int afe_open(u16 port_id,
4908 union afe_port_config *afe_config, int rate)
4909{
4910 struct afe_port_cmd_device_start start;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004911 union afe_port_config port_cfg;
4912 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304913 int ret = 0;
4914 int cfg_type;
4915 int index = 0;
4916
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08004917 memset(&param_hdr, 0, sizeof(param_hdr));
4918 memset(&start, 0, sizeof(start));
4919 memset(&port_cfg, 0, sizeof(port_cfg));
4920
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304921 if (!afe_config) {
4922 pr_err("%s: Error, no configuration data\n", __func__);
4923 ret = -EINVAL;
4924 return ret;
4925 }
4926
4927 pr_err("%s: port_id 0x%x rate %d\n", __func__, port_id, rate);
4928
4929 index = q6audio_get_port_index(port_id);
4930 if (index < 0 || index >= AFE_MAX_PORTS) {
4931 pr_err("%s: AFE port index[%d] invalid!\n",
4932 __func__, index);
4933 return -EINVAL;
4934 }
4935 ret = q6audio_validate_port(port_id);
4936 if (ret < 0) {
4937 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
4938 return -EINVAL;
4939 }
4940
4941 if ((port_id == RT_PROXY_DAI_001_RX) ||
4942 (port_id == RT_PROXY_DAI_002_TX)) {
4943 pr_err("%s: wrong port 0x%x\n", __func__, port_id);
4944 return -EINVAL;
4945 }
4946 if ((port_id == RT_PROXY_DAI_002_RX) ||
4947 (port_id == RT_PROXY_DAI_001_TX))
4948 port_id = VIRTUAL_ID_TO_PORTID(port_id);
4949
4950 ret = afe_q6_interface_prepare();
4951 if (ret != 0) {
4952 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
4953 return -EINVAL;
4954 }
4955
4956 if ((index >= 0) && (index < AFE_MAX_PORTS)) {
4957 this_afe.afe_sample_rates[index] = rate;
4958
4959 if (this_afe.rt_cb)
4960 this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
4961 }
4962
4963 /* Also send the topology id here: */
4964 afe_send_custom_topology(); /* One time call: only for first time */
4965 afe_send_port_topology_id(port_id);
4966
4967 ret = q6audio_validate_port(port_id);
4968 if (ret < 0) {
4969 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
4970 __func__, port_id, ret);
4971 return -EINVAL;
4972 }
4973 mutex_lock(&this_afe.afe_cmd_lock);
4974
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304975 switch (port_id) {
4976 case PRIMARY_I2S_RX:
4977 case PRIMARY_I2S_TX:
4978 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
4979 break;
4980 case AFE_PORT_ID_PRIMARY_PCM_RX:
4981 case AFE_PORT_ID_PRIMARY_PCM_TX:
4982 case AFE_PORT_ID_SECONDARY_PCM_RX:
4983 case AFE_PORT_ID_SECONDARY_PCM_TX:
4984 case AFE_PORT_ID_TERTIARY_PCM_RX:
4985 case AFE_PORT_ID_TERTIARY_PCM_TX:
4986 case AFE_PORT_ID_QUATERNARY_PCM_RX:
4987 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05304988 case AFE_PORT_ID_QUINARY_PCM_RX:
4989 case AFE_PORT_ID_QUINARY_PCM_TX:
Dieter Lueckingfa7687b2018-09-28 14:21:44 +02004990 case AFE_PORT_ID_SENARY_PCM_RX:
4991 case AFE_PORT_ID_SENARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304992 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
4993 break;
4994 case SECONDARY_I2S_RX:
4995 case SECONDARY_I2S_TX:
4996 case AFE_PORT_ID_PRIMARY_MI2S_RX:
4997 case AFE_PORT_ID_PRIMARY_MI2S_TX:
4998 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
4999 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
5000 case MI2S_RX:
5001 case MI2S_TX:
5002 case AFE_PORT_ID_QUINARY_MI2S_RX:
5003 case AFE_PORT_ID_QUINARY_MI2S_TX:
5004 case AFE_PORT_ID_SENARY_MI2S_TX:
5005 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
5006 break;
5007 case HDMI_RX:
5008 case DISPLAY_PORT_RX:
5009 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
5010 break;
Ralf Herzcc29b9e2018-07-17 20:19:04 +05305011 case AFE_PORT_ID_PRIMARY_SPDIF_RX:
5012 case AFE_PORT_ID_PRIMARY_SPDIF_TX:
5013 case AFE_PORT_ID_SECONDARY_SPDIF_RX:
5014 case AFE_PORT_ID_SECONDARY_SPDIF_TX:
5015 cfg_type = AFE_PARAM_ID_SPDIF_CONFIG;
5016 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305017 case SLIMBUS_0_RX:
5018 case SLIMBUS_0_TX:
5019 case SLIMBUS_1_RX:
5020 case SLIMBUS_1_TX:
5021 case SLIMBUS_2_RX:
5022 case SLIMBUS_2_TX:
5023 case SLIMBUS_3_RX:
5024 case SLIMBUS_3_TX:
5025 case SLIMBUS_4_RX:
5026 case SLIMBUS_4_TX:
5027 case SLIMBUS_5_RX:
5028 case SLIMBUS_6_RX:
5029 case SLIMBUS_6_TX:
5030 case SLIMBUS_7_RX:
5031 case SLIMBUS_7_TX:
5032 case SLIMBUS_8_RX:
5033 case SLIMBUS_8_TX:
Surendar Karkab0dd21f2018-09-28 18:53:50 +05305034 case SLIMBUS_9_RX:
5035 case SLIMBUS_9_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305036 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
5037 break;
5038 case AFE_PORT_ID_USB_RX:
5039 case AFE_PORT_ID_USB_TX:
5040 cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
5041 break;
Mangesh Kunchamwar8c706ab2018-04-04 17:48:46 +05305042 case AFE_PORT_ID_WSA_CODEC_DMA_RX_0:
5043 case AFE_PORT_ID_WSA_CODEC_DMA_TX_0:
5044 case AFE_PORT_ID_WSA_CODEC_DMA_RX_1:
5045 case AFE_PORT_ID_WSA_CODEC_DMA_TX_1:
5046 case AFE_PORT_ID_WSA_CODEC_DMA_TX_2:
5047 case AFE_PORT_ID_VA_CODEC_DMA_TX_0:
5048 case AFE_PORT_ID_VA_CODEC_DMA_TX_1:
Xiaoyu Ye8341eef2019-01-03 14:57:47 -08005049 case AFE_PORT_ID_VA_CODEC_DMA_TX_2:
Aditya Bavanari348a4a62018-05-16 21:48:45 +05305050 case AFE_PORT_ID_RX_CODEC_DMA_RX_0:
5051 case AFE_PORT_ID_TX_CODEC_DMA_TX_0:
5052 case AFE_PORT_ID_RX_CODEC_DMA_RX_1:
5053 case AFE_PORT_ID_TX_CODEC_DMA_TX_1:
5054 case AFE_PORT_ID_RX_CODEC_DMA_RX_2:
5055 case AFE_PORT_ID_TX_CODEC_DMA_TX_2:
5056 case AFE_PORT_ID_RX_CODEC_DMA_RX_3:
5057 case AFE_PORT_ID_TX_CODEC_DMA_TX_3:
5058 case AFE_PORT_ID_RX_CODEC_DMA_RX_4:
5059 case AFE_PORT_ID_TX_CODEC_DMA_TX_4:
5060 case AFE_PORT_ID_RX_CODEC_DMA_RX_5:
5061 case AFE_PORT_ID_TX_CODEC_DMA_TX_5:
5062 case AFE_PORT_ID_RX_CODEC_DMA_RX_6:
5063 case AFE_PORT_ID_RX_CODEC_DMA_RX_7:
Mangesh Kunchamwar8c706ab2018-04-04 17:48:46 +05305064 cfg_type = AFE_PARAM_ID_CODEC_DMA_CONFIG;
5065 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305066 default:
5067 pr_err("%s: Invalid port id 0x%x\n",
5068 __func__, port_id);
5069 ret = -EINVAL;
5070 goto fail_cmd;
5071 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305072
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005073 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
5074 param_hdr.instance_id = INSTANCE_ID_0;
5075 param_hdr.param_id = cfg_type;
5076 param_hdr.param_size = sizeof(union afe_port_config);
5077 port_cfg = *afe_config;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305078
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005079 ret = q6afe_pack_and_set_param_in_band(port_id,
5080 q6audio_get_port_index(port_id),
5081 param_hdr, (u8 *) &port_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305082 if (ret) {
5083 pr_err("%s: AFE enable for port 0x%x opcode[0x%x]failed %d\n",
5084 __func__, port_id, cfg_type, ret);
5085 goto fail_cmd;
5086 }
5087 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5088 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5089 start.hdr.pkt_size = sizeof(start);
5090 start.hdr.src_port = 0;
5091 start.hdr.dest_port = 0;
5092 start.hdr.token = index;
5093 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
5094 start.port_id = q6audio_get_port_id(port_id);
5095 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
5096 __func__, start.hdr.opcode, start.port_id);
5097
5098 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
5099 if (ret) {
5100 pr_err("%s: AFE enable for port 0x%x failed %d\n", __func__,
5101 port_id, ret);
5102 goto fail_cmd;
5103 }
5104
5105fail_cmd:
5106 mutex_unlock(&this_afe.afe_cmd_lock);
5107 return ret;
5108}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305109EXPORT_SYMBOL(afe_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305110
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305111/**
5112 * afe_loopback -
5113 * command to set loopback between AFE ports
5114 *
5115 * @enable: enable or disable loopback
5116 * @rx_port: AFE RX port ID
5117 * @tx_port: AFE TX port ID
5118 *
5119 * Returns 0 on success or error on failure
5120 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305121int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
5122{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005123 struct afe_loopback_cfg_v1 lb_param;
5124 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305125 int ret = 0;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005126
5127 memset(&lb_param, 0, sizeof(lb_param));
5128 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305129
5130 if (rx_port == MI2S_RX)
5131 rx_port = AFE_PORT_ID_PRIMARY_MI2S_RX;
5132 if (tx_port == MI2S_TX)
5133 tx_port = AFE_PORT_ID_PRIMARY_MI2S_TX;
5134
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005135 param_hdr.module_id = AFE_MODULE_LOOPBACK;
5136 param_hdr.instance_id = INSTANCE_ID_0;
5137 param_hdr.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
5138 param_hdr.param_size = sizeof(struct afe_loopback_cfg_v1);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305139
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005140 lb_param.dst_port_id = rx_port;
5141 lb_param.routing_mode = LB_MODE_DEFAULT;
5142 lb_param.enable = (enable ? 1 : 0);
5143 lb_param.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305144
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005145 ret = q6afe_pack_and_set_param_in_band(tx_port,
5146 q6audio_get_port_index(tx_port),
5147 param_hdr, (u8 *) &lb_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305148 if (ret)
5149 pr_err("%s: AFE loopback failed %d\n", __func__, ret);
5150 return ret;
5151}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305152EXPORT_SYMBOL(afe_loopback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305153
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305154/**
5155 * afe_loopback_gain -
5156 * command to set gain for AFE loopback
5157 *
5158 * @port_id: AFE port id
5159 * @volume: gain value to set
5160 *
5161 * Returns 0 on success or error on failure
5162 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305163int afe_loopback_gain(u16 port_id, u16 volume)
5164{
5165 struct afe_loopback_gain_per_path_param set_param;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005166 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305167 int ret = 0;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005168
5169 memset(&set_param, 0, sizeof(set_param));
5170 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305171
5172 if (this_afe.apr == NULL) {
5173 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5174 0xFFFFFFFF, &this_afe);
5175 pr_debug("%s: Register AFE\n", __func__);
5176 if (this_afe.apr == NULL) {
5177 pr_err("%s: Unable to register AFE\n", __func__);
5178 ret = -ENODEV;
5179 return ret;
5180 }
5181 rtac_set_afe_handle(this_afe.apr);
5182 }
5183
5184 ret = q6audio_validate_port(port_id);
5185 if (ret < 0) {
5186 pr_err("%s: Failed : Invalid Port id = 0x%x ret %d\n",
5187 __func__, port_id, ret);
5188 ret = -EINVAL;
5189 goto fail_cmd;
5190 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305191
5192 /* RX ports numbers are even .TX ports numbers are odd. */
5193 if (port_id % 2 == 0) {
5194 pr_err("%s: Failed : afe loopback gain only for TX ports. port_id %d\n",
5195 __func__, port_id);
5196 ret = -EINVAL;
5197 goto fail_cmd;
5198 }
5199
5200 pr_debug("%s: port 0x%x volume %d\n", __func__, port_id, volume);
5201
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005202 param_hdr.module_id = AFE_MODULE_LOOPBACK;
5203 param_hdr.instance_id = INSTANCE_ID_0;
5204 param_hdr.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
5205 param_hdr.param_size = sizeof(struct afe_loopback_gain_per_path_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305206 set_param.rx_port_id = port_id;
5207 set_param.gain = volume;
5208
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005209 ret = q6afe_pack_and_set_param_in_band(port_id,
5210 q6audio_get_port_index(port_id),
5211 param_hdr, (u8 *) &set_param);
5212 if (ret)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305213 pr_err("%s: AFE param set failed for port 0x%x ret %d\n",
5214 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305215
5216fail_cmd:
5217 return ret;
5218}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305219EXPORT_SYMBOL(afe_loopback_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305220
5221int afe_pseudo_port_start_nowait(u16 port_id)
5222{
5223 struct afe_pseudoport_start_command start;
5224 int ret = 0;
5225
5226 pr_debug("%s: port_id=0x%x\n", __func__, port_id);
5227 if (this_afe.apr == NULL) {
5228 pr_err("%s: AFE APR is not registered\n", __func__);
5229 return -ENODEV;
5230 }
5231
5232
5233 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5234 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5235 start.hdr.pkt_size = sizeof(start);
5236 start.hdr.src_port = 0;
5237 start.hdr.dest_port = 0;
5238 start.hdr.token = 0;
5239 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
5240 start.port_id = port_id;
5241 start.timing = 1;
5242
5243 ret = afe_apr_send_pkt(&start, NULL);
5244 if (ret) {
5245 pr_err("%s: AFE enable for port 0x%x failed %d\n",
5246 __func__, port_id, ret);
5247 return ret;
5248 }
5249 return 0;
5250}
5251
5252int afe_start_pseudo_port(u16 port_id)
5253{
5254 int ret = 0;
5255 struct afe_pseudoport_start_command start;
5256 int index = 0;
5257
5258 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
5259
5260 ret = afe_q6_interface_prepare();
5261 if (ret != 0) {
5262 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
5263 return ret;
5264 }
5265
5266 index = q6audio_get_port_index(port_id);
5267 if (index < 0 || index >= AFE_MAX_PORTS) {
5268 pr_err("%s: AFE port index[%d] invalid!\n",
5269 __func__, index);
5270 return -EINVAL;
5271 }
5272 ret = q6audio_validate_port(port_id);
5273 if (ret < 0) {
5274 pr_err("%s: Invalid port 0x%x ret %d",
5275 __func__, port_id, ret);
5276 return -EINVAL;
5277 }
5278
5279 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5280 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5281 start.hdr.pkt_size = sizeof(start);
5282 start.hdr.src_port = 0;
5283 start.hdr.dest_port = 0;
5284 start.hdr.token = 0;
5285 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
5286 start.port_id = port_id;
5287 start.timing = 1;
5288 start.hdr.token = index;
5289
5290 ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
5291 if (ret)
5292 pr_err("%s: AFE enable for port 0x%x failed %d\n",
5293 __func__, port_id, ret);
5294 return ret;
5295}
5296
5297int afe_pseudo_port_stop_nowait(u16 port_id)
5298{
5299 int ret = 0;
5300 struct afe_pseudoport_stop_command stop;
5301 int index = 0;
5302
5303 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
5304
5305 if (this_afe.apr == NULL) {
5306 pr_err("%s: AFE is already closed\n", __func__);
5307 return -EINVAL;
5308 }
5309 index = q6audio_get_port_index(port_id);
5310 if (index < 0 || index >= AFE_MAX_PORTS) {
5311 pr_err("%s: AFE port index[%d] invalid!\n",
5312 __func__, index);
5313 return -EINVAL;
5314 }
5315 ret = q6audio_validate_port(port_id);
5316 if (ret < 0) {
5317 pr_err("%s: Invalid port 0x%x ret %d",
5318 __func__, port_id, ret);
5319 return -EINVAL;
5320 }
5321
5322 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5323 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5324 stop.hdr.pkt_size = sizeof(stop);
5325 stop.hdr.src_port = 0;
5326 stop.hdr.dest_port = 0;
5327 stop.hdr.token = 0;
5328 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
5329 stop.port_id = port_id;
5330 stop.reserved = 0;
5331 stop.hdr.token = index;
5332
5333 ret = afe_apr_send_pkt(&stop, NULL);
5334 if (ret)
5335 pr_err("%s: AFE close failed %d\n", __func__, ret);
5336
5337 return ret;
5338}
5339
5340int afe_port_group_set_param(u16 group_id,
5341 union afe_port_group_config *afe_group_config)
5342{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005343 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305344 int cfg_type;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005345 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305346
5347 if (!afe_group_config) {
5348 pr_err("%s: Error, no configuration data\n", __func__);
5349 return -EINVAL;
5350 }
5351
5352 pr_debug("%s: group id: 0x%x\n", __func__, group_id);
5353
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005354 memset(&param_hdr, 0, sizeof(param_hdr));
5355
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305356 ret = afe_q6_interface_prepare();
5357 if (ret != 0) {
5358 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
5359 return ret;
5360 }
5361
5362 switch (group_id) {
5363 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX:
5364 case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX:
5365 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_RX:
5366 case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_TX:
5367 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_RX:
5368 case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_TX:
5369 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_RX:
5370 case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05305371 case AFE_GROUP_DEVICE_ID_QUINARY_TDM_RX:
5372 case AFE_GROUP_DEVICE_ID_QUINARY_TDM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305373 cfg_type = AFE_PARAM_ID_GROUP_DEVICE_TDM_CONFIG;
5374 break;
5375 default:
5376 pr_err("%s: Invalid group id 0x%x\n", __func__, group_id);
5377 return -EINVAL;
5378 }
5379
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005380 param_hdr.module_id = AFE_MODULE_GROUP_DEVICE;
5381 param_hdr.instance_id = INSTANCE_ID_0;
5382 param_hdr.param_id = cfg_type;
5383 param_hdr.param_size = sizeof(union afe_port_group_config);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305384
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005385 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
5386 (u8 *) afe_group_config);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305387 if (ret)
5388 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_CFG failed %d\n",
5389 __func__, ret);
5390
5391 return ret;
5392}
5393
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305394/**
5395 * afe_port_group_enable -
5396 * command to enable AFE port group
5397 *
5398 * @group_id: group ID for AFE port group
5399 * @afe_group_config: config for AFE group
5400 * @enable: flag to indicate enable or disable
5401 *
5402 * Returns 0 on success or error on failure
5403 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305404int afe_port_group_enable(u16 group_id,
5405 union afe_port_group_config *afe_group_config,
5406 u16 enable)
5407{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005408 struct afe_group_device_enable group_enable;
5409 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305410 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305411
5412 pr_debug("%s: group id: 0x%x enable: %d\n", __func__,
5413 group_id, enable);
5414
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005415 memset(&group_enable, 0, sizeof(group_enable));
5416 memset(&param_hdr, 0, sizeof(param_hdr));
5417
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305418 ret = afe_q6_interface_prepare();
5419 if (ret != 0) {
5420 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
5421 return ret;
5422 }
5423
5424 if (enable) {
5425 ret = afe_port_group_set_param(group_id, afe_group_config);
5426 if (ret < 0) {
5427 pr_err("%s: afe send failed %d\n", __func__, ret);
5428 return ret;
5429 }
5430 }
5431
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005432 param_hdr.module_id = AFE_MODULE_GROUP_DEVICE;
5433 param_hdr.instance_id = INSTANCE_ID_0;
5434 param_hdr.param_id = AFE_PARAM_ID_GROUP_DEVICE_ENABLE;
5435 param_hdr.param_size = sizeof(struct afe_group_device_enable);
5436 group_enable.group_id = group_id;
5437 group_enable.enable = enable;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305438
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08005439 ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr,
5440 (u8 *) &group_enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305441 if (ret)
5442 pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_ENABLE failed %d\n",
5443 __func__, ret);
5444
5445 return ret;
5446}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305447EXPORT_SYMBOL(afe_port_group_enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305448
5449int afe_stop_pseudo_port(u16 port_id)
5450{
5451 int ret = 0;
5452 struct afe_pseudoport_stop_command stop;
5453 int index = 0;
5454
5455 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
5456
5457 if (this_afe.apr == NULL) {
5458 pr_err("%s: AFE is already closed\n", __func__);
5459 return -EINVAL;
5460 }
5461
5462 index = q6audio_get_port_index(port_id);
5463 if (index < 0 || index >= AFE_MAX_PORTS) {
5464 pr_err("%s: AFE port index[%d] invalid!\n",
5465 __func__, index);
5466 return -EINVAL;
5467 }
5468 ret = q6audio_validate_port(port_id);
5469 if (ret < 0) {
5470 pr_err("%s: Invalid port 0x%x ret %d\n",
5471 __func__, port_id, ret);
5472 return -EINVAL;
5473 }
5474
5475 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5476 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5477 stop.hdr.pkt_size = sizeof(stop);
5478 stop.hdr.src_port = 0;
5479 stop.hdr.dest_port = 0;
5480 stop.hdr.token = 0;
5481 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
5482 stop.port_id = port_id;
5483 stop.reserved = 0;
5484 stop.hdr.token = index;
5485
5486 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
5487 if (ret)
5488 pr_err("%s: AFE close failed %d\n", __func__, ret);
5489
5490 return ret;
5491}
5492
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305493/**
5494 * afe_req_mmap_handle -
5495 * Retrieve AFE memory map handle
5496 *
5497 * @ac: AFE audio client
5498 *
5499 * Returns memory map handle
5500 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305501uint32_t afe_req_mmap_handle(struct afe_audio_client *ac)
5502{
5503 return ac->mem_map_handle;
5504}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305505EXPORT_SYMBOL(afe_req_mmap_handle);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305506
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305507/**
5508 * q6afe_audio_client_alloc -
5509 * Assign new AFE audio client
5510 *
5511 * @priv: privata data to hold for audio client
5512 *
5513 * Returns ac pointer on success or NULL on failure
5514 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305515struct afe_audio_client *q6afe_audio_client_alloc(void *priv)
5516{
5517 struct afe_audio_client *ac;
5518 int lcnt = 0;
5519
5520 ac = kzalloc(sizeof(struct afe_audio_client), GFP_KERNEL);
5521 if (!ac)
5522 return NULL;
5523
5524 ac->priv = priv;
5525
5526 init_waitqueue_head(&ac->cmd_wait);
5527 INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
5528 INIT_LIST_HEAD(&ac->port[1].mem_map_handle);
5529 pr_debug("%s: mem_map_handle list init'ed\n", __func__);
5530 mutex_init(&ac->cmd_lock);
5531 for (lcnt = 0; lcnt <= OUT; lcnt++) {
5532 mutex_init(&ac->port[lcnt].lock);
5533 spin_lock_init(&ac->port[lcnt].dsp_lock);
5534 }
5535 atomic_set(&ac->cmd_state, 0);
5536
5537 return ac;
5538}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305539EXPORT_SYMBOL(q6afe_audio_client_alloc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305540
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305541/**
5542 * q6afe_audio_client_buf_alloc_contiguous -
5543 * Allocate contiguous shared buffers
5544 *
5545 * @dir: RX or TX direction of AFE port
5546 * @ac: AFE audio client handle
5547 * @bufsz: size of each shared buffer
5548 * @bufcnt: number of buffers
5549 *
5550 * Returns 0 on success or error on failure
5551 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305552int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir,
5553 struct afe_audio_client *ac,
5554 unsigned int bufsz,
5555 unsigned int bufcnt)
5556{
5557 int cnt = 0;
5558 int rc = 0;
5559 struct afe_audio_buffer *buf;
5560 size_t len;
5561
5562 if (!(ac) || ((dir != IN) && (dir != OUT))) {
5563 pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
5564 return -EINVAL;
5565 }
5566
5567 pr_debug("%s: bufsz[%d]bufcnt[%d]\n",
5568 __func__,
5569 bufsz, bufcnt);
5570
5571 if (ac->port[dir].buf) {
5572 pr_debug("%s: buffer already allocated\n", __func__);
5573 return 0;
5574 }
5575 mutex_lock(&ac->cmd_lock);
5576 buf = kzalloc(((sizeof(struct afe_audio_buffer))*bufcnt),
5577 GFP_KERNEL);
5578
5579 if (!buf) {
5580 pr_err("%s: null buf\n", __func__);
5581 mutex_unlock(&ac->cmd_lock);
5582 goto fail;
5583 }
5584
5585 ac->port[dir].buf = buf;
5586
Banajit Goswami08bb7362017-11-03 22:48:23 -07005587 rc = msm_audio_ion_alloc(&buf[0].dma_buf,
5588 bufsz * bufcnt,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305589 &buf[0].phys, &len,
5590 &buf[0].data);
5591 if (rc) {
5592 pr_err("%s: audio ION alloc failed, rc = %d\n",
5593 __func__, rc);
5594 mutex_unlock(&ac->cmd_lock);
5595 goto fail;
5596 }
5597
5598 buf[0].used = dir ^ 1;
5599 buf[0].size = bufsz;
5600 buf[0].actual_size = bufsz;
5601 cnt = 1;
5602 while (cnt < bufcnt) {
5603 if (bufsz > 0) {
5604 buf[cnt].data = buf[0].data + (cnt * bufsz);
5605 buf[cnt].phys = buf[0].phys + (cnt * bufsz);
5606 if (!buf[cnt].data) {
5607 pr_err("%s: Buf alloc failed\n",
5608 __func__);
5609 mutex_unlock(&ac->cmd_lock);
5610 goto fail;
5611 }
5612 buf[cnt].used = dir ^ 1;
5613 buf[cnt].size = bufsz;
5614 buf[cnt].actual_size = bufsz;
5615 pr_debug("%s: data[%pK]phys[%pK][%pK]\n", __func__,
5616 buf[cnt].data,
5617 &buf[cnt].phys,
5618 &buf[cnt].phys);
5619 }
5620 cnt++;
5621 }
5622 ac->port[dir].max_buf_cnt = cnt;
5623 mutex_unlock(&ac->cmd_lock);
5624 return 0;
5625fail:
5626 pr_err("%s: jump fail\n", __func__);
5627 q6afe_audio_client_buf_free_contiguous(dir, ac);
5628 return -EINVAL;
5629}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305630EXPORT_SYMBOL(q6afe_audio_client_buf_alloc_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305631
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305632/**
5633 * afe_memory_map -
5634 * command to map shared buffers to AFE
5635 *
5636 * @dma_addr_p: DMA physical address
5637 * @dma_buf_sz: shared DMA buffer size
5638 * @ac: AFE audio client handle
5639 *
5640 * Returns 0 on success or error on failure
5641 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305642int afe_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz,
5643 struct afe_audio_client *ac)
5644{
5645 int ret = 0;
5646
5647 mutex_lock(&this_afe.afe_cmd_lock);
5648 ac->mem_map_handle = 0;
5649 ret = afe_cmd_memory_map(dma_addr_p, dma_buf_sz);
5650 if (ret < 0) {
5651 pr_err("%s: afe_cmd_memory_map failed %d\n",
5652 __func__, ret);
5653
5654 mutex_unlock(&this_afe.afe_cmd_lock);
5655 return ret;
5656 }
5657 ac->mem_map_handle = this_afe.mmap_handle;
5658 mutex_unlock(&this_afe.afe_cmd_lock);
5659
5660 return ret;
5661}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305662EXPORT_SYMBOL(afe_memory_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305663
5664int afe_cmd_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz)
5665{
5666 int ret = 0;
5667 int cmd_size = 0;
5668 void *payload = NULL;
5669 void *mmap_region_cmd = NULL;
5670 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
5671 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
5672 int index = 0;
5673
5674 pr_debug("%s:\n", __func__);
5675
5676 if (this_afe.apr == NULL) {
5677 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5678 0xFFFFFFFF, &this_afe);
5679 pr_debug("%s: Register AFE\n", __func__);
5680 if (this_afe.apr == NULL) {
5681 pr_err("%s: Unable to register AFE\n", __func__);
5682 ret = -ENODEV;
5683 return ret;
5684 }
5685 rtac_set_afe_handle(this_afe.apr);
5686 }
5687 if (dma_buf_sz % SZ_4K != 0) {
5688 /*
5689 * The memory allocated by msm_audio_ion_alloc is always 4kB
5690 * aligned, ADSP expects the size to be 4kB aligned as well
5691 * so re-adjusts the buffer size before passing to ADSP.
5692 */
5693 dma_buf_sz = PAGE_ALIGN(dma_buf_sz);
5694 }
5695
5696 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
5697 + sizeof(struct afe_service_shared_map_region_payload);
5698
5699 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
5700 if (!mmap_region_cmd)
5701 return -ENOMEM;
5702
5703 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
5704 mmap_region_cmd;
5705 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5706 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5707 mregion->hdr.pkt_size = cmd_size;
5708 mregion->hdr.src_port = 0;
5709 mregion->hdr.dest_port = 0;
5710 mregion->hdr.token = 0;
5711 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
5712 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
5713 mregion->num_regions = 1;
5714 mregion->property_flag = 0x00;
5715 /* Todo */
5716 index = mregion->hdr.token = IDX_RSVD_2;
5717
5718 payload = ((u8 *) mmap_region_cmd +
5719 sizeof(struct afe_service_cmd_shared_mem_map_regions));
5720
5721 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
5722
5723 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
5724 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
5725 mregion_pl->mem_size_bytes = dma_buf_sz;
5726
5727 pr_debug("%s: dma_addr_p 0x%pK , size %d\n", __func__,
5728 &dma_addr_p, dma_buf_sz);
5729 atomic_set(&this_afe.state, 1);
5730 atomic_set(&this_afe.status, 0);
5731 this_afe.mmap_handle = 0;
5732 ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
5733 if (ret < 0) {
5734 pr_err("%s: AFE memory map cmd failed %d\n",
5735 __func__, ret);
5736 ret = -EINVAL;
5737 goto fail_cmd;
5738 }
5739
5740 ret = wait_event_timeout(this_afe.wait[index],
5741 (atomic_read(&this_afe.state) == 0),
5742 msecs_to_jiffies(TIMEOUT_MS));
5743 if (!ret) {
5744 pr_err("%s: wait_event timeout\n", __func__);
5745 ret = -EINVAL;
5746 goto fail_cmd;
5747 }
5748 if (atomic_read(&this_afe.status) > 0) {
5749 pr_err("%s: config cmd failed [%s]\n",
5750 __func__, adsp_err_get_err_str(
5751 atomic_read(&this_afe.status)));
5752 ret = adsp_err_get_lnx_err_code(
5753 atomic_read(&this_afe.status));
5754 goto fail_cmd;
5755 }
5756
5757 kfree(mmap_region_cmd);
5758 return 0;
5759fail_cmd:
5760 kfree(mmap_region_cmd);
5761 pr_err("%s: fail_cmd\n", __func__);
5762 return ret;
5763}
5764
5765int afe_cmd_memory_map_nowait(int port_id, phys_addr_t dma_addr_p,
5766 u32 dma_buf_sz)
5767{
5768 int ret = 0;
5769 int cmd_size = 0;
5770 void *payload = NULL;
5771 void *mmap_region_cmd = NULL;
5772 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
5773 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
5774 int index = 0;
5775
5776 pr_debug("%s:\n", __func__);
5777
5778 if (this_afe.apr == NULL) {
5779 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5780 0xFFFFFFFF, &this_afe);
5781 pr_debug("%s: Register AFE\n", __func__);
5782 if (this_afe.apr == NULL) {
5783 pr_err("%s: Unable to register AFE\n", __func__);
5784 ret = -ENODEV;
5785 return ret;
5786 }
5787 rtac_set_afe_handle(this_afe.apr);
5788 }
5789 index = q6audio_get_port_index(port_id);
5790 if (index < 0 || index >= AFE_MAX_PORTS) {
5791 pr_err("%s: AFE port index[%d] invalid!\n",
5792 __func__, index);
5793 return -EINVAL;
5794 }
5795 ret = q6audio_validate_port(port_id);
5796 if (ret < 0) {
5797 pr_err("%s: Invalid port 0x%x ret %d",
5798 __func__, port_id, ret);
5799 return -EINVAL;
5800 }
5801
5802 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
5803 + sizeof(struct afe_service_shared_map_region_payload);
5804
5805 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
5806 if (!mmap_region_cmd)
5807 return -ENOMEM;
5808
5809 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
5810 mmap_region_cmd;
5811 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5812 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5813 mregion->hdr.pkt_size = sizeof(mregion);
5814 mregion->hdr.src_port = 0;
5815 mregion->hdr.dest_port = 0;
5816 mregion->hdr.token = 0;
5817 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
5818 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
5819 mregion->num_regions = 1;
5820 mregion->property_flag = 0x00;
5821
5822 payload = ((u8 *) mmap_region_cmd +
5823 sizeof(struct afe_service_cmd_shared_mem_map_regions));
5824 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
5825
5826 mregion_pl->shm_addr_lsw = lower_32_bits(dma_addr_p);
5827 mregion_pl->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
5828 mregion_pl->mem_size_bytes = dma_buf_sz;
5829
5830 ret = afe_apr_send_pkt(mmap_region_cmd, NULL);
5831 if (ret)
5832 pr_err("%s: AFE memory map cmd failed %d\n",
5833 __func__, ret);
5834 kfree(mmap_region_cmd);
5835 return ret;
5836}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305837
5838/**
5839 * q6afe_audio_client_buf_free_contiguous -
5840 * frees the shared contiguous memory
5841 *
5842 * @dir: RX or TX direction of port
5843 * @ac: AFE audio client handle
5844 *
5845 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305846int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
5847 struct afe_audio_client *ac)
5848{
5849 struct afe_audio_port_data *port;
5850 int cnt = 0;
5851
5852 mutex_lock(&ac->cmd_lock);
5853 port = &ac->port[dir];
5854 if (!port->buf) {
5855 pr_err("%s: buf is null\n", __func__);
5856 mutex_unlock(&ac->cmd_lock);
5857 return 0;
5858 }
5859 cnt = port->max_buf_cnt - 1;
5860
5861 if (port->buf[0].data) {
Banajit Goswami08bb7362017-11-03 22:48:23 -07005862 pr_debug("%s: data[%pK], phys[%pK], dma_buf[%pK]\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305863 __func__,
5864 port->buf[0].data,
5865 &port->buf[0].phys,
Banajit Goswami08bb7362017-11-03 22:48:23 -07005866 port->buf[0].dma_buf);
5867 msm_audio_ion_free(port->buf[0].dma_buf);
5868 port->buf[0].dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305869 }
5870
5871 while (cnt >= 0) {
5872 port->buf[cnt].data = NULL;
5873 port->buf[cnt].phys = 0;
5874 cnt--;
5875 }
5876 port->max_buf_cnt = 0;
5877 kfree(port->buf);
5878 port->buf = NULL;
5879 mutex_unlock(&ac->cmd_lock);
5880 return 0;
5881}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305882EXPORT_SYMBOL(q6afe_audio_client_buf_free_contiguous);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305883
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305884/**
5885 * q6afe_audio_client_free -
5886 * frees the audio client from AFE
5887 *
5888 * @ac: AFE audio client handle
5889 *
5890 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305891void q6afe_audio_client_free(struct afe_audio_client *ac)
5892{
5893 int loopcnt;
5894 struct afe_audio_port_data *port;
5895
5896 if (!ac) {
5897 pr_err("%s: audio client is NULL\n", __func__);
5898 return;
5899 }
5900 for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
5901 port = &ac->port[loopcnt];
5902 if (!port->buf)
5903 continue;
5904 pr_debug("%s: loopcnt = %d\n", __func__, loopcnt);
5905 q6afe_audio_client_buf_free_contiguous(loopcnt, ac);
5906 }
5907 kfree(ac);
5908}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305909EXPORT_SYMBOL(q6afe_audio_client_free);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305910
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305911/**
5912 * afe_cmd_memory_unmap -
5913 * command to unmap memory for AFE shared buffer
5914 *
5915 * @mem_map_handle: memory map handle to be unmapped
5916 *
5917 * Returns 0 on success or error on failure
5918 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305919int afe_cmd_memory_unmap(u32 mem_map_handle)
5920{
5921 int ret = 0;
5922 struct afe_service_cmd_shared_mem_unmap_regions mregion;
5923 int index = 0;
5924
5925 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
5926
5927 if (this_afe.apr == NULL) {
5928 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5929 0xFFFFFFFF, &this_afe);
5930 pr_debug("%s: Register AFE\n", __func__);
5931 if (this_afe.apr == NULL) {
5932 pr_err("%s: Unable to register AFE\n", __func__);
5933 ret = -ENODEV;
5934 return ret;
5935 }
5936 rtac_set_afe_handle(this_afe.apr);
5937 }
5938
5939 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5940 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5941 mregion.hdr.pkt_size = sizeof(mregion);
5942 mregion.hdr.src_port = 0;
5943 mregion.hdr.dest_port = 0;
5944 mregion.hdr.token = 0;
5945 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
5946 mregion.mem_map_handle = mem_map_handle;
5947
5948 /* Todo */
5949 index = mregion.hdr.token = IDX_RSVD_2;
5950
5951 atomic_set(&this_afe.status, 0);
5952 ret = afe_apr_send_pkt(&mregion, &this_afe.wait[index]);
5953 if (ret)
5954 pr_err("%s: AFE memory unmap cmd failed %d\n",
5955 __func__, ret);
5956
5957 return ret;
5958}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305959EXPORT_SYMBOL(afe_cmd_memory_unmap);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305960
5961int afe_cmd_memory_unmap_nowait(u32 mem_map_handle)
5962{
5963 int ret = 0;
5964 struct afe_service_cmd_shared_mem_unmap_regions mregion;
5965
5966 pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
5967
5968 if (this_afe.apr == NULL) {
5969 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
5970 0xFFFFFFFF, &this_afe);
5971 pr_debug("%s: Register AFE\n", __func__);
5972 if (this_afe.apr == NULL) {
5973 pr_err("%s: Unable to register AFE\n", __func__);
5974 ret = -ENODEV;
5975 return ret;
5976 }
5977 rtac_set_afe_handle(this_afe.apr);
5978 }
5979
5980 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5981 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5982 mregion.hdr.pkt_size = sizeof(mregion);
5983 mregion.hdr.src_port = 0;
5984 mregion.hdr.dest_port = 0;
5985 mregion.hdr.token = 0;
5986 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
5987 mregion.mem_map_handle = mem_map_handle;
5988
5989 ret = afe_apr_send_pkt(&mregion, NULL);
5990 if (ret)
5991 pr_err("%s: AFE memory unmap cmd failed %d\n",
5992 __func__, ret);
5993 return ret;
5994}
5995
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305996/**
5997 * afe_register_get_events -
5998 * register for events from proxy port
5999 *
6000 * @port_id: Port ID to register events
6001 * @cb: callback function to invoke for events from proxy port
6002 * @private_data: private data to sent back in callback fn
6003 *
6004 * Returns 0 on success or error on failure
6005 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306006int afe_register_get_events(u16 port_id,
6007 void (*cb)(uint32_t opcode,
6008 uint32_t token, uint32_t *payload, void *priv),
6009 void *private_data)
6010{
6011 int ret = 0;
6012 struct afe_service_cmd_register_rt_port_driver rtproxy;
6013
6014 pr_debug("%s: port_id: 0x%x\n", __func__, port_id);
6015
6016 if (this_afe.apr == NULL) {
6017 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
6018 0xFFFFFFFF, &this_afe);
6019 pr_debug("%s: Register AFE\n", __func__);
6020 if (this_afe.apr == NULL) {
6021 pr_err("%s: Unable to register AFE\n", __func__);
6022 ret = -ENODEV;
6023 return ret;
6024 }
6025 rtac_set_afe_handle(this_afe.apr);
6026 }
6027 if ((port_id == RT_PROXY_DAI_002_RX) ||
6028 (port_id == RT_PROXY_DAI_001_TX)) {
6029 port_id = VIRTUAL_ID_TO_PORTID(port_id);
6030 } else {
6031 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
6032 return -EINVAL;
6033 }
6034
6035 if (port_id == RT_PROXY_PORT_001_TX) {
6036 this_afe.tx_cb = cb;
6037 this_afe.tx_private_data = private_data;
6038 } else if (port_id == RT_PROXY_PORT_001_RX) {
6039 this_afe.rx_cb = cb;
6040 this_afe.rx_private_data = private_data;
6041 }
6042
6043 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6044 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6045 rtproxy.hdr.pkt_size = sizeof(rtproxy);
6046 rtproxy.hdr.src_port = 1;
6047 rtproxy.hdr.dest_port = 1;
6048 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER;
6049 rtproxy.port_id = port_id;
6050 rtproxy.reserved = 0;
6051
6052 ret = afe_apr_send_pkt(&rtproxy, NULL);
6053 if (ret)
6054 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
6055 __func__, ret);
6056 return ret;
6057}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306058EXPORT_SYMBOL(afe_register_get_events);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306059
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306060/**
6061 * afe_unregister_get_events -
6062 * unregister for events from proxy port
6063 *
6064 * @port_id: Port ID to unregister events
6065 *
6066 * Returns 0 on success or error on failure
6067 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306068int afe_unregister_get_events(u16 port_id)
6069{
6070 int ret = 0;
6071 struct afe_service_cmd_unregister_rt_port_driver rtproxy;
6072 int index = 0;
6073
6074 pr_debug("%s:\n", __func__);
6075
6076 if (this_afe.apr == NULL) {
6077 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
6078 0xFFFFFFFF, &this_afe);
6079 pr_debug("%s: Register AFE\n", __func__);
6080 if (this_afe.apr == NULL) {
6081 pr_err("%s: Unable to register AFE\n", __func__);
6082 ret = -ENODEV;
6083 return ret;
6084 }
6085 rtac_set_afe_handle(this_afe.apr);
6086 }
6087
6088 if ((port_id == RT_PROXY_DAI_002_RX) ||
6089 (port_id == RT_PROXY_DAI_001_TX)) {
6090 port_id = VIRTUAL_ID_TO_PORTID(port_id);
6091 } else {
6092 pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
6093 return -EINVAL;
6094 }
6095
6096 index = q6audio_get_port_index(port_id);
6097 if (index < 0 || index >= AFE_MAX_PORTS) {
6098 pr_err("%s: AFE port index[%d] invalid!\n",
6099 __func__, index);
6100 return -EINVAL;
6101 }
6102 ret = q6audio_validate_port(port_id);
6103 if (ret < 0) {
6104 pr_err("%s: Invalid port 0x%x ret %d", __func__, port_id, ret);
6105 return -EINVAL;
6106 }
6107
6108 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6109 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6110 rtproxy.hdr.pkt_size = sizeof(rtproxy);
6111 rtproxy.hdr.src_port = 0;
6112 rtproxy.hdr.dest_port = 0;
6113 rtproxy.hdr.token = 0;
6114 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER;
6115 rtproxy.port_id = port_id;
6116 rtproxy.reserved = 0;
6117
6118 rtproxy.hdr.token = index;
6119
6120 if (port_id == RT_PROXY_PORT_001_TX) {
6121 this_afe.tx_cb = NULL;
6122 this_afe.tx_private_data = NULL;
6123 } else if (port_id == RT_PROXY_PORT_001_RX) {
6124 this_afe.rx_cb = NULL;
6125 this_afe.rx_private_data = NULL;
6126 }
6127
6128 ret = afe_apr_send_pkt(&rtproxy, &this_afe.wait[index]);
6129 if (ret)
6130 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
6131 __func__, ret);
6132 return ret;
6133}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306134EXPORT_SYMBOL(afe_unregister_get_events);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306135
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306136/**
6137 * afe_rt_proxy_port_write -
6138 * command for AFE RT proxy port write
6139 *
6140 * @buf_addr_p: Physical buffer address with
6141 * playback data to proxy port
6142 * @mem_map_handle: memory map handle of write buffer
6143 * @bytes: number of bytes to write
6144 *
6145 * Returns 0 on success or error on failure
6146 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306147int afe_rt_proxy_port_write(phys_addr_t buf_addr_p,
6148 u32 mem_map_handle, int bytes)
6149{
6150 int ret = 0;
6151 struct afe_port_data_cmd_rt_proxy_port_write_v2 afecmd_wr;
6152
6153 if (this_afe.apr == NULL) {
6154 pr_err("%s: register to AFE is not done\n", __func__);
6155 ret = -ENODEV;
6156 return ret;
6157 }
6158 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
6159 &buf_addr_p, bytes);
6160
6161 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6162 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6163 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
6164 afecmd_wr.hdr.src_port = 0;
6165 afecmd_wr.hdr.dest_port = 0;
6166 afecmd_wr.hdr.token = 0;
6167 afecmd_wr.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2;
6168 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
6169 afecmd_wr.buffer_address_lsw = lower_32_bits(buf_addr_p);
6170 afecmd_wr.buffer_address_msw =
6171 msm_audio_populate_upper_32_bits(buf_addr_p);
6172 afecmd_wr.mem_map_handle = mem_map_handle;
6173 afecmd_wr.available_bytes = bytes;
6174 afecmd_wr.reserved = 0;
6175
6176 ret = afe_apr_send_pkt(&afecmd_wr, NULL);
6177 if (ret)
6178 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
6179 __func__, afecmd_wr.port_id, ret);
6180 return ret;
6181
6182}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306183EXPORT_SYMBOL(afe_rt_proxy_port_write);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306184
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306185/**
6186 * afe_rt_proxy_port_read -
6187 * command for AFE RT proxy port read
6188 *
6189 * @buf_addr_p: Physical buffer address to fill read data
6190 * @mem_map_handle: memory map handle for buffer read
6191 * @bytes: number of bytes to read
6192 *
6193 * Returns 0 on success or error on failure
6194 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306195int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
6196 u32 mem_map_handle, int bytes)
6197{
6198 int ret = 0;
6199 struct afe_port_data_cmd_rt_proxy_port_read_v2 afecmd_rd;
6200
6201 if (this_afe.apr == NULL) {
6202 pr_err("%s: register to AFE is not done\n", __func__);
6203 ret = -ENODEV;
6204 return ret;
6205 }
6206 pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__,
6207 &buf_addr_p, bytes);
6208
6209 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6210 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6211 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
6212 afecmd_rd.hdr.src_port = 0;
6213 afecmd_rd.hdr.dest_port = 0;
6214 afecmd_rd.hdr.token = 0;
6215 afecmd_rd.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2;
6216 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
6217 afecmd_rd.buffer_address_lsw = lower_32_bits(buf_addr_p);
6218 afecmd_rd.buffer_address_msw =
6219 msm_audio_populate_upper_32_bits(buf_addr_p);
6220 afecmd_rd.available_bytes = bytes;
6221 afecmd_rd.mem_map_handle = mem_map_handle;
6222
6223 ret = afe_apr_send_pkt(&afecmd_rd, NULL);
6224 if (ret)
6225 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
6226 __func__, afecmd_rd.port_id, ret);
6227 return ret;
6228}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306229EXPORT_SYMBOL(afe_rt_proxy_port_read);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306230
6231#ifdef CONFIG_DEBUG_FS
6232static struct dentry *debugfs_afelb;
6233static struct dentry *debugfs_afelb_gain;
6234
6235static int afe_debug_open(struct inode *inode, struct file *file)
6236{
6237 file->private_data = inode->i_private;
6238 pr_info("%s: debug intf %s\n", __func__, (char *) file->private_data);
6239 return 0;
6240}
6241
6242static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
6243{
6244 char *token;
6245 int base, cnt;
6246
6247 token = strsep(&buf, " ");
6248
6249 for (cnt = 0; cnt < num_of_par; cnt++) {
6250 if (token != NULL) {
6251 if ((token[1] == 'x') || (token[1] == 'X'))
6252 base = 16;
6253 else
6254 base = 10;
6255
6256 if (kstrtoul(token, base, &param1[cnt]) != 0) {
6257 pr_err("%s: kstrtoul failed\n",
6258 __func__);
6259 return -EINVAL;
6260 }
6261
6262 token = strsep(&buf, " ");
6263 } else {
6264 pr_err("%s: token NULL\n", __func__);
6265 return -EINVAL;
6266 }
6267 }
6268 return 0;
6269}
6270#define AFE_LOOPBACK_ON (1)
6271#define AFE_LOOPBACK_OFF (0)
6272static ssize_t afe_debug_write(struct file *filp,
6273 const char __user *ubuf, size_t cnt, loff_t *ppos)
6274{
6275 char *lb_str = filp->private_data;
6276 char lbuf[32];
6277 int rc;
6278 unsigned long param[5];
6279
6280 if (cnt > sizeof(lbuf) - 1) {
6281 pr_err("%s: cnt %zd size %zd\n", __func__, cnt, sizeof(lbuf)-1);
6282 return -EINVAL;
6283 }
6284
6285 rc = copy_from_user(lbuf, ubuf, cnt);
6286 if (rc) {
6287 pr_err("%s: copy from user failed %d\n", __func__, rc);
6288 return -EFAULT;
6289 }
6290
6291 lbuf[cnt] = '\0';
6292
6293 if (!strcmp(lb_str, "afe_loopback")) {
6294 rc = afe_get_parameters(lbuf, param, 3);
6295 if (!rc) {
6296 pr_info("%s: %lu %lu %lu\n", lb_str, param[0], param[1],
6297 param[2]);
6298
6299 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
6300 AFE_LOOPBACK_OFF)) {
6301 pr_err("%s: Error, parameter 0 incorrect\n",
6302 __func__);
6303 rc = -EINVAL;
6304 goto afe_error;
6305 }
6306 if ((q6audio_validate_port(param[1]) < 0) ||
6307 (q6audio_validate_port(param[2])) < 0) {
6308 pr_err("%s: Error, invalid afe port\n",
6309 __func__);
6310 }
6311 if (this_afe.apr == NULL) {
6312 pr_err("%s: Error, AFE not opened\n", __func__);
6313 rc = -EINVAL;
6314 } else {
6315 rc = afe_loopback(param[0], param[1], param[2]);
6316 }
6317 } else {
6318 pr_err("%s: Error, invalid parameters\n", __func__);
6319 rc = -EINVAL;
6320 }
6321
6322 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
6323 rc = afe_get_parameters(lbuf, param, 2);
6324 if (!rc) {
6325 pr_info("%s: %s %lu %lu\n",
6326 __func__, lb_str, param[0], param[1]);
6327
6328 rc = q6audio_validate_port(param[0]);
6329 if (rc < 0) {
6330 pr_err("%s: Error, invalid afe port %d %lu\n",
6331 __func__, rc, param[0]);
6332 rc = -EINVAL;
6333 goto afe_error;
6334 }
6335
6336 if (param[1] > 100) {
6337 pr_err("%s: Error, volume should be 0 to 100 percentage param = %lu\n",
6338 __func__, param[1]);
6339 rc = -EINVAL;
6340 goto afe_error;
6341 }
6342
6343 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
6344
6345 if (this_afe.apr == NULL) {
6346 pr_err("%s: Error, AFE not opened\n", __func__);
6347 rc = -EINVAL;
6348 } else {
6349 rc = afe_loopback_gain(param[0], param[1]);
6350 }
6351 } else {
6352 pr_err("%s: Error, invalid parameters\n", __func__);
6353 rc = -EINVAL;
6354 }
6355 }
6356
6357afe_error:
6358 if (rc == 0)
6359 rc = cnt;
6360 else
6361 pr_err("%s: rc = %d\n", __func__, rc);
6362
6363 return rc;
6364}
6365
6366static const struct file_operations afe_debug_fops = {
6367 .open = afe_debug_open,
6368 .write = afe_debug_write
6369};
6370
6371static void config_debug_fs_init(void)
6372{
6373 debugfs_afelb = debugfs_create_file("afe_loopback",
6374 0664, NULL, (void *) "afe_loopback",
6375 &afe_debug_fops);
6376
6377 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
6378 0664, NULL, (void *) "afe_loopback_gain",
6379 &afe_debug_fops);
6380}
6381static void config_debug_fs_exit(void)
6382{
6383 debugfs_remove(debugfs_afelb);
6384 debugfs_remove(debugfs_afelb_gain);
6385}
6386#else
6387static void config_debug_fs_init(void)
6388{
6389}
6390static void config_debug_fs_exit(void)
6391{
6392}
6393#endif
6394
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306395/**
6396 * afe_set_dtmf_gen_rx_portid -
6397 * Set port_id for DTMF tone generation
6398 *
6399 * @port_id: AFE port id
6400 * @set: set or reset port id value for dtmf gen
6401 *
6402 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306403void afe_set_dtmf_gen_rx_portid(u16 port_id, int set)
6404{
6405 if (set)
6406 this_afe.dtmf_gen_rx_portid = port_id;
6407 else if (this_afe.dtmf_gen_rx_portid == port_id)
6408 this_afe.dtmf_gen_rx_portid = -1;
6409}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306410EXPORT_SYMBOL(afe_set_dtmf_gen_rx_portid);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306411
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306412/**
6413 * afe_dtmf_generate_rx - command to generate AFE DTMF RX
6414 *
6415 * @duration_in_ms: Duration in ms for dtmf tone
6416 * @high_freq: Higher frequency for dtmf
6417 * @low_freq: lower frequency for dtmf
6418 * @gain: Gain value for DTMF tone
6419 *
6420 * Returns 0 on success, appropriate error code otherwise
6421 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306422int afe_dtmf_generate_rx(int64_t duration_in_ms,
6423 uint16_t high_freq,
6424 uint16_t low_freq, uint16_t gain)
6425{
6426 int ret = 0;
6427 int index = 0;
6428 struct afe_dtmf_generation_command cmd_dtmf;
6429
6430 pr_debug("%s: DTMF AFE Gen\n", __func__);
6431
6432 if (afe_validate_port(this_afe.dtmf_gen_rx_portid) < 0) {
6433 pr_err("%s: Failed : Invalid Port id = 0x%x\n",
6434 __func__, this_afe.dtmf_gen_rx_portid);
6435 ret = -EINVAL;
6436 goto fail_cmd;
6437 }
6438
6439 if (this_afe.apr == NULL) {
6440 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
6441 0xFFFFFFFF, &this_afe);
6442 pr_debug("%s: Register AFE\n", __func__);
6443 if (this_afe.apr == NULL) {
6444 pr_err("%s: Unable to register AFE\n", __func__);
6445 ret = -ENODEV;
6446 return ret;
6447 }
6448 rtac_set_afe_handle(this_afe.apr);
6449 }
6450
6451 pr_debug("%s: dur=%lld: hfreq=%d lfreq=%d gain=%d portid=0x%x\n",
6452 __func__,
6453 duration_in_ms, high_freq, low_freq, gain,
6454 this_afe.dtmf_gen_rx_portid);
6455
6456 cmd_dtmf.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6457 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6458 cmd_dtmf.hdr.pkt_size = sizeof(cmd_dtmf);
6459 cmd_dtmf.hdr.src_port = 0;
6460 cmd_dtmf.hdr.dest_port = 0;
6461 cmd_dtmf.hdr.token = 0;
6462 cmd_dtmf.hdr.opcode = AFE_PORTS_CMD_DTMF_CTL;
6463 cmd_dtmf.duration_in_ms = duration_in_ms;
6464 cmd_dtmf.high_freq = high_freq;
6465 cmd_dtmf.low_freq = low_freq;
6466 cmd_dtmf.gain = gain;
6467 cmd_dtmf.num_ports = 1;
6468 cmd_dtmf.port_ids = q6audio_get_port_id(this_afe.dtmf_gen_rx_portid);
6469
6470 atomic_set(&this_afe.state, 1);
6471 atomic_set(&this_afe.status, 0);
6472 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_dtmf);
6473 if (ret < 0) {
6474 pr_err("%s: AFE DTMF failed for num_ports:%d ids:0x%x\n",
6475 __func__, cmd_dtmf.num_ports, cmd_dtmf.port_ids);
6476 ret = -EINVAL;
6477 goto fail_cmd;
6478 }
6479 index = q6audio_get_port_index(this_afe.dtmf_gen_rx_portid);
6480 if (index < 0 || index >= AFE_MAX_PORTS) {
6481 pr_err("%s: AFE port index[%d] invalid!\n",
6482 __func__, index);
6483 ret = -EINVAL;
6484 goto fail_cmd;
6485 }
6486 ret = wait_event_timeout(this_afe.wait[index],
6487 (atomic_read(&this_afe.state) == 0),
6488 msecs_to_jiffies(TIMEOUT_MS));
6489 if (!ret) {
6490 pr_err("%s: wait_event timeout\n", __func__);
6491 ret = -EINVAL;
6492 goto fail_cmd;
6493 }
6494 if (atomic_read(&this_afe.status) > 0) {
6495 pr_err("%s: config cmd failed [%s]\n",
6496 __func__, adsp_err_get_err_str(
6497 atomic_read(&this_afe.status)));
6498 ret = adsp_err_get_lnx_err_code(
6499 atomic_read(&this_afe.status));
6500 goto fail_cmd;
6501 }
6502 return 0;
6503
6504fail_cmd:
6505 pr_err("%s: failed %d\n", __func__, ret);
6506 return ret;
6507}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306508EXPORT_SYMBOL(afe_dtmf_generate_rx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306509
6510static int afe_sidetone_iir(u16 tx_port_id)
6511{
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306512 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306513 uint16_t size = 0;
6514 int cal_index = AFE_SIDETONE_IIR_CAL;
6515 int iir_pregain = 0;
6516 int iir_num_biquad_stages = 0;
6517 int iir_enable;
6518 struct cal_block_data *cal_block;
6519 int mid;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006520 struct afe_mod_enable_param enable;
6521 struct afe_sidetone_iir_filter_config_params filter_data;
6522 struct param_hdr_v3 param_hdr;
6523 u8 *packed_param_data = NULL;
6524 u32 packed_param_size = 0;
6525 u32 single_param_size = 0;
6526 struct audio_cal_info_sidetone_iir *st_iir_cal_info = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306527
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006528 memset(&enable, 0, sizeof(enable));
6529 memset(&filter_data, 0, sizeof(filter_data));
6530 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306531
6532 if (this_afe.cal_data[cal_index] == NULL) {
6533 pr_err("%s: cal data is NULL\n", __func__);
6534 ret = -EINVAL;
6535 goto done;
6536 }
6537 mutex_lock(&this_afe.cal_data[cal_index]->lock);
6538 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07006539 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306540 pr_err("%s: cal_block not found\n ", __func__);
6541 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
6542 ret = -EINVAL;
6543 goto done;
6544 }
6545
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006546 /* Cache data from cal block while inside lock to reduce locked time */
6547 st_iir_cal_info =
6548 (struct audio_cal_info_sidetone_iir *) cal_block->cal_info;
6549 iir_pregain = st_iir_cal_info->pregain;
6550 iir_enable = st_iir_cal_info->iir_enable;
6551 iir_num_biquad_stages = st_iir_cal_info->num_biquad_stages;
6552 mid = st_iir_cal_info->mid;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306553
6554 /*
6555 * calculate the actual size of payload based on no of stages
6556 * enabled in calibration
6557 */
6558 size = (MAX_SIDETONE_IIR_DATA_SIZE / MAX_NO_IIR_FILTER_STAGE) *
6559 iir_num_biquad_stages;
6560 /*
6561 * For an odd number of stages, 2 bytes of padding are
6562 * required at the end of the payload.
6563 */
6564 if (iir_num_biquad_stages % 2) {
6565 pr_debug("%s: adding 2 to size:%d\n", __func__, size);
6566 size = size + 2;
6567 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006568 memcpy(&filter_data.iir_config, &st_iir_cal_info->iir_config, size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306569 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
6570
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006571 packed_param_size =
6572 sizeof(param_hdr) * 2 + sizeof(enable) + sizeof(filter_data);
6573 packed_param_data = kzalloc(packed_param_size, GFP_KERNEL);
6574 if (!packed_param_data)
6575 return -ENOMEM;
6576 packed_param_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306577
6578 /*
6579 * Set IIR enable params
6580 */
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006581 param_hdr.module_id = mid;
6582 param_hdr.param_id = INSTANCE_ID_0;
6583 param_hdr.param_id = AFE_PARAM_ID_ENABLE;
6584 param_hdr.param_size = sizeof(enable);
6585 enable.enable = iir_enable;
6586 ret = q6common_pack_pp_params(packed_param_data, &param_hdr,
6587 (u8 *) &enable, &single_param_size);
6588 if (ret) {
6589 pr_err("%s: Failed to pack param data, error %d\n", __func__,
6590 ret);
6591 goto done;
6592 }
6593 packed_param_size += single_param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306594
6595 /*
6596 * Set IIR filter config params
6597 */
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006598 param_hdr.module_id = mid;
6599 param_hdr.instance_id = INSTANCE_ID_0;
6600 param_hdr.param_id = AFE_PARAM_ID_SIDETONE_IIR_FILTER_CONFIG;
6601 param_hdr.param_size = sizeof(filter_data.num_biquad_stages) +
6602 sizeof(filter_data.pregain) + size;
6603 filter_data.num_biquad_stages = iir_num_biquad_stages;
6604 filter_data.pregain = iir_pregain;
6605 ret = q6common_pack_pp_params(packed_param_data + packed_param_size,
6606 &param_hdr, (u8 *) &filter_data,
6607 &single_param_size);
6608 if (ret) {
6609 pr_err("%s: Failed to pack param data, error %d\n", __func__,
6610 ret);
6611 goto done;
6612 }
6613 packed_param_size += single_param_size;
6614
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306615 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 -08006616 __func__, tx_port_id, mid, enable.enable,
6617 filter_data.num_biquad_stages, filter_data.pregain,
6618 param_hdr.param_size);
6619
6620 ret = q6afe_set_params(tx_port_id, q6audio_get_port_index(tx_port_id),
6621 NULL, packed_param_data, packed_param_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306622 if (ret)
6623 pr_err("%s: AFE sidetone failed for tx_port(0x%x)\n",
6624 __func__, tx_port_id);
6625
6626done:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006627 kfree(packed_param_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306628 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306629}
6630
6631static int afe_sidetone(u16 tx_port_id, u16 rx_port_id, bool enable)
6632{
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306633 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306634 int cal_index = AFE_SIDETONE_CAL;
6635 int sidetone_gain;
6636 int sidetone_enable;
6637 struct cal_block_data *cal_block;
6638 int mid = 0;
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006639 struct afe_loopback_sidetone_gain gain_data;
6640 struct loopback_cfg_data cfg_data;
6641 struct param_hdr_v3 param_hdr;
6642 u8 *packed_param_data = NULL;
6643 u32 packed_param_size = 0;
6644 u32 single_param_size = 0;
6645 struct audio_cal_info_sidetone *st_cal_info = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306646
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306647 if (this_afe.cal_data[cal_index] == NULL) {
6648 pr_err("%s: cal data is NULL\n", __func__);
6649 ret = -EINVAL;
6650 goto done;
6651 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006652
6653 memset(&gain_data, 0, sizeof(gain_data));
6654 memset(&cfg_data, 0, sizeof(cfg_data));
6655 memset(&param_hdr, 0, sizeof(param_hdr));
6656
6657 packed_param_size =
6658 sizeof(param_hdr) * 2 + sizeof(gain_data) + sizeof(cfg_data);
6659 packed_param_data = kzalloc(packed_param_size, GFP_KERNEL);
6660 if (!packed_param_data)
6661 return -ENOMEM;
6662 packed_param_size = 0;
6663
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306664 mutex_lock(&this_afe.cal_data[cal_index]->lock);
6665 cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07006666 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306667 pr_err("%s: cal_block not found\n", __func__);
6668 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
6669 ret = -EINVAL;
6670 goto done;
6671 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006672
6673 /* Cache data from cal block while inside lock to reduce locked time */
6674 st_cal_info = (struct audio_cal_info_sidetone *) cal_block->cal_info;
6675 sidetone_gain = st_cal_info->gain;
6676 sidetone_enable = st_cal_info->enable;
6677 mid = st_cal_info->mid;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306678 mutex_unlock(&this_afe.cal_data[cal_index]->lock);
6679
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006680 /* Set gain data. */
6681 param_hdr.module_id = AFE_MODULE_LOOPBACK;
6682 param_hdr.instance_id = INSTANCE_ID_0;
6683 param_hdr.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
6684 param_hdr.param_size = sizeof(struct afe_loopback_sidetone_gain);
6685 gain_data.rx_port_id = rx_port_id;
6686 gain_data.gain = sidetone_gain;
6687 ret = q6common_pack_pp_params(packed_param_data, &param_hdr,
6688 (u8 *) &gain_data, &single_param_size);
6689 if (ret) {
6690 pr_err("%s: Failed to pack param data, error %d\n", __func__,
6691 ret);
6692 goto done;
6693 }
6694 packed_param_size += single_param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306695
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006696 /* Set configuration data. */
6697 param_hdr.module_id = AFE_MODULE_LOOPBACK;
6698 param_hdr.instance_id = INSTANCE_ID_0;
6699 param_hdr.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
6700 param_hdr.param_size = sizeof(struct loopback_cfg_data);
6701 cfg_data.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
6702 cfg_data.dst_port_id = rx_port_id;
6703 cfg_data.routing_mode = LB_MODE_SIDETONE;
6704 cfg_data.enable = enable;
6705 ret = q6common_pack_pp_params(packed_param_data + packed_param_size,
6706 &param_hdr, (u8 *) &cfg_data,
6707 &single_param_size);
6708 if (ret) {
6709 pr_err("%s: Failed to pack param data, error %d\n", __func__,
6710 ret);
6711 goto done;
6712 }
6713 packed_param_size += single_param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306714
6715 pr_debug("%s rx(0x%x) tx(0x%x) enable(%d) mid(0x%x) gain(%d) sidetone_enable(%d)\n",
6716 __func__, rx_port_id, tx_port_id,
6717 enable, mid, sidetone_gain, sidetone_enable);
6718
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006719 ret = q6afe_set_params(tx_port_id, q6audio_get_port_index(tx_port_id),
6720 NULL, packed_param_data, packed_param_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306721 if (ret)
6722 pr_err("%s: AFE sidetone send failed for tx_port:%d rx_port:%d ret:%d\n",
6723 __func__, tx_port_id, rx_port_id, ret);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006724
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306725done:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08006726 kfree(packed_param_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306727 return ret;
6728}
6729
6730int afe_sidetone_enable(u16 tx_port_id, u16 rx_port_id, bool enable)
6731{
6732 int ret;
6733 int index;
6734
6735 index = q6audio_get_port_index(rx_port_id);
6736 if (index < 0 || index >= AFE_MAX_PORTS) {
6737 pr_err("%s: AFE port index[%d] invalid!\n",
6738 __func__, index);
6739 ret = -EINVAL;
6740 goto done;
6741 }
6742 if (q6audio_validate_port(rx_port_id) < 0) {
6743 pr_err("%s: Invalid port 0x%x\n",
6744 __func__, rx_port_id);
6745 ret = -EINVAL;
6746 goto done;
6747 }
6748 index = q6audio_get_port_index(tx_port_id);
6749 if (index < 0 || index >= AFE_MAX_PORTS) {
6750 pr_err("%s: AFE port index[%d] invalid!\n",
6751 __func__, index);
6752 ret = -EINVAL;
6753 goto done;
6754 }
6755 if (q6audio_validate_port(tx_port_id) < 0) {
6756 pr_err("%s: Invalid port 0x%x\n",
6757 __func__, tx_port_id);
6758 ret = -EINVAL;
6759 goto done;
6760 }
6761 if (enable) {
6762 ret = afe_sidetone_iir(tx_port_id);
6763 if (ret)
6764 goto done;
6765 }
6766
6767 ret = afe_sidetone(tx_port_id, rx_port_id, enable);
6768
6769done:
6770 return ret;
6771}
6772
Karthikeyan Mani16b69722018-05-03 18:26:21 -07006773/**
6774 * afe_set_display_stream - command to update AFE dp port params
6775 *
6776 * @rx_port_id: AFE port id
6777 * @stream_idx: dp controller stream index
6778 * @ctl_idx: dp controller index
6779 *
6780 * Returns 0 on success, appropriate error code otherwise
6781 */
6782int afe_set_display_stream(u16 rx_port_id, u32 stream_idx, u32 ctl_idx)
6783{
6784 int ret;
6785 struct param_hdr_v3 param_hdr;
6786 u32 packed_param_size = 0;
6787 u8 *packed_param_data = NULL;
6788 struct afe_display_stream_idx stream_data;
6789 struct afe_display_ctl_idx ctl_data;
6790 u32 single_param_size = 0;
6791
6792 memset(&param_hdr, 0, sizeof(param_hdr));
6793 memset(&stream_data, 0, sizeof(stream_data));
6794 memset(&ctl_data, 0, sizeof(ctl_data));
6795
6796 packed_param_size =
6797 sizeof(param_hdr) * 2 + sizeof(stream_data) + sizeof(ctl_data);
6798 packed_param_data = kzalloc(packed_param_size, GFP_KERNEL);
6799 if (!packed_param_data)
6800 return -ENOMEM;
6801 packed_param_size = 0;
6802
6803 /* Set stream index */
6804 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6805 param_hdr.instance_id = INSTANCE_ID_0;
6806 param_hdr.param_id = AFE_PARAM_ID_HDMI_DP_MST_VID_IDX_CFG;
6807 param_hdr.param_size = sizeof(struct afe_display_stream_idx);
6808 stream_data.minor_version = 1;
6809 stream_data.stream_idx = stream_idx;
6810 ret = q6common_pack_pp_params(packed_param_data, &param_hdr,
6811 (u8 *) &stream_data, &single_param_size);
6812 if (ret) {
6813 pr_err("%s: Failed to pack param data, error %d\n", __func__,
6814 ret);
6815 goto done;
6816 }
6817 packed_param_size += single_param_size;
6818
6819 /* Set controller dptx index */
6820 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
6821 param_hdr.instance_id = INSTANCE_ID_0;
6822 param_hdr.param_id = AFE_PARAM_ID_HDMI_DPTX_IDX_CFG;
6823 param_hdr.param_size = sizeof(struct afe_display_ctl_idx);
6824 ctl_data.minor_version = 1;
6825 ctl_data.ctl_idx = ctl_idx;
6826 ret = q6common_pack_pp_params(packed_param_data + packed_param_size,
6827 &param_hdr, (u8 *) &ctl_data,
6828 &single_param_size);
6829 if (ret) {
6830 pr_err("%s: Failed to pack param data, error %d\n", __func__,
6831 ret);
6832 goto done;
6833 }
6834 packed_param_size += single_param_size;
6835
6836 pr_debug("%s: rx(0x%x) stream(%d) controller(%d)\n",
6837 __func__, rx_port_id, stream_idx, ctl_idx);
6838
6839 ret = q6afe_set_params(rx_port_id, q6audio_get_port_index(rx_port_id),
6840 NULL, packed_param_data, packed_param_size);
6841 if (ret)
6842 pr_err("%s: AFE display stream send failed for rx_port:%d ret:%d\n",
6843 __func__, rx_port_id, ret);
6844
6845done:
6846 kfree(packed_param_data);
6847 return ret;
6848
6849}
6850EXPORT_SYMBOL(afe_set_display_stream);
6851
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306852int afe_validate_port(u16 port_id)
6853{
6854 int ret;
6855
6856 switch (port_id) {
6857 case PRIMARY_I2S_RX:
6858 case PRIMARY_I2S_TX:
6859 case AFE_PORT_ID_PRIMARY_PCM_RX:
6860 case AFE_PORT_ID_PRIMARY_PCM_TX:
6861 case AFE_PORT_ID_SECONDARY_PCM_RX:
6862 case AFE_PORT_ID_SECONDARY_PCM_TX:
6863 case AFE_PORT_ID_TERTIARY_PCM_RX:
6864 case AFE_PORT_ID_TERTIARY_PCM_TX:
6865 case AFE_PORT_ID_QUATERNARY_PCM_RX:
6866 case AFE_PORT_ID_QUATERNARY_PCM_TX:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05306867 case AFE_PORT_ID_QUINARY_PCM_RX:
6868 case AFE_PORT_ID_QUINARY_PCM_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306869 case SECONDARY_I2S_RX:
6870 case SECONDARY_I2S_TX:
6871 case MI2S_RX:
6872 case MI2S_TX:
6873 case HDMI_RX:
6874 case DISPLAY_PORT_RX:
Ralf Herzcc29b9e2018-07-17 20:19:04 +05306875 case AFE_PORT_ID_PRIMARY_SPDIF_RX:
6876 case AFE_PORT_ID_PRIMARY_SPDIF_TX:
6877 case AFE_PORT_ID_SECONDARY_SPDIF_RX:
6878 case AFE_PORT_ID_SECONDARY_SPDIF_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306879 case RSVD_2:
6880 case RSVD_3:
6881 case DIGI_MIC_TX:
6882 case VOICE_RECORD_RX:
6883 case VOICE_RECORD_TX:
6884 case VOICE_PLAYBACK_TX:
6885 case VOICE2_PLAYBACK_TX:
6886 case SLIMBUS_0_RX:
6887 case SLIMBUS_0_TX:
6888 case SLIMBUS_1_RX:
6889 case SLIMBUS_1_TX:
6890 case SLIMBUS_2_RX:
6891 case SLIMBUS_2_TX:
6892 case SLIMBUS_3_RX:
6893 case INT_BT_SCO_RX:
6894 case INT_BT_SCO_TX:
6895 case INT_BT_A2DP_RX:
6896 case INT_FM_RX:
6897 case INT_FM_TX:
6898 case RT_PROXY_PORT_001_RX:
6899 case RT_PROXY_PORT_001_TX:
6900 case SLIMBUS_4_RX:
6901 case SLIMBUS_4_TX:
6902 case SLIMBUS_5_RX:
6903 case SLIMBUS_6_RX:
6904 case SLIMBUS_6_TX:
6905 case SLIMBUS_7_RX:
6906 case SLIMBUS_7_TX:
6907 case SLIMBUS_8_RX:
6908 case SLIMBUS_8_TX:
Surendar Karkab0dd21f2018-09-28 18:53:50 +05306909 case SLIMBUS_9_RX:
6910 case SLIMBUS_9_TX:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306911 case AFE_PORT_ID_USB_RX:
6912 case AFE_PORT_ID_USB_TX:
6913 case AFE_PORT_ID_PRIMARY_MI2S_RX:
6914 case AFE_PORT_ID_PRIMARY_MI2S_TX:
6915 case AFE_PORT_ID_SECONDARY_MI2S_RX:
6916 case AFE_PORT_ID_SECONDARY_MI2S_TX:
6917 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
6918 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
6919 case AFE_PORT_ID_TERTIARY_MI2S_RX:
6920 case AFE_PORT_ID_TERTIARY_MI2S_TX:
6921 case AFE_PORT_ID_QUINARY_MI2S_RX:
6922 case AFE_PORT_ID_QUINARY_MI2S_TX:
6923 case AFE_PORT_ID_SENARY_MI2S_TX:
6924 case AFE_PORT_ID_PRIMARY_TDM_RX:
6925 case AFE_PORT_ID_PRIMARY_TDM_TX:
6926 case AFE_PORT_ID_PRIMARY_TDM_RX_1:
6927 case AFE_PORT_ID_PRIMARY_TDM_TX_1:
6928 case AFE_PORT_ID_PRIMARY_TDM_RX_2:
6929 case AFE_PORT_ID_PRIMARY_TDM_TX_2:
6930 case AFE_PORT_ID_PRIMARY_TDM_RX_3:
6931 case AFE_PORT_ID_PRIMARY_TDM_TX_3:
6932 case AFE_PORT_ID_PRIMARY_TDM_RX_4:
6933 case AFE_PORT_ID_PRIMARY_TDM_TX_4:
6934 case AFE_PORT_ID_PRIMARY_TDM_RX_5:
6935 case AFE_PORT_ID_PRIMARY_TDM_TX_5:
6936 case AFE_PORT_ID_PRIMARY_TDM_RX_6:
6937 case AFE_PORT_ID_PRIMARY_TDM_TX_6:
6938 case AFE_PORT_ID_PRIMARY_TDM_RX_7:
6939 case AFE_PORT_ID_PRIMARY_TDM_TX_7:
6940 case AFE_PORT_ID_SECONDARY_TDM_RX:
6941 case AFE_PORT_ID_SECONDARY_TDM_TX:
6942 case AFE_PORT_ID_SECONDARY_TDM_RX_1:
6943 case AFE_PORT_ID_SECONDARY_TDM_TX_1:
6944 case AFE_PORT_ID_SECONDARY_TDM_RX_2:
6945 case AFE_PORT_ID_SECONDARY_TDM_TX_2:
6946 case AFE_PORT_ID_SECONDARY_TDM_RX_3:
6947 case AFE_PORT_ID_SECONDARY_TDM_TX_3:
6948 case AFE_PORT_ID_SECONDARY_TDM_RX_4:
6949 case AFE_PORT_ID_SECONDARY_TDM_TX_4:
6950 case AFE_PORT_ID_SECONDARY_TDM_RX_5:
6951 case AFE_PORT_ID_SECONDARY_TDM_TX_5:
6952 case AFE_PORT_ID_SECONDARY_TDM_RX_6:
6953 case AFE_PORT_ID_SECONDARY_TDM_TX_6:
6954 case AFE_PORT_ID_SECONDARY_TDM_RX_7:
6955 case AFE_PORT_ID_SECONDARY_TDM_TX_7:
6956 case AFE_PORT_ID_TERTIARY_TDM_RX:
6957 case AFE_PORT_ID_TERTIARY_TDM_TX:
6958 case AFE_PORT_ID_TERTIARY_TDM_RX_1:
6959 case AFE_PORT_ID_TERTIARY_TDM_TX_1:
6960 case AFE_PORT_ID_TERTIARY_TDM_RX_2:
6961 case AFE_PORT_ID_TERTIARY_TDM_TX_2:
6962 case AFE_PORT_ID_TERTIARY_TDM_RX_3:
6963 case AFE_PORT_ID_TERTIARY_TDM_TX_3:
6964 case AFE_PORT_ID_TERTIARY_TDM_RX_4:
6965 case AFE_PORT_ID_TERTIARY_TDM_TX_4:
6966 case AFE_PORT_ID_TERTIARY_TDM_RX_5:
6967 case AFE_PORT_ID_TERTIARY_TDM_TX_5:
6968 case AFE_PORT_ID_TERTIARY_TDM_RX_6:
6969 case AFE_PORT_ID_TERTIARY_TDM_TX_6:
6970 case AFE_PORT_ID_TERTIARY_TDM_RX_7:
6971 case AFE_PORT_ID_TERTIARY_TDM_TX_7:
6972 case AFE_PORT_ID_QUATERNARY_TDM_RX:
6973 case AFE_PORT_ID_QUATERNARY_TDM_TX:
6974 case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
6975 case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
6976 case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
6977 case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
6978 case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
6979 case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
6980 case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
6981 case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
6982 case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
6983 case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
6984 case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
6985 case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
6986 case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
6987 case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
Rohit Kumarc08b14f2017-10-06 10:52:17 +05306988 case AFE_PORT_ID_QUINARY_TDM_RX:
6989 case AFE_PORT_ID_QUINARY_TDM_TX:
6990 case AFE_PORT_ID_QUINARY_TDM_RX_1:
6991 case AFE_PORT_ID_QUINARY_TDM_TX_1:
6992 case AFE_PORT_ID_QUINARY_TDM_RX_2:
6993 case AFE_PORT_ID_QUINARY_TDM_TX_2:
6994 case AFE_PORT_ID_QUINARY_TDM_RX_3:
6995 case AFE_PORT_ID_QUINARY_TDM_TX_3:
6996 case AFE_PORT_ID_QUINARY_TDM_RX_4:
6997 case AFE_PORT_ID_QUINARY_TDM_TX_4:
6998 case AFE_PORT_ID_QUINARY_TDM_RX_5:
6999 case AFE_PORT_ID_QUINARY_TDM_TX_5:
7000 case AFE_PORT_ID_QUINARY_TDM_RX_6:
7001 case AFE_PORT_ID_QUINARY_TDM_TX_6:
7002 case AFE_PORT_ID_QUINARY_TDM_RX_7:
7003 case AFE_PORT_ID_QUINARY_TDM_TX_7:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307004 case AFE_PORT_ID_INT0_MI2S_RX:
7005 case AFE_PORT_ID_INT1_MI2S_RX:
7006 case AFE_PORT_ID_INT2_MI2S_RX:
7007 case AFE_PORT_ID_INT3_MI2S_RX:
7008 case AFE_PORT_ID_INT4_MI2S_RX:
7009 case AFE_PORT_ID_INT5_MI2S_RX:
7010 case AFE_PORT_ID_INT6_MI2S_RX:
7011 case AFE_PORT_ID_INT0_MI2S_TX:
7012 case AFE_PORT_ID_INT1_MI2S_TX:
7013 case AFE_PORT_ID_INT2_MI2S_TX:
7014 case AFE_PORT_ID_INT3_MI2S_TX:
7015 case AFE_PORT_ID_INT4_MI2S_TX:
7016 case AFE_PORT_ID_INT5_MI2S_TX:
7017 case AFE_PORT_ID_INT6_MI2S_TX:
Mangesh Kunchamwar07b8dc92018-07-16 19:46:25 +05307018 case AFE_PORT_ID_WSA_CODEC_DMA_RX_0:
7019 case AFE_PORT_ID_WSA_CODEC_DMA_TX_0:
7020 case AFE_PORT_ID_WSA_CODEC_DMA_RX_1:
7021 case AFE_PORT_ID_WSA_CODEC_DMA_TX_1:
7022 case AFE_PORT_ID_WSA_CODEC_DMA_TX_2:
7023 case AFE_PORT_ID_VA_CODEC_DMA_TX_0:
7024 case AFE_PORT_ID_VA_CODEC_DMA_TX_1:
Xiaoyu Ye8341eef2019-01-03 14:57:47 -08007025 case AFE_PORT_ID_VA_CODEC_DMA_TX_2:
Aditya Bavanari54ca7d12018-08-08 13:59:54 +05307026 case AFE_PORT_ID_RX_CODEC_DMA_RX_0:
7027 case AFE_PORT_ID_TX_CODEC_DMA_TX_0:
7028 case AFE_PORT_ID_RX_CODEC_DMA_RX_1:
7029 case AFE_PORT_ID_TX_CODEC_DMA_TX_1:
7030 case AFE_PORT_ID_RX_CODEC_DMA_RX_2:
7031 case AFE_PORT_ID_TX_CODEC_DMA_TX_2:
7032 case AFE_PORT_ID_RX_CODEC_DMA_RX_3:
7033 case AFE_PORT_ID_TX_CODEC_DMA_TX_3:
7034 case AFE_PORT_ID_RX_CODEC_DMA_RX_4:
7035 case AFE_PORT_ID_TX_CODEC_DMA_TX_4:
7036 case AFE_PORT_ID_RX_CODEC_DMA_RX_5:
7037 case AFE_PORT_ID_TX_CODEC_DMA_TX_5:
7038 case AFE_PORT_ID_RX_CODEC_DMA_RX_6:
7039 case AFE_PORT_ID_RX_CODEC_DMA_RX_7:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307040 {
7041 ret = 0;
7042 break;
7043 }
7044
7045 default:
7046 pr_err("%s: default ret 0x%x\n", __func__, port_id);
7047 ret = -EINVAL;
7048 }
7049
7050 return ret;
7051}
7052
7053int afe_convert_virtual_to_portid(u16 port_id)
7054{
7055 int ret;
7056
7057 /*
7058 * if port_id is virtual, convert to physical..
7059 * if port_id is already physical, return physical
7060 */
7061 if (afe_validate_port(port_id) < 0) {
7062 if (port_id == RT_PROXY_DAI_001_RX ||
7063 port_id == RT_PROXY_DAI_001_TX ||
7064 port_id == RT_PROXY_DAI_002_RX ||
7065 port_id == RT_PROXY_DAI_002_TX) {
7066 ret = VIRTUAL_ID_TO_PORTID(port_id);
7067 } else {
7068 pr_err("%s: wrong port 0x%x\n",
7069 __func__, port_id);
7070 ret = -EINVAL;
7071 }
7072 } else
7073 ret = port_id;
7074
7075 return ret;
7076}
7077int afe_port_stop_nowait(int port_id)
7078{
7079 struct afe_port_cmd_device_stop stop;
7080 int ret = 0;
7081
7082 if (this_afe.apr == NULL) {
7083 pr_err("%s: AFE is already closed\n", __func__);
7084 ret = -EINVAL;
7085 goto fail_cmd;
7086 }
7087 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
7088 port_id = q6audio_convert_virtual_to_portid(port_id);
7089
7090 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7091 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
7092 stop.hdr.pkt_size = sizeof(stop);
7093 stop.hdr.src_port = 0;
7094 stop.hdr.dest_port = 0;
7095 stop.hdr.token = 0;
7096 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
7097 stop.port_id = port_id;
7098 stop.reserved = 0;
7099
7100 ret = afe_apr_send_pkt(&stop, NULL);
7101 if (ret)
7102 pr_err("%s: AFE close failed %d\n", __func__, ret);
7103
7104fail_cmd:
7105 return ret;
7106
7107}
7108
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307109/**
7110 * afe_close - command to close AFE port
7111 *
7112 * @port_id: AFE port id
7113 *
7114 * Returns 0 on success, appropriate error code otherwise
7115 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307116int afe_close(int port_id)
7117{
7118 struct afe_port_cmd_device_stop stop;
7119 enum afe_mad_type mad_type;
7120 int ret = 0;
7121 int index = 0;
7122 uint16_t port_index;
7123
7124 if (this_afe.apr == NULL) {
7125 pr_err("%s: AFE is already closed\n", __func__);
7126 if ((port_id == RT_PROXY_DAI_001_RX) ||
7127 (port_id == RT_PROXY_DAI_002_TX))
7128 pcm_afe_instance[port_id & 0x1] = 0;
7129 if ((port_id == RT_PROXY_DAI_002_RX) ||
7130 (port_id == RT_PROXY_DAI_001_TX))
7131 proxy_afe_instance[port_id & 0x1] = 0;
7132 afe_close_done[port_id & 0x1] = true;
7133 ret = -EINVAL;
7134 goto fail_cmd;
7135 }
7136 pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
7137 if ((port_id == RT_PROXY_DAI_001_RX) ||
7138 (port_id == RT_PROXY_DAI_002_TX)) {
7139 pr_debug("%s: before decrementing pcm_afe_instance %d\n",
7140 __func__, pcm_afe_instance[port_id & 0x1]);
7141 port_id = VIRTUAL_ID_TO_PORTID(port_id);
7142 pcm_afe_instance[port_id & 0x1]--;
7143 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
7144 proxy_afe_instance[port_id & 0x1] == 0)) ||
7145 afe_close_done[port_id & 0x1] == true)
7146 return 0;
7147
7148 afe_close_done[port_id & 0x1] = true;
7149 }
7150
7151 if ((port_id == RT_PROXY_DAI_002_RX) ||
7152 (port_id == RT_PROXY_DAI_001_TX)) {
7153 pr_debug("%s: before decrementing proxy_afe_instance %d\n",
7154 __func__, proxy_afe_instance[port_id & 0x1]);
7155 port_id = VIRTUAL_ID_TO_PORTID(port_id);
7156 proxy_afe_instance[port_id & 0x1]--;
7157 if ((!(pcm_afe_instance[port_id & 0x1] == 0 &&
7158 proxy_afe_instance[port_id & 0x1] == 0)) ||
7159 afe_close_done[port_id & 0x1] == true)
7160 return 0;
7161
7162 afe_close_done[port_id & 0x1] = true;
7163 }
7164
7165 port_id = q6audio_convert_virtual_to_portid(port_id);
7166 index = q6audio_get_port_index(port_id);
7167 if (index < 0 || index >= AFE_MAX_PORTS) {
7168 pr_err("%s: AFE port index[%d] invalid!\n",
7169 __func__, index);
7170 return -EINVAL;
7171 }
7172 ret = q6audio_validate_port(port_id);
7173 if (ret < 0) {
7174 pr_warn("%s: Not a valid port id 0x%x ret %d\n",
7175 __func__, port_id, ret);
7176 return -EINVAL;
7177 }
7178
7179 mad_type = afe_port_get_mad_type(port_id);
7180 pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
7181 mad_type);
7182 if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
7183 pr_debug("%s: Turn off MAD\n", __func__);
7184 ret = afe_turn_onoff_hw_mad(mad_type, false);
7185 if (ret) {
7186 pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
7187 __func__, ret);
7188 return ret;
7189 }
7190 } else {
7191 pr_debug("%s: Not a MAD port\n", __func__);
7192 }
7193
7194 port_index = afe_get_port_index(port_id);
7195 if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
7196 this_afe.afe_sample_rates[port_index] = 0;
7197 this_afe.topology[port_index] = 0;
7198 this_afe.dev_acdb_id[port_index] = 0;
7199 } else {
7200 pr_err("%s: port %d\n", __func__, port_index);
7201 ret = -EINVAL;
7202 goto fail_cmd;
7203 }
7204
7205 if ((port_id == this_afe.aanc_info.aanc_tx_port) &&
7206 (this_afe.aanc_info.aanc_active)) {
7207 memset(&this_afe.aanc_info, 0x00, sizeof(this_afe.aanc_info));
7208 ret = afe_aanc_mod_enable(this_afe.apr, port_id, 0);
7209 if (ret)
7210 pr_err("%s: AFE mod disable failed %d\n",
7211 __func__, ret);
7212 }
7213
7214 /*
7215 * even if ramp down configuration failed it is not serious enough to
7216 * warrant bailaing out.
7217 */
7218 if (afe_spk_ramp_dn_cfg(port_id) < 0)
7219 pr_err("%s: ramp down configuration failed\n", __func__);
7220
7221 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7222 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
7223 stop.hdr.pkt_size = sizeof(stop);
7224 stop.hdr.src_port = 0;
7225 stop.hdr.dest_port = 0;
7226 stop.hdr.token = index;
7227 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
7228 stop.port_id = q6audio_get_port_id(port_id);
7229 stop.reserved = 0;
7230
7231 ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
7232 if (ret)
7233 pr_err("%s: AFE close failed %d\n", __func__, ret);
7234
7235fail_cmd:
7236 return ret;
7237}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307238EXPORT_SYMBOL(afe_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307239
7240int afe_set_digital_codec_core_clock(u16 port_id,
7241 struct afe_digital_clk_cfg *cfg)
7242{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007243 struct afe_digital_clk_cfg clk_cfg;
7244 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307245 int ret = 0;
7246
7247 if (!cfg) {
7248 pr_err("%s: clock cfg is NULL\n", __func__);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007249 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307250 }
7251
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007252 memset(&clk_cfg, 0, sizeof(clk_cfg));
7253 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307254
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307255 /*default rx port is taken to enable the codec digital clock*/
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007256 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
7257 param_hdr.instance_id = INSTANCE_ID_0;
7258 param_hdr.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
7259 param_hdr.param_size = sizeof(struct afe_digital_clk_cfg);
7260 clk_cfg = *cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307261
7262 pr_debug("%s: Minor version =0x%x clk val = %d\n"
7263 "clk root = 0x%x resrv = 0x%x\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007264 __func__, cfg->i2s_cfg_minor_version, cfg->clk_val,
7265 cfg->clk_root, cfg->reserved);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307266
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007267 ret = q6afe_pack_and_set_param_in_band(port_id,
7268 q6audio_get_port_index(port_id),
7269 param_hdr, (u8 *) &clk_cfg);
7270 if (ret < 0)
7271 pr_err("%s: AFE enable for port 0x%x ret %d\n", __func__,
7272 port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307273 return ret;
7274}
7275
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307276/**
7277 * afe_set_lpass_clock - Enable AFE lpass clock
7278 *
7279 * @port_id: AFE port id
7280 * @cfg: pointer to clk set struct
7281 *
7282 * Returns 0 on success, appropriate error code otherwise
7283 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307284int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg)
7285{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007286 struct afe_clk_cfg clk_cfg;
7287 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307288 int ret = 0;
7289
7290 if (!cfg) {
7291 pr_err("%s: clock cfg is NULL\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307292 return -EINVAL;
7293 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007294
7295 memset(&clk_cfg, 0, sizeof(clk_cfg));
7296 memset(&param_hdr, 0, sizeof(param_hdr));
7297
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307298 ret = q6audio_is_digital_pcm_interface(port_id);
7299 if (ret < 0) {
7300 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
7301 __func__, ret);
7302 return -EINVAL;
7303 }
7304
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307305 mutex_lock(&this_afe.afe_cmd_lock);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007306 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
7307 param_hdr.instance_id = INSTANCE_ID_0;
7308 param_hdr.param_id = AFE_PARAM_ID_LPAIF_CLK_CONFIG;
7309 param_hdr.param_size = sizeof(clk_cfg);
7310 clk_cfg = *cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307311
7312 pr_debug("%s: Minor version =0x%x clk val1 = %d\n"
7313 "clk val2 = %d, clk src = 0x%x\n"
7314 "clk root = 0x%x clk mode = 0x%x resrv = 0x%x\n"
7315 "port id = 0x%x\n",
7316 __func__, cfg->i2s_cfg_minor_version,
7317 cfg->clk_val1, cfg->clk_val2, cfg->clk_src,
7318 cfg->clk_root, cfg->clk_set_mode,
7319 cfg->reserved, q6audio_get_port_id(port_id));
7320
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007321 ret = q6afe_pack_and_set_param_in_band(port_id,
7322 q6audio_get_port_index(port_id),
7323 param_hdr, (u8 *) &clk_cfg);
7324 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307325 pr_err("%s: AFE enable for port 0x%x ret %d\n",
7326 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307327
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307328 mutex_unlock(&this_afe.afe_cmd_lock);
7329 return ret;
7330}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307331EXPORT_SYMBOL(afe_set_lpass_clock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307332
7333/**
7334 * afe_set_lpass_clk_cfg - Set AFE clk config
7335 *
7336 * @index: port index
7337 * @cfg: pointer to clk set struct
7338 *
7339 * Returns 0 on success, appropriate error code otherwise
7340 */
7341int afe_set_lpass_clk_cfg(int index, struct afe_clk_set *cfg)
7342{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007343 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307344 int ret = 0;
7345
7346 if (!cfg) {
7347 pr_err("%s: clock cfg is NULL\n", __func__);
7348 ret = -EINVAL;
7349 return ret;
7350 }
7351
7352 if (index < 0 || index >= AFE_MAX_PORTS) {
7353 pr_err("%s: index[%d] invalid!\n", __func__, index);
7354 return -EINVAL;
7355 }
7356
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007357 memset(&param_hdr, 0, sizeof(param_hdr));
7358
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307359 ret = afe_q6_interface_prepare();
7360 if (ret != 0) {
7361 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
7362 return ret;
7363 }
7364
7365 mutex_lock(&this_afe.afe_cmd_lock);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007366 param_hdr.module_id = AFE_MODULE_CLOCK_SET;
7367 param_hdr.instance_id = INSTANCE_ID_0;
7368 param_hdr.param_id = AFE_PARAM_ID_CLOCK_SET;
7369 param_hdr.param_size = sizeof(struct afe_clk_set);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307370
7371
7372 pr_debug("%s: Minor version =0x%x clk id = %d\n"
7373 "clk freq (Hz) = %d, clk attri = 0x%x\n"
7374 "clk root = 0x%x clk enable = 0x%x\n",
7375 __func__, cfg->clk_set_minor_version,
7376 cfg->clk_id, cfg->clk_freq_in_hz, cfg->clk_attri,
7377 cfg->clk_root, cfg->enable);
7378
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007379 ret = q6afe_svc_pack_and_set_param_in_band(index, param_hdr,
7380 (u8 *) cfg);
7381 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307382 pr_err("%s: AFE clk cfg failed with ret %d\n",
7383 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307384
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307385 mutex_unlock(&this_afe.afe_cmd_lock);
7386 return ret;
7387}
7388EXPORT_SYMBOL(afe_set_lpass_clk_cfg);
7389
7390/**
7391 * afe_set_lpass_clock_v2 - Enable AFE lpass clock
7392 *
7393 * @port_id: AFE port id
7394 * @cfg: pointer to clk set struct
7395 *
7396 * Returns 0 on success, appropriate error code otherwise
7397 */
7398int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
7399{
7400 int index = 0;
7401 int ret = 0;
7402
7403 index = q6audio_get_port_index(port_id);
7404 if (index < 0 || index >= AFE_MAX_PORTS) {
7405 pr_err("%s: AFE port index[%d] invalid!\n",
7406 __func__, index);
7407 return -EINVAL;
7408 }
7409 ret = q6audio_is_digital_pcm_interface(port_id);
7410 if (ret < 0) {
7411 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
7412 __func__, ret);
7413 return -EINVAL;
7414 }
7415
7416 ret = afe_set_lpass_clk_cfg(index, cfg);
7417 if (ret)
7418 pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
7419 __func__, ret);
7420
7421 return ret;
7422}
7423EXPORT_SYMBOL(afe_set_lpass_clock_v2);
7424
7425int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
7426 struct afe_digital_clk_cfg *cfg)
7427{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007428 struct afe_digital_clk_cfg clk_cfg;
7429 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307430 int ret = 0;
7431
7432 if (!cfg) {
7433 pr_err("%s: clock cfg is NULL\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307434 return -EINVAL;
7435 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007436
7437 memset(&clk_cfg, 0, sizeof(clk_cfg));
7438 memset(&param_hdr, 0, sizeof(param_hdr));
7439
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307440 ret = q6audio_is_digital_pcm_interface(port_id);
7441 if (ret < 0) {
7442 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
7443 __func__, ret);
7444 return -EINVAL;
7445 }
7446
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007447 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
7448 param_hdr.instance_id = INSTANCE_ID_0;
7449 param_hdr.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
7450 param_hdr.param_size = sizeof(clk_cfg);
7451 clk_cfg = *cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307452
7453 pr_debug("%s: Minor version =0x%x clk val = %d\n"
7454 "clk root = 0x%x resrv = 0x%x port id = 0x%x\n",
7455 __func__, cfg->i2s_cfg_minor_version,
7456 cfg->clk_val, cfg->clk_root, cfg->reserved,
7457 q6audio_get_port_id(port_id));
7458
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007459 ret = q6afe_pack_and_set_param_in_band(port_id,
7460 q6audio_get_port_index(port_id),
7461 param_hdr, (u8 *) &clk_cfg);
7462 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307463 pr_err("%s: AFE enable for port 0x0x%x ret %d\n",
7464 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307465
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307466 return ret;
7467}
Josh Kirsch22533092019-01-17 16:01:08 -08007468/**
7469 * afe_enable_lpass_core_shared_clock -
7470 * Configures the core clk on LPASS.
7471 * Need on targets where lpass provides
7472 * clocks
7473 * @port_id: afe port id
7474 * @enable: enable or disable clk
7475 *
7476 * Returns success or failure of call.
7477 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307478int afe_enable_lpass_core_shared_clock(u16 port_id, u32 enable)
7479{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007480 struct afe_param_id_lpass_core_shared_clk_cfg clk_cfg;
7481 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307482 int ret = 0;
7483
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007484 memset(&clk_cfg, 0, sizeof(clk_cfg));
7485 memset(&param_hdr, 0, sizeof(param_hdr));
7486
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307487 ret = q6audio_is_digital_pcm_interface(port_id);
7488 if (ret < 0) {
7489 pr_err("%s: q6audio_is_digital_pcm_interface fail %d\n",
7490 __func__, ret);
7491 return -EINVAL;
7492 }
7493
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307494 mutex_lock(&this_afe.afe_cmd_lock);
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007495 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
7496 param_hdr.instance_id = INSTANCE_ID_0;
7497 param_hdr.param_id = AFE_PARAM_ID_LPASS_CORE_SHARED_CLOCK_CONFIG;
7498 param_hdr.param_size = sizeof(clk_cfg);
7499 clk_cfg.lpass_core_shared_clk_cfg_minor_version =
7500 AFE_API_VERSION_LPASS_CORE_SHARED_CLK_CONFIG;
7501 clk_cfg.enable = enable;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307502
7503 pr_debug("%s: port id = %d, enable = %d\n",
7504 __func__, q6audio_get_port_id(port_id), enable);
7505
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007506 ret = q6afe_pack_and_set_param_in_band(port_id,
7507 q6audio_get_port_index(port_id),
7508 param_hdr, (u8 *) &clk_cfg);
7509 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307510 pr_err("%s: AFE enable for port 0x%x ret %d\n",
7511 __func__, port_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307512
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307513 mutex_unlock(&this_afe.afe_cmd_lock);
7514 return ret;
7515}
Josh Kirsch22533092019-01-17 16:01:08 -08007516EXPORT_SYMBOL(afe_enable_lpass_core_shared_clock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307517
Josh Kirsch22533092019-01-17 16:01:08 -08007518/**
7519 * q6afe_check_osr_clk_freq -
7520 * Gets supported OSR CLK frequencies
7521 *
7522 * @freq: frequency to check
7523 *
7524 * Returns success if freq is supported.
7525 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307526int q6afe_check_osr_clk_freq(u32 freq)
7527{
7528 int ret = 0;
7529
7530 switch (freq) {
7531 case Q6AFE_LPASS_OSR_CLK_12_P288_MHZ:
Karthikeyan Mani0575b672017-12-10 23:50:37 -08007532 case Q6AFE_LPASS_OSR_CLK_9_P600_MHZ:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307533 case Q6AFE_LPASS_OSR_CLK_8_P192_MHZ:
7534 case Q6AFE_LPASS_OSR_CLK_6_P144_MHZ:
7535 case Q6AFE_LPASS_OSR_CLK_4_P096_MHZ:
7536 case Q6AFE_LPASS_OSR_CLK_3_P072_MHZ:
7537 case Q6AFE_LPASS_OSR_CLK_2_P048_MHZ:
7538 case Q6AFE_LPASS_OSR_CLK_1_P536_MHZ:
7539 case Q6AFE_LPASS_OSR_CLK_1_P024_MHZ:
7540 case Q6AFE_LPASS_OSR_CLK_768_kHZ:
7541 case Q6AFE_LPASS_OSR_CLK_512_kHZ:
7542 break;
7543 default:
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007544 pr_err("%s: default freq 0x%x\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307545 __func__, freq);
7546 ret = -EINVAL;
7547 }
7548 return ret;
7549}
Josh Kirsch22533092019-01-17 16:01:08 -08007550EXPORT_SYMBOL(q6afe_check_osr_clk_freq);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307551
Laxminath Kasam2e13d952019-02-20 15:05:39 +05307552static int afe_get_sp_th_vi_v_vali_data(
7553 struct afe_sp_th_vi_v_vali_get_param *th_vi_v_vali)
7554{
7555 struct param_hdr_v3 param_hdr;
7556 int port = SLIMBUS_4_TX;
7557 int ret = -EINVAL;
7558
7559 if (!th_vi_v_vali) {
7560 pr_err("%s: Invalid params\n", __func__);
7561 goto done;
7562 }
7563 if (this_afe.vi_tx_port != -1)
7564 port = this_afe.vi_tx_port;
7565
7566 memset(&param_hdr, 0, sizeof(param_hdr));
7567
7568 param_hdr.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
7569 param_hdr.instance_id = INSTANCE_ID_0;
7570 param_hdr.param_id = AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_PARAMS;
7571 param_hdr.param_size = sizeof(struct afe_sp_th_vi_v_vali_params);
7572
7573 ret = q6afe_get_params(port, NULL, &param_hdr);
7574 if (ret) {
7575 pr_err("%s: Failed to get TH VI V-Vali data\n", __func__);
7576 goto done;
7577 }
7578
7579 th_vi_v_vali->pdata = param_hdr;
7580 memcpy(&th_vi_v_vali->param, &this_afe.th_vi_v_vali_resp.param,
7581 sizeof(this_afe.th_vi_v_vali_resp.param));
7582 pr_debug("%s: Vrms %d %d status %d %d\n", __func__,
7583 th_vi_v_vali->param.vrms_q24[SP_V2_SPKR_1],
7584 th_vi_v_vali->param.vrms_q24[SP_V2_SPKR_2],
7585 th_vi_v_vali->param.status[SP_V2_SPKR_1],
7586 th_vi_v_vali->param.status[SP_V2_SPKR_2]);
7587 ret = 0;
7588done:
7589 return ret;
7590}
7591
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307592int afe_get_sp_th_vi_ftm_data(struct afe_sp_th_vi_get_param *th_vi)
7593{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007594 struct param_hdr_v3 param_hdr;
7595 int port = SLIMBUS_4_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307596 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307597
7598 if (!th_vi) {
7599 pr_err("%s: Invalid params\n", __func__);
7600 goto done;
7601 }
7602 if (this_afe.vi_tx_port != -1)
7603 port = this_afe.vi_tx_port;
7604
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007605 memset(&param_hdr, 0, sizeof(param_hdr));
7606
7607 param_hdr.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
7608 param_hdr.instance_id = INSTANCE_ID_0;
7609 param_hdr.param_id = AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS;
7610 param_hdr.param_size = sizeof(struct afe_sp_th_vi_ftm_params);
7611
7612 ret = q6afe_get_params(port, NULL, &param_hdr);
7613 if (ret) {
7614 pr_err("%s: Failed to get TH VI FTM data\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307615 goto done;
7616 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007617
7618 th_vi->pdata = param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307619 memcpy(&th_vi->param, &this_afe.th_vi_resp.param,
7620 sizeof(this_afe.th_vi_resp.param));
7621 pr_debug("%s: DC resistance %d %d temp %d %d status %d %d\n",
7622 __func__, th_vi->param.dc_res_q24[SP_V2_SPKR_1],
7623 th_vi->param.dc_res_q24[SP_V2_SPKR_2],
7624 th_vi->param.temp_q22[SP_V2_SPKR_1],
7625 th_vi->param.temp_q22[SP_V2_SPKR_2],
7626 th_vi->param.status[SP_V2_SPKR_1],
7627 th_vi->param.status[SP_V2_SPKR_2]);
7628 ret = 0;
7629done:
7630 return ret;
7631}
7632
7633int afe_get_sp_ex_vi_ftm_data(struct afe_sp_ex_vi_get_param *ex_vi)
7634{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007635 struct param_hdr_v3 param_hdr;
7636 int port = SLIMBUS_4_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307637 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307638
7639 if (!ex_vi) {
7640 pr_err("%s: Invalid params\n", __func__);
7641 goto done;
7642 }
7643 if (this_afe.vi_tx_port != -1)
7644 port = this_afe.vi_tx_port;
7645
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007646 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307647
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007648 param_hdr.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
7649 param_hdr.instance_id = INSTANCE_ID_0;
7650 param_hdr.param_id = AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS;
7651 param_hdr.param_size = sizeof(struct afe_sp_ex_vi_ftm_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307652
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007653 ret = q6afe_get_params(port, NULL, &param_hdr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307654 if (ret < 0) {
7655 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007656 __func__, port, param_hdr.param_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307657 goto done;
7658 }
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007659
7660 ex_vi->pdata = param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307661 memcpy(&ex_vi->param, &this_afe.ex_vi_resp.param,
7662 sizeof(this_afe.ex_vi_resp.param));
7663 pr_debug("%s: freq %d %d resistance %d %d qfactor %d %d state %d %d\n",
7664 __func__, ex_vi->param.freq_q20[SP_V2_SPKR_1],
7665 ex_vi->param.freq_q20[SP_V2_SPKR_2],
7666 ex_vi->param.resis_q24[SP_V2_SPKR_1],
7667 ex_vi->param.resis_q24[SP_V2_SPKR_2],
7668 ex_vi->param.qmct_q24[SP_V2_SPKR_1],
7669 ex_vi->param.qmct_q24[SP_V2_SPKR_2],
7670 ex_vi->param.status[SP_V2_SPKR_1],
7671 ex_vi->param.status[SP_V2_SPKR_2]);
7672 ret = 0;
7673done:
7674 return ret;
7675}
7676
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307677/**
Aditya Bavanari740b4832018-12-24 18:46:12 +05307678 * afe_get_sp_rx_tmax_xmax_logging_data -
7679 * command to get excursion logging data from DSP
7680 *
7681 * @xt_logging: excursion logging params
7682 * @port: AFE port ID
7683 *
7684 * Returns 0 on success or error on failure
7685 */
7686int afe_get_sp_rx_tmax_xmax_logging_data(
7687 struct afe_sp_rx_tmax_xmax_logging_param *xt_logging,
7688 u16 port_id)
7689{
7690 struct param_hdr_v3 param_hdr;
7691 int ret = -EINVAL;
7692
7693 if (!xt_logging) {
7694 pr_err("%s: Invalid params\n", __func__);
7695 goto done;
7696 }
7697
7698 memset(&param_hdr, 0, sizeof(param_hdr));
7699
7700 param_hdr.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
7701 param_hdr.instance_id = INSTANCE_ID_0;
7702 param_hdr.param_id = AFE_PARAM_ID_SP_RX_TMAX_XMAX_LOGGING;
7703 param_hdr.param_size = sizeof(struct afe_sp_rx_tmax_xmax_logging_param);
7704
7705 ret = q6afe_get_params(port_id, NULL, &param_hdr);
7706 if (ret < 0) {
7707 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
7708 __func__, port_id, param_hdr.param_id, ret);
7709 goto done;
7710 }
7711
7712 memcpy(xt_logging, &this_afe.xt_logging_resp.param,
7713 sizeof(this_afe.xt_logging_resp.param));
7714 pr_debug("%s: max_excursion %d %d count_exceeded_excursion %d %d max_temperature %d %d count_exceeded_temperature %d %d\n",
7715 __func__, xt_logging->max_excursion[SP_V2_SPKR_1],
7716 xt_logging->max_excursion[SP_V2_SPKR_2],
7717 xt_logging->count_exceeded_excursion[SP_V2_SPKR_1],
7718 xt_logging->count_exceeded_excursion[SP_V2_SPKR_2],
7719 xt_logging->max_temperature[SP_V2_SPKR_1],
7720 xt_logging->max_temperature[SP_V2_SPKR_2],
7721 xt_logging->count_exceeded_temperature[SP_V2_SPKR_1],
7722 xt_logging->count_exceeded_temperature[SP_V2_SPKR_2]);
7723done:
7724 return ret;
7725}
7726EXPORT_SYMBOL(afe_get_sp_rx_tmax_xmax_logging_data);
7727
7728/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307729 * afe_get_av_dev_drift -
7730 * command to retrieve AV drift
7731 *
7732 * @timing_stats: timing stats to be updated with AV drift values
7733 * @port: AFE port ID
7734 *
7735 * Returns 0 on success or error on failure
7736 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307737int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
7738 u16 port)
7739{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007740 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307741 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307742
7743 if (!timing_stats) {
7744 pr_err("%s: Invalid params\n", __func__);
7745 goto exit;
7746 }
7747
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007748 memset(&param_hdr, 0, sizeof(param_hdr));
7749 param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
7750 param_hdr.instance_id = INSTANCE_ID_0;
7751 param_hdr.param_id = AFE_PARAM_ID_DEV_TIMING_STATS;
7752 param_hdr.param_size = sizeof(struct afe_param_id_dev_timing_stats);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307753
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007754 ret = q6afe_get_params(port, NULL, &param_hdr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307755 if (ret < 0) {
7756 pr_err("%s: get param port 0x%x param id[0x%x] failed %d\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007757 __func__, port, param_hdr.param_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307758 goto exit;
7759 }
7760
7761 memcpy(timing_stats, &this_afe.av_dev_drift_resp.timing_stats,
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007762 param_hdr.param_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307763 ret = 0;
7764exit:
7765 return ret;
7766}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307767EXPORT_SYMBOL(afe_get_av_dev_drift);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307768
Chaithanya Krishna Bacharaju8c6a1842018-11-16 15:02:39 +05307769/**
7770 * afe_get_doa_tracking_mon -
7771 * command to retrieve doa tracking monitor data
7772 *
7773 * @port: AFE port ID
7774 * @doa_tracking_data: param to be updated with doa tracking data
7775 *
7776 * Returns 0 on success or error on failure
7777 */
7778int afe_get_doa_tracking_mon(u16 port,
7779 struct doa_tracking_mon_param *doa_tracking_data)
7780{
7781 struct param_hdr_v3 param_hdr;
7782 int ret = -EINVAL, i = 0;
7783
7784 if (!doa_tracking_data) {
7785 pr_err("%s: Invalid params\n", __func__);
7786 goto exit;
7787 }
7788
7789 memset(&param_hdr, 0, sizeof(param_hdr));
7790 param_hdr.module_id = AUDPROC_MODULE_ID_FFNS;
7791 param_hdr.instance_id = INSTANCE_ID_0;
7792 param_hdr.param_id = AUDPROC_PARAM_ID_FFV_DOA_TRACKING_MONITOR;
7793 param_hdr.param_size = sizeof(struct doa_tracking_mon_param);
7794
7795 ret = q6afe_get_params(port, NULL, &param_hdr);
7796 if (ret < 0) {
7797 pr_err("%s: get param port 0x%x param id[0x%x] failed %d\n",
7798 __func__, port, param_hdr.param_id, ret);
7799 goto exit;
7800 }
7801
7802 memcpy(doa_tracking_data, &this_afe.doa_tracking_mon_resp.doa,
7803 param_hdr.param_size);
7804 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
7805 pr_debug("%s: target angle[%d] = %d\n",
7806 __func__, i, doa_tracking_data->target_angle_L16[i]);
7807 pr_debug("%s: interference angle[%d] = %d\n",
7808 __func__, i, doa_tracking_data->interf_angle_L16[i]);
7809 }
7810
7811exit:
7812 return ret;
7813}
7814EXPORT_SYMBOL(afe_get_doa_tracking_mon);
7815
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307816int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp)
7817{
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007818 struct param_hdr_v3 param_hdr;
7819 int port = SLIMBUS_4_TX;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307820 int ret = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307821
7822 if (!calib_resp) {
7823 pr_err("%s: Invalid params\n", __func__);
7824 goto fail_cmd;
7825 }
7826 if (this_afe.vi_tx_port != -1)
7827 port = this_afe.vi_tx_port;
7828
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007829 memset(&param_hdr, 0, sizeof(param_hdr));
7830 param_hdr.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
7831 param_hdr.instance_id = INSTANCE_ID_0;
7832 param_hdr.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2;
7833 param_hdr.param_size = sizeof(struct afe_spkr_prot_get_vi_calib);
7834
7835 ret = q6afe_get_params(port, NULL, &param_hdr);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307836 if (ret < 0) {
7837 pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
Vignesh Kulothungan85073c02018-01-26 10:27:56 -08007838 __func__, port, param_hdr.param_id, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307839 goto fail_cmd;
7840 }
7841 memcpy(&calib_resp->res_cfg, &this_afe.calib_data.res_cfg,
7842 sizeof(this_afe.calib_data.res_cfg));
7843 pr_info("%s: state %s resistance %d %d\n", __func__,
Laxminath Kasam36384ec2019-02-18 21:57:19 +05307844 fbsp_state[calib_resp->res_cfg.th_vi_ca_state],
7845 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1],
7846 calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307847 ret = 0;
7848fail_cmd:
7849 return ret;
7850}
7851
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307852/**
7853 * afe_spk_prot_feed_back_cfg -
7854 * command to setup spk protection feedback config
7855 *
7856 * @src_port: source port id
7857 * @dst_port: destination port id
7858 * @l_ch: left speaker active or not
7859 * @r_ch: right speaker active or not
7860 * @enable: flag to enable or disable
7861 *
7862 * Returns 0 on success or error on failure
7863 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307864int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
7865 int l_ch, int r_ch, u32 enable)
7866{
7867 int ret = -EINVAL;
7868 union afe_spkr_prot_config prot_config;
7869 int index = 0;
7870
7871 if (!enable) {
7872 pr_debug("%s: Disable Feedback tx path", __func__);
7873 this_afe.vi_tx_port = -1;
7874 this_afe.vi_rx_port = -1;
7875 return 0;
7876 }
7877
7878 if ((q6audio_validate_port(src_port) < 0) ||
7879 (q6audio_validate_port(dst_port) < 0)) {
7880 pr_err("%s: invalid ports src 0x%x dst 0x%x",
7881 __func__, src_port, dst_port);
7882 goto fail_cmd;
7883 }
7884 if (!l_ch && !r_ch) {
7885 pr_err("%s: error ch values zero\n", __func__);
7886 goto fail_cmd;
7887 }
7888 pr_debug("%s: src_port 0x%x dst_port 0x%x l_ch %d r_ch %d\n",
7889 __func__, src_port, dst_port, l_ch, r_ch);
7890 memset(&prot_config, 0, sizeof(prot_config));
7891 prot_config.feedback_path_cfg.dst_portid =
7892 q6audio_get_port_id(dst_port);
7893 if (l_ch) {
7894 prot_config.feedback_path_cfg.chan_info[index++] = 1;
7895 prot_config.feedback_path_cfg.chan_info[index++] = 2;
7896 }
7897 if (r_ch) {
7898 prot_config.feedback_path_cfg.chan_info[index++] = 3;
7899 prot_config.feedback_path_cfg.chan_info[index++] = 4;
7900 }
7901 prot_config.feedback_path_cfg.num_channels = index;
7902 pr_debug("%s no of channels: %d\n", __func__, index);
7903 prot_config.feedback_path_cfg.minor_version = 1;
7904 ret = afe_spk_prot_prepare(src_port, dst_port,
7905 AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config);
7906fail_cmd:
7907 return ret;
7908}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307909EXPORT_SYMBOL(afe_spk_prot_feed_back_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307910
7911static int get_cal_type_index(int32_t cal_type)
7912{
7913 int ret = -EINVAL;
7914
7915 switch (cal_type) {
7916 case AFE_COMMON_RX_CAL_TYPE:
7917 ret = AFE_COMMON_RX_CAL;
7918 break;
7919 case AFE_COMMON_TX_CAL_TYPE:
7920 ret = AFE_COMMON_TX_CAL;
7921 break;
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307922 case AFE_LSM_TX_CAL_TYPE:
7923 ret = AFE_LSM_TX_CAL;
7924 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307925 case AFE_AANC_CAL_TYPE:
7926 ret = AFE_AANC_CAL;
7927 break;
7928 case AFE_HW_DELAY_CAL_TYPE:
7929 ret = AFE_HW_DELAY_CAL;
7930 break;
7931 case AFE_FB_SPKR_PROT_CAL_TYPE:
7932 ret = AFE_FB_SPKR_PROT_CAL;
7933 break;
7934 case AFE_SIDETONE_CAL_TYPE:
7935 ret = AFE_SIDETONE_CAL;
7936 break;
7937 case AFE_SIDETONE_IIR_CAL_TYPE:
7938 ret = AFE_SIDETONE_IIR_CAL;
7939 break;
7940 case AFE_TOPOLOGY_CAL_TYPE:
7941 ret = AFE_TOPOLOGY_CAL;
7942 break;
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05307943 case AFE_LSM_TOPOLOGY_CAL_TYPE:
7944 ret = AFE_LSM_TOPOLOGY_CAL;
7945 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307946 case AFE_CUST_TOPOLOGY_CAL_TYPE:
7947 ret = AFE_CUST_TOPOLOGY_CAL;
7948 break;
7949 default:
7950 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
7951 }
7952 return ret;
7953}
7954
7955int afe_alloc_cal(int32_t cal_type, size_t data_size,
7956 void *data)
7957{
7958 int ret = 0;
7959 int cal_index;
7960
7961 cal_index = get_cal_type_index(cal_type);
7962 pr_debug("%s: cal_type = %d cal_index = %d\n",
7963 __func__, cal_type, cal_index);
7964
7965 if (cal_index < 0) {
7966 pr_err("%s: could not get cal index %d!\n",
7967 __func__, cal_index);
7968 ret = -EINVAL;
7969 goto done;
7970 }
7971
Xiaojun Sang41de9e12018-10-16 15:12:47 +08007972 mutex_lock(&this_afe.afe_cmd_lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307973 ret = cal_utils_alloc_cal(data_size, data,
7974 this_afe.cal_data[cal_index], 0, NULL);
7975 if (ret < 0) {
7976 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
7977 __func__, ret, cal_type);
7978 ret = -EINVAL;
Xiaojun Sang41de9e12018-10-16 15:12:47 +08007979 mutex_unlock(&this_afe.afe_cmd_lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307980 goto done;
7981 }
Xiaojun Sang41de9e12018-10-16 15:12:47 +08007982 mutex_unlock(&this_afe.afe_cmd_lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307983done:
7984 return ret;
7985}
7986
7987static int afe_dealloc_cal(int32_t cal_type, size_t data_size,
7988 void *data)
7989{
7990 int ret = 0;
7991 int cal_index;
7992
7993 pr_debug("%s:\n", __func__);
7994
7995 cal_index = get_cal_type_index(cal_type);
7996 if (cal_index < 0) {
7997 pr_err("%s: could not get cal index %d!\n",
7998 __func__, cal_index);
7999 ret = -EINVAL;
8000 goto done;
8001 }
8002
8003 ret = cal_utils_dealloc_cal(data_size, data,
8004 this_afe.cal_data[cal_index]);
8005 if (ret < 0) {
8006 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
8007 __func__, ret, cal_type);
8008 ret = -EINVAL;
8009 goto done;
8010 }
8011done:
8012 return ret;
8013}
8014
8015static int afe_set_cal(int32_t cal_type, size_t data_size,
8016 void *data)
8017{
8018 int ret = 0;
8019 int cal_index;
8020
8021 pr_debug("%s:\n", __func__);
8022
8023 cal_index = get_cal_type_index(cal_type);
8024 if (cal_index < 0) {
8025 pr_err("%s: could not get cal index %d!\n",
8026 __func__, cal_index);
8027 ret = -EINVAL;
8028 goto done;
8029 }
8030
8031 ret = cal_utils_set_cal(data_size, data,
8032 this_afe.cal_data[cal_index], 0, NULL);
8033 if (ret < 0) {
8034 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
8035 __func__, ret, cal_type);
8036 ret = -EINVAL;
8037 goto done;
8038 }
8039
8040 if (cal_index == AFE_CUST_TOPOLOGY_CAL) {
8041 mutex_lock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
8042 this_afe.set_custom_topology = 1;
8043 pr_debug("%s:[AFE_CUSTOM_TOPOLOGY] ret = %d, cal type = %d!\n",
8044 __func__, ret, cal_type);
8045 mutex_unlock(&this_afe.cal_data[AFE_CUST_TOPOLOGY_CAL]->lock);
8046 }
8047
8048done:
8049 return ret;
8050}
8051
8052static struct cal_block_data *afe_find_hw_delay_by_path(
8053 struct cal_type_data *cal_type, int path)
8054{
8055 struct list_head *ptr, *next;
8056 struct cal_block_data *cal_block = NULL;
8057
8058 pr_debug("%s:\n", __func__);
8059
8060 list_for_each_safe(ptr, next,
8061 &cal_type->cal_blocks) {
8062
8063 cal_block = list_entry(ptr,
8064 struct cal_block_data, list);
8065
Vikram Panduranga770b8382017-09-27 12:17:36 -07008066 if (cal_utils_is_cal_stale(cal_block))
8067 continue;
8068
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308069 if (((struct audio_cal_info_hw_delay *)cal_block->cal_info)
8070 ->path == path) {
8071 return cal_block;
8072 }
8073 }
8074 return NULL;
8075}
8076
8077static int afe_get_cal_hw_delay(int32_t path,
8078 struct audio_cal_hw_delay_entry *entry)
8079{
8080 int ret = 0;
8081 int i;
8082 struct cal_block_data *cal_block = NULL;
8083 struct audio_cal_hw_delay_data *hw_delay_info = NULL;
8084
8085 pr_debug("%s:\n", __func__);
8086
8087 if (this_afe.cal_data[AFE_HW_DELAY_CAL] == NULL) {
8088 pr_err("%s: AFE_HW_DELAY_CAL not initialized\n", __func__);
8089 ret = -EINVAL;
8090 goto done;
8091 }
8092 if (entry == NULL) {
8093 pr_err("%s: entry is NULL\n", __func__);
8094 ret = -EINVAL;
8095 goto done;
8096 }
8097 if ((path >= MAX_PATH_TYPE) || (path < 0)) {
8098 pr_err("%s: bad path: %d\n",
8099 __func__, path);
8100 ret = -EINVAL;
8101 goto done;
8102 }
8103
8104 mutex_lock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
8105 cal_block = afe_find_hw_delay_by_path(
8106 this_afe.cal_data[AFE_HW_DELAY_CAL], path);
8107 if (cal_block == NULL)
8108 goto unlock;
8109
8110 hw_delay_info = &((struct audio_cal_info_hw_delay *)
8111 cal_block->cal_info)->data;
8112 if (hw_delay_info->num_entries > MAX_HW_DELAY_ENTRIES) {
8113 pr_err("%s: invalid num entries: %d\n",
8114 __func__, hw_delay_info->num_entries);
8115 ret = -EINVAL;
8116 goto unlock;
8117 }
8118
8119 for (i = 0; i < hw_delay_info->num_entries; i++) {
8120 if (hw_delay_info->entry[i].sample_rate ==
8121 entry->sample_rate) {
8122 entry->delay_usec = hw_delay_info->entry[i].delay_usec;
8123 break;
8124 }
8125 }
8126 if (i == hw_delay_info->num_entries) {
8127 pr_err("%s: Unable to find delay for sample rate %d\n",
8128 __func__, entry->sample_rate);
8129 ret = -EFAULT;
8130 goto unlock;
8131 }
Vikram Panduranga770b8382017-09-27 12:17:36 -07008132
8133 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308134 pr_debug("%s: Path = %d samplerate = %u usec = %u status %d\n",
8135 __func__, path, entry->sample_rate, entry->delay_usec, ret);
8136unlock:
8137 mutex_unlock(&this_afe.cal_data[AFE_HW_DELAY_CAL]->lock);
8138done:
8139 return ret;
8140}
8141
Laxminath Kasam2e13d952019-02-20 15:05:39 +05308142static int afe_set_cal_sp_th_vi_v_vali_cfg(int32_t cal_type, size_t data_size,
8143 void *data)
8144{
8145 int ret = 0;
8146 struct audio_cal_type_sp_th_vi_v_vali_cfg *cal_data = data;
8147
8148 if (cal_data == NULL || data_size != sizeof(*cal_data))
8149 goto done;
8150
8151 memcpy(&this_afe.v_vali_cfg, &cal_data->cal_info,
8152 sizeof(this_afe.v_vali_cfg));
8153done:
8154 return ret;
8155}
8156
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308157static int afe_set_cal_sp_th_vi_ftm_cfg(int32_t cal_type, size_t data_size,
8158 void *data)
8159{
8160 int ret = 0;
8161 struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data;
8162
Laxminath Kasam2e13d952019-02-20 15:05:39 +05308163 if (cal_data == NULL || data_size != sizeof(*cal_data))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308164 goto done;
8165
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308166 memcpy(&this_afe.th_ftm_cfg, &cal_data->cal_info,
8167 sizeof(this_afe.th_ftm_cfg));
Laxminath Kasam2e13d952019-02-20 15:05:39 +05308168done:
8169 return ret;
8170}
8171
8172static int afe_set_cal_sp_th_vi_cfg(int32_t cal_type, size_t data_size,
8173 void *data)
8174{
8175 int ret = 0;
8176 struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data;
8177 uint32_t mode;
8178
8179 if (cal_data == NULL ||
8180 this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL)
8181 goto done;
8182
8183 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
8184 mode = cal_data->cal_info.mode;
8185 pr_debug("%s: cal_type = %d, mode = %d\n", __func__, cal_type, mode);
8186 if (mode == MSM_SPKR_PROT_IN_FTM_MODE) {
8187 ret = afe_set_cal_sp_th_vi_ftm_cfg(cal_type,
8188 data_size, data);
8189 } else if (mode == MSM_SPKR_PROT_IN_V_VALI_MODE) {
8190 ret = afe_set_cal_sp_th_vi_v_vali_cfg(cal_type,
8191 data_size, data);
8192 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308193 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
8194done:
8195 return ret;
8196}
8197
8198static int afe_set_cal_sp_ex_vi_ftm_cfg(int32_t cal_type, size_t data_size,
8199 void *data)
8200{
8201 int ret = 0;
8202 struct audio_cal_type_sp_ex_vi_ftm_cfg *cal_data = data;
8203
8204 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
8205 cal_data == NULL ||
8206 data_size != sizeof(*cal_data))
8207 goto done;
8208
8209 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
8210 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
8211 memcpy(&this_afe.ex_ftm_cfg, &cal_data->cal_info,
8212 sizeof(this_afe.ex_ftm_cfg));
8213 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
8214done:
8215 return ret;
8216}
8217
8218static int afe_set_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
8219 void *data)
8220{
8221 int ret = 0;
8222 struct audio_cal_type_fb_spk_prot_cfg *cal_data = data;
8223
8224 pr_debug("%s:\n", __func__);
8225
8226 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
8227 goto done;
8228 if (cal_data == NULL)
8229 goto done;
8230 if (data_size != sizeof(*cal_data))
8231 goto done;
8232
8233 if (cal_data->cal_info.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
8234 __pm_wakeup_event(&wl.ws, jiffies_to_msecs(WAKELOCK_TIMEOUT));
8235 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
8236 memcpy(&this_afe.prot_cfg, &cal_data->cal_info,
8237 sizeof(this_afe.prot_cfg));
8238 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
8239done:
8240 return ret;
8241}
8242
Laxminath Kasam2e13d952019-02-20 15:05:39 +05308243static int afe_get_cal_sp_th_vi_v_vali_param(int32_t cal_type, size_t data_size,
8244 void *data)
8245{
8246 int i, ret = 0;
8247 struct audio_cal_type_sp_th_vi_v_vali_param *cal_data = data;
8248 struct afe_sp_th_vi_v_vali_get_param th_vi_v_vali;
8249
8250 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
8251 cal_data == NULL ||
8252 data_size != sizeof(*cal_data))
8253 goto done;
8254
8255 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
8256 cal_data->cal_info.status[i] = -EINVAL;
8257 cal_data->cal_info.vrms_q24[i] = -1;
8258 }
8259 if (!afe_get_sp_th_vi_v_vali_data(&th_vi_v_vali)) {
8260 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
8261 pr_debug("%s: v-vali param status = %d\n",
8262 __func__, th_vi_v_vali.param.status[i]);
8263 if (th_vi_v_vali.param.status[i] ==
8264 V_VALI_IN_PROGRESS) {
8265 cal_data->cal_info.status[i] = -EAGAIN;
8266 } else if (th_vi_v_vali.param.status[i] ==
8267 V_VALI_SUCCESS) {
8268 cal_data->cal_info.status[i] = V_VALI_SUCCESS;
8269 cal_data->cal_info.vrms_q24[i] =
8270 th_vi_v_vali.param.vrms_q24[i];
8271 }
8272 }
8273 }
Laxminath Kasam36384ec2019-02-18 21:57:19 +05308274 this_afe.v_vali_flag = 0;
Laxminath Kasam2e13d952019-02-20 15:05:39 +05308275done:
8276 return ret;
8277}
8278
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308279static int afe_get_cal_sp_th_vi_ftm_param(int32_t cal_type, size_t data_size,
8280 void *data)
8281{
8282 int i, ret = 0;
8283 struct audio_cal_type_sp_th_vi_param *cal_data = data;
8284 struct afe_sp_th_vi_get_param th_vi;
8285
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308286 if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
8287 cal_data == NULL ||
8288 data_size != sizeof(*cal_data))
8289 goto done;
8290
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308291 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
8292 cal_data->cal_info.status[i] = -EINVAL;
8293 cal_data->cal_info.r_dc_q24[i] = -1;
8294 cal_data->cal_info.temp_q22[i] = -1;
8295 }
8296 if (!afe_get_sp_th_vi_ftm_data(&th_vi)) {
8297 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
8298 pr_debug("%s: ftm param status = %d\n",
8299 __func__, th_vi.param.status[i]);
8300 if (th_vi.param.status[i] == FBSP_IN_PROGRESS) {
8301 cal_data->cal_info.status[i] = -EAGAIN;
8302 } else if (th_vi.param.status[i] == FBSP_SUCCESS) {
8303 cal_data->cal_info.status[i] = 0;
8304 cal_data->cal_info.r_dc_q24[i] =
8305 th_vi.param.dc_res_q24[i];
8306 cal_data->cal_info.temp_q22[i] =
8307 th_vi.param.temp_q22[i];
8308 }
8309 }
8310 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308311done:
8312 return ret;
8313}
8314
Laxminath Kasam2e13d952019-02-20 15:05:39 +05308315static int afe_get_cal_sp_th_vi_param(int32_t cal_type, size_t data_size,
8316 void *data)
8317{
8318 struct audio_cal_type_sp_th_vi_param *cal_data = data;
8319 uint32_t mode;
8320 int ret = 0;
8321
8322 if (cal_data == NULL ||
8323 this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL)
8324 return 0;
8325
8326 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
8327 mode = cal_data->cal_info.mode;
8328 pr_debug("%s: cal_type = %d,mode = %d\n", __func__, cal_type, mode);
8329 if (mode == MSM_SPKR_PROT_IN_V_VALI_MODE)
8330 ret = afe_get_cal_sp_th_vi_v_vali_param(cal_type,
8331 data_size, data);
8332 else
8333 ret = afe_get_cal_sp_th_vi_ftm_param(cal_type,
8334 data_size, data);
8335 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
8336 return ret;
8337}
8338
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308339static int afe_get_cal_sp_ex_vi_ftm_param(int32_t cal_type, size_t data_size,
8340 void *data)
8341{
8342 int i, ret = 0;
8343 struct audio_cal_type_sp_ex_vi_param *cal_data = data;
8344 struct afe_sp_ex_vi_get_param ex_vi;
8345
8346 pr_debug("%s: cal_type = %d\n", __func__, cal_type);
8347 if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL ||
8348 cal_data == NULL ||
8349 data_size != sizeof(*cal_data))
8350 goto done;
8351
8352 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
8353 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
8354 cal_data->cal_info.status[i] = -EINVAL;
8355 cal_data->cal_info.freq_q20[i] = -1;
8356 cal_data->cal_info.resis_q24[i] = -1;
8357 cal_data->cal_info.qmct_q24[i] = -1;
8358 }
8359 if (!afe_get_sp_ex_vi_ftm_data(&ex_vi)) {
8360 for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
8361 pr_debug("%s: ftm param status = %d\n",
8362 __func__, ex_vi.param.status[i]);
8363 if (ex_vi.param.status[i] == FBSP_IN_PROGRESS) {
8364 cal_data->cal_info.status[i] = -EAGAIN;
8365 } else if (ex_vi.param.status[i] == FBSP_SUCCESS) {
8366 cal_data->cal_info.status[i] = 0;
8367 cal_data->cal_info.freq_q20[i] =
8368 ex_vi.param.freq_q20[i];
8369 cal_data->cal_info.resis_q24[i] =
8370 ex_vi.param.resis_q24[i];
8371 cal_data->cal_info.qmct_q24[i] =
8372 ex_vi.param.qmct_q24[i];
8373 }
8374 }
8375 }
8376 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock);
8377done:
8378 return ret;
8379}
8380
8381static int afe_get_cal_fb_spkr_prot(int32_t cal_type, size_t data_size,
8382 void *data)
8383{
8384 int ret = 0;
8385 struct audio_cal_type_fb_spk_prot_status *cal_data = data;
8386 struct afe_spkr_prot_get_vi_calib calib_resp;
8387
8388 pr_debug("%s:\n", __func__);
8389
8390 if (this_afe.cal_data[AFE_FB_SPKR_PROT_CAL] == NULL)
8391 goto done;
8392 if (cal_data == NULL)
8393 goto done;
8394 if (data_size != sizeof(*cal_data))
8395 goto done;
8396
8397 mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
8398 if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATED) {
8399 cal_data->cal_info.r0[SP_V2_SPKR_1] =
8400 this_afe.prot_cfg.r0[SP_V2_SPKR_1];
8401 cal_data->cal_info.r0[SP_V2_SPKR_2] =
8402 this_afe.prot_cfg.r0[SP_V2_SPKR_2];
8403 cal_data->cal_info.status = 0;
8404 } else if (this_afe.prot_cfg.mode ==
8405 MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
8406 /*Call AFE to query the status*/
8407 cal_data->cal_info.status = -EINVAL;
8408 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
8409 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
8410 if (!afe_spk_prot_get_calib_data(&calib_resp)) {
8411 if (calib_resp.res_cfg.th_vi_ca_state ==
8412 FBSP_IN_PROGRESS)
8413 cal_data->cal_info.status = -EAGAIN;
8414 else if (calib_resp.res_cfg.th_vi_ca_state ==
8415 FBSP_SUCCESS) {
8416 cal_data->cal_info.status = 0;
8417 cal_data->cal_info.r0[SP_V2_SPKR_1] =
8418 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_1];
8419 cal_data->cal_info.r0[SP_V2_SPKR_2] =
8420 calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_2];
8421 }
8422 }
8423 if (!cal_data->cal_info.status) {
8424 this_afe.prot_cfg.mode =
8425 MSM_SPKR_PROT_CALIBRATED;
8426 this_afe.prot_cfg.r0[SP_V2_SPKR_1] =
8427 cal_data->cal_info.r0[SP_V2_SPKR_1];
8428 this_afe.prot_cfg.r0[SP_V2_SPKR_2] =
8429 cal_data->cal_info.r0[SP_V2_SPKR_2];
8430 }
8431 } else {
8432 /*Indicates calibration data is invalid*/
8433 cal_data->cal_info.status = -EINVAL;
8434 cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
8435 cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
8436 }
Laxminath Kasam36384ec2019-02-18 21:57:19 +05308437 this_afe.initial_cal = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308438 mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
8439 __pm_relax(&wl.ws);
8440done:
8441 return ret;
8442}
8443
8444static int afe_map_cal_data(int32_t cal_type,
8445 struct cal_block_data *cal_block)
8446{
8447 int ret = 0;
8448 int cal_index;
8449
8450 pr_debug("%s:\n", __func__);
8451
8452 cal_index = get_cal_type_index(cal_type);
8453 if (cal_index < 0) {
8454 pr_err("%s: could not get cal index %d!\n",
8455 __func__, cal_index);
8456 ret = -EINVAL;
8457 goto done;
8458 }
8459
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308460 atomic_set(&this_afe.mem_map_cal_index, cal_index);
8461 ret = afe_cmd_memory_map(cal_block->cal_data.paddr,
8462 cal_block->map_data.map_size);
8463 atomic_set(&this_afe.mem_map_cal_index, -1);
8464 if (ret < 0) {
8465 pr_err("%s: mmap did not work! size = %zd ret %d\n",
8466 __func__,
8467 cal_block->map_data.map_size, ret);
8468 pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n",
8469 __func__,
8470 &cal_block->cal_data.paddr,
8471 cal_block->map_data.map_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308472 goto done;
8473 }
8474 cal_block->map_data.q6map_handle = atomic_read(&this_afe.
8475 mem_map_cal_handles[cal_index]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308476done:
8477 return ret;
8478}
8479
8480static int afe_unmap_cal_data(int32_t cal_type,
8481 struct cal_block_data *cal_block)
8482{
8483 int ret = 0;
8484 int cal_index;
8485
8486 pr_debug("%s:\n", __func__);
8487
8488 cal_index = get_cal_type_index(cal_type);
8489 if (cal_index < 0) {
8490 pr_err("%s: could not get cal index %d!\n",
8491 __func__, cal_index);
8492 ret = -EINVAL;
8493 goto done;
8494 }
8495
8496 if (cal_block == NULL) {
8497 pr_err("%s: Cal block is NULL!\n",
8498 __func__);
8499 goto done;
8500 }
8501
8502 if (cal_block->map_data.q6map_handle == 0) {
8503 pr_err("%s: Map handle is NULL, nothing to unmap\n",
8504 __func__);
8505 goto done;
8506 }
8507
8508 atomic_set(&this_afe.mem_map_cal_handles[cal_index],
8509 cal_block->map_data.q6map_handle);
8510 atomic_set(&this_afe.mem_map_cal_index, cal_index);
8511 ret = afe_cmd_memory_unmap_nowait(
8512 cal_block->map_data.q6map_handle);
8513 atomic_set(&this_afe.mem_map_cal_index, -1);
8514 if (ret < 0) {
8515 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
8516 __func__, cal_index, ret);
8517 }
8518 cal_block->map_data.q6map_handle = 0;
8519done:
8520 return ret;
8521}
8522
8523static void afe_delete_cal_data(void)
8524{
8525 pr_debug("%s:\n", __func__);
8526
8527 cal_utils_destroy_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data);
8528}
8529
8530static int afe_init_cal_data(void)
8531{
8532 int ret = 0;
8533 struct cal_type_info cal_type_info[] = {
8534 {{AFE_COMMON_RX_CAL_TYPE,
8535 {afe_alloc_cal, afe_dealloc_cal, NULL,
8536 afe_set_cal, NULL, NULL} },
8537 {afe_map_cal_data, afe_unmap_cal_data,
8538 cal_utils_match_buf_num} },
8539
8540 {{AFE_COMMON_TX_CAL_TYPE,
8541 {afe_alloc_cal, afe_dealloc_cal, NULL,
8542 afe_set_cal, NULL, NULL} },
8543 {afe_map_cal_data, afe_unmap_cal_data,
8544 cal_utils_match_buf_num} },
8545
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05308546 {{AFE_LSM_TX_CAL_TYPE,
8547 {afe_alloc_cal, afe_dealloc_cal, NULL,
8548 afe_set_cal, NULL, NULL} },
8549 {afe_map_cal_data, afe_unmap_cal_data,
8550 cal_utils_match_buf_num} },
8551
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308552 {{AFE_AANC_CAL_TYPE,
8553 {afe_alloc_cal, afe_dealloc_cal, NULL,
8554 afe_set_cal, NULL, NULL} },
8555 {afe_map_cal_data, afe_unmap_cal_data,
8556 cal_utils_match_buf_num} },
8557
8558 {{AFE_FB_SPKR_PROT_CAL_TYPE,
8559 {NULL, NULL, NULL, afe_set_cal_fb_spkr_prot,
8560 afe_get_cal_fb_spkr_prot, NULL} },
8561 {NULL, NULL, cal_utils_match_buf_num} },
8562
8563 {{AFE_HW_DELAY_CAL_TYPE,
8564 {NULL, NULL, NULL,
8565 afe_set_cal, NULL, NULL} },
8566 {NULL, NULL, cal_utils_match_buf_num} },
8567
8568 {{AFE_SIDETONE_CAL_TYPE,
8569 {NULL, NULL, NULL,
8570 afe_set_cal, NULL, NULL} },
8571 {NULL, NULL, cal_utils_match_buf_num} },
8572
8573 {{AFE_SIDETONE_IIR_CAL_TYPE,
8574 {NULL, NULL, NULL,
8575 afe_set_cal, NULL, NULL} },
8576 {NULL, NULL, cal_utils_match_buf_num} },
8577
8578 {{AFE_TOPOLOGY_CAL_TYPE,
8579 {NULL, NULL, NULL,
8580 afe_set_cal, NULL, NULL} },
8581 {NULL, NULL,
8582 cal_utils_match_buf_num} },
8583
Aditya Bavanari3889b4a2017-11-21 19:52:26 +05308584 {{AFE_LSM_TOPOLOGY_CAL_TYPE,
8585 {NULL, NULL, NULL,
8586 afe_set_cal, NULL, NULL} },
8587 {NULL, NULL,
8588 cal_utils_match_buf_num} },
8589
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308590 {{AFE_CUST_TOPOLOGY_CAL_TYPE,
8591 {afe_alloc_cal, afe_dealloc_cal, NULL,
8592 afe_set_cal, NULL, NULL} },
8593 {afe_map_cal_data, afe_unmap_cal_data,
8594 cal_utils_match_buf_num} },
8595
8596 {{AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE,
Laxminath Kasam2e13d952019-02-20 15:05:39 +05308597 {NULL, NULL, NULL, afe_set_cal_sp_th_vi_cfg,
8598 afe_get_cal_sp_th_vi_param, NULL} },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308599 {NULL, NULL, cal_utils_match_buf_num} },
8600
8601 {{AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE,
8602 {NULL, NULL, NULL, afe_set_cal_sp_ex_vi_ftm_cfg,
8603 afe_get_cal_sp_ex_vi_ftm_param, NULL} },
8604 {NULL, NULL, cal_utils_match_buf_num} },
8605 };
8606 pr_debug("%s:\n", __func__);
8607
8608 ret = cal_utils_create_cal_types(MAX_AFE_CAL_TYPES, this_afe.cal_data,
8609 cal_type_info);
8610 if (ret < 0) {
8611 pr_err("%s: could not create cal type! %d\n",
8612 __func__, ret);
8613 ret = -EINVAL;
8614 goto err;
8615 }
8616
8617 return ret;
8618err:
8619 afe_delete_cal_data();
8620 return ret;
8621}
8622
8623int afe_map_rtac_block(struct rtac_cal_block_data *cal_block)
8624{
8625 int result = 0;
8626
8627 pr_debug("%s:\n", __func__);
8628
8629 if (cal_block == NULL) {
8630 pr_err("%s: cal_block is NULL!\n",
8631 __func__);
8632 result = -EINVAL;
8633 goto done;
8634 }
8635
8636 if (cal_block->cal_data.paddr == 0) {
8637 pr_debug("%s: No address to map!\n",
8638 __func__);
8639 result = -EINVAL;
8640 goto done;
8641 }
8642
8643 if (cal_block->map_data.map_size == 0) {
8644 pr_debug("%s: map size is 0!\n",
8645 __func__);
8646 result = -EINVAL;
8647 goto done;
8648 }
8649
8650 result = afe_cmd_memory_map(cal_block->cal_data.paddr,
8651 cal_block->map_data.map_size);
8652 if (result < 0) {
8653 pr_err("%s: afe_cmd_memory_map failed for addr = 0x%pK, size = %d, err %d\n",
8654 __func__, &cal_block->cal_data.paddr,
8655 cal_block->map_data.map_size, result);
8656 return result;
8657 }
8658 cal_block->map_data.map_handle = this_afe.mmap_handle;
8659
8660done:
8661 return result;
8662}
8663
8664int afe_unmap_rtac_block(uint32_t *mem_map_handle)
8665{
8666 int result = 0;
8667
8668 pr_debug("%s:\n", __func__);
8669
8670 if (mem_map_handle == NULL) {
8671 pr_err("%s: Map handle is NULL, nothing to unmap\n",
8672 __func__);
8673 goto done;
8674 }
8675
8676 if (*mem_map_handle == 0) {
8677 pr_debug("%s: Map handle is 0, nothing to unmap\n",
8678 __func__);
8679 goto done;
8680 }
8681
8682 result = afe_cmd_memory_unmap(*mem_map_handle);
8683 if (result) {
8684 pr_err("%s: AFE memory unmap failed %d, handle 0x%x\n",
8685 __func__, result, *mem_map_handle);
8686 goto done;
8687 } else {
8688 *mem_map_handle = 0;
8689 }
8690
8691done:
8692 return result;
8693}
8694
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -07008695static void afe_release_uevent_data(struct kobject *kobj)
8696{
8697 struct audio_uevent_data *data = container_of(kobj,
8698 struct audio_uevent_data, kobj);
8699
8700 kfree(data);
8701}
8702
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308703int __init afe_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308704{
8705 int i = 0, ret;
8706
8707 atomic_set(&this_afe.state, 0);
8708 atomic_set(&this_afe.status, 0);
8709 atomic_set(&this_afe.mem_map_cal_index, -1);
8710 this_afe.apr = NULL;
8711 this_afe.dtmf_gen_rx_portid = -1;
8712 this_afe.mmap_handle = 0;
8713 this_afe.vi_tx_port = -1;
8714 this_afe.vi_rx_port = -1;
8715 this_afe.prot_cfg.mode = MSM_SPKR_PROT_DISABLED;
8716 this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
8717 this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
8718 mutex_init(&this_afe.afe_cmd_lock);
8719 for (i = 0; i < AFE_MAX_PORTS; i++) {
8720 this_afe.afe_cal_mode[i] = AFE_CAL_MODE_DEFAULT;
8721 this_afe.afe_sample_rates[i] = 0;
8722 this_afe.dev_acdb_id[i] = 0;
Mangesh Kunchamwar4e1e7182018-04-26 17:58:58 +05308723 this_afe.island_mode[i] = 0;
8724 this_afe.vad_cfg[i].is_enable = 0;
8725 this_afe.vad_cfg[i].pre_roll = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308726 init_waitqueue_head(&this_afe.wait[i]);
8727 }
Ramprasad Katkam250075f2018-08-31 03:31:54 +05308728 init_waitqueue_head(&this_afe.wait_wakeup);
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +05308729 init_waitqueue_head(&this_afe.lpass_core_hw_wait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308730 wakeup_source_init(&wl.ws, "spkr-prot");
8731 ret = afe_init_cal_data();
8732 if (ret)
8733 pr_err("%s: could not init cal data! %d\n", __func__, ret);
8734
8735 config_debug_fs_init();
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -07008736
8737 this_afe.uevent_data = kzalloc(sizeof(*(this_afe.uevent_data)), GFP_KERNEL);
8738 if (!this_afe.uevent_data)
8739 return -ENOMEM;
8740
8741 /*
8742 * Set release function to cleanup memory related to kobject
8743 * before initializing the kobject.
8744 */
8745 this_afe.uevent_data->ktype.release = afe_release_uevent_data;
8746 q6core_init_uevent_data(this_afe.uevent_data, "q6afe_uevent");
8747
Xiaoyu Yebaf28392018-06-22 15:22:27 -07008748 INIT_WORK(&this_afe.afe_dc_work, afe_notify_dc_presence_work_fn);
Ralf Herz044e4762018-09-10 11:04:16 +02008749 INIT_WORK(&this_afe.afe_spdif_work,
8750 afe_notify_spdif_fmt_update_work_fn);
Xiaoyu Yebaf28392018-06-22 15:22:27 -07008751
Ramprasad Katkam250075f2018-08-31 03:31:54 +05308752 this_afe.event_notifier.notifier_call = afe_aud_event_notify;
8753 msm_aud_evt_blocking_register_client(&this_afe.event_notifier);
8754
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308755 return 0;
8756}
8757
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05308758void afe_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308759{
Laxminath Kasam30ad7512017-11-28 12:40:22 +05308760 if (this_afe.apr) {
8761 apr_reset(this_afe.apr);
8762 atomic_set(&this_afe.state, 0);
8763 this_afe.apr = NULL;
8764 rtac_set_afe_handle(this_afe.apr);
8765 }
Vignesh Kulothunganc3f38982018-05-22 18:08:20 -07008766
8767 q6core_destroy_uevent_data(this_afe.uevent_data);
8768
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308769 afe_delete_cal_data();
8770
8771 config_debug_fs_exit();
8772 mutex_destroy(&this_afe.afe_cmd_lock);
8773 wakeup_source_trash(&wl.ws);
8774}
Mangesh Kunchamwar4e1e7182018-04-26 17:58:58 +05308775
8776/*
8777 * afe_cal_init_hwdep -
8778 * Initiliaze AFE HW dependent Node
8779 *
8780 * @card: pointer to sound card
8781 *
8782 */
8783int afe_cal_init_hwdep(void *card)
8784{
8785 int ret = 0;
8786
8787 this_afe.fw_data = kzalloc(sizeof(*(this_afe.fw_data)),
8788 GFP_KERNEL);
8789 if (!this_afe.fw_data)
8790 return -ENOMEM;
8791
8792 set_bit(Q6AFE_VAD_CORE_CAL, this_afe.fw_data->cal_bit);
8793 ret = q6afe_cal_create_hwdep(this_afe.fw_data, Q6AFE_HWDEP_NODE, card);
8794 if (ret < 0) {
8795 pr_err("%s: couldn't create hwdep for AFE %d\n", __func__, ret);
8796 return ret;
8797 }
8798 return ret;
8799}
8800EXPORT_SYMBOL(afe_cal_init_hwdep);
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +05308801
8802/*
8803 * afe_vote_lpass_core_hw -
8804 * Voting for lpass core hardware
8805 *
8806 * @hw_block_id: id of the hardware block
8807 * @client_name: client name
8808 * @client_handle: client handle
8809 *
8810 */
8811int afe_vote_lpass_core_hw(uint32_t hw_block_id, char *client_name,
8812 uint32_t *client_handle)
8813{
8814 struct afe_cmd_remote_lpass_core_hw_vote_request hw_vote_cfg;
8815 struct afe_cmd_remote_lpass_core_hw_vote_request *cmd_ptr =
8816 &hw_vote_cfg;
8817 int ret = 0;
8818
8819 if (!client_handle) {
8820 pr_err("%s: Invalid client_handle\n", __func__);
8821 return -EINVAL;
8822 }
8823
8824 if (!client_name) {
8825 pr_err("%s: Invalid client_name\n", __func__);
8826 *client_handle = 0;
8827 return -EINVAL;
8828 }
8829
Karthikeyan Mani5670cbd2019-03-21 18:00:51 -07008830 ret = afe_q6_interface_prepare();
8831 if(ret) {
8832 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
8833 return ret;
8834 }
8835
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +05308836 mutex_lock(&this_afe.afe_cmd_lock);
8837
8838 memset(cmd_ptr, 0, sizeof(hw_vote_cfg));
8839
8840 cmd_ptr->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
8841 APR_HDR_LEN(APR_HDR_SIZE),
8842 APR_PKT_VER);
8843 cmd_ptr->hdr.pkt_size = sizeof(hw_vote_cfg);
8844 cmd_ptr->hdr.src_port = 0;
8845 cmd_ptr->hdr.dest_port = 0;
8846 cmd_ptr->hdr.token = 0;
8847 cmd_ptr->hdr.opcode = AFE_CMD_REMOTE_LPASS_CORE_HW_VOTE_REQUEST;
8848 cmd_ptr->hw_block_id = hw_block_id;
8849 strlcpy(cmd_ptr->client_name, client_name,
8850 sizeof(cmd_ptr->client_name));
8851
8852 pr_debug("%s: lpass core hw vote opcode[0x%x] hw id[0x%x]\n",
8853 __func__, cmd_ptr->hdr.opcode, cmd_ptr->hw_block_id);
8854
8855 *client_handle = 0;
8856 atomic_set(&this_afe.status, 0);
8857 atomic_set(&this_afe.state, 1);
8858 ret = apr_send_pkt(this_afe.apr, (uint32_t *) cmd_ptr);
8859 if (ret < 0) {
8860 pr_err("%s: lpass core hw vote failed %d\n",
8861 __func__, ret);
8862 goto done;
8863 }
8864
8865 ret = wait_event_timeout(this_afe.lpass_core_hw_wait,
8866 (atomic_read(&this_afe.state) == 0),
8867 msecs_to_jiffies(TIMEOUT_MS));
8868 if (!ret) {
8869 pr_err("%s: timeout. waited for lpass core hw vote\n",
8870 __func__);
8871 ret = -ETIMEDOUT;
8872 goto done;
8873 } else {
8874 /* set ret to 0 as no timeout happened */
8875 ret = 0;
8876 }
8877
8878 if (atomic_read(&this_afe.status) > 0) {
8879 pr_err("%s: lpass core hw vote cmd failed [%s]\n",
8880 __func__, adsp_err_get_err_str(
8881 atomic_read(&this_afe.status)));
8882 ret = adsp_err_get_lnx_err_code(
8883 atomic_read(&this_afe.status));
8884 goto done;
8885 }
8886
8887 *client_handle = this_afe.lpass_hw_core_client_hdl;
8888 pr_debug("%s: lpass_hw_core_client_hdl %d\n", __func__,
8889 this_afe.lpass_hw_core_client_hdl);
8890done:
8891 mutex_unlock(&this_afe.afe_cmd_lock);
8892 return ret;
8893}
8894EXPORT_SYMBOL(afe_vote_lpass_core_hw);
8895
8896/*
8897 * afe_unvote_lpass_core_hw -
8898 * unvoting for lpass core hardware
8899 *
8900 * @hw_block_id: id of the hardware block
8901 * @client_handle: client handle
8902 *
8903 */
8904int afe_unvote_lpass_core_hw(uint32_t hw_block_id, uint32_t client_handle)
8905{
8906 struct afe_cmd_remote_lpass_core_hw_devote_request hw_vote_cfg;
8907 struct afe_cmd_remote_lpass_core_hw_devote_request *cmd_ptr =
8908 &hw_vote_cfg;
8909 int ret = 0;
8910
Karthikeyan Mani5670cbd2019-03-21 18:00:51 -07008911 ret = afe_q6_interface_prepare();
8912 if(ret) {
8913 pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
8914 return ret;
8915 }
8916
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +05308917 mutex_lock(&this_afe.afe_cmd_lock);
8918
8919 memset(cmd_ptr, 0, sizeof(hw_vote_cfg));
8920
8921 cmd_ptr->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
8922 APR_HDR_LEN(APR_HDR_SIZE),
8923 APR_PKT_VER);
8924 cmd_ptr->hdr.pkt_size = sizeof(hw_vote_cfg);
8925 cmd_ptr->hdr.src_port = 0;
8926 cmd_ptr->hdr.dest_port = 0;
8927 cmd_ptr->hdr.token = 0;
8928 cmd_ptr->hdr.opcode = AFE_CMD_REMOTE_LPASS_CORE_HW_DEVOTE_REQUEST;
8929 cmd_ptr->hw_block_id = hw_block_id;
8930 cmd_ptr->client_handle = client_handle;
8931
8932 pr_debug("%s: lpass core hw unvote opcode[0x%x] hw id[0x%x]\n",
8933 __func__, cmd_ptr->hdr.opcode, cmd_ptr->hw_block_id);
8934
8935 atomic_set(&this_afe.status, 0);
8936 atomic_set(&this_afe.state, 1);
8937 ret = apr_send_pkt(this_afe.apr, (uint32_t *) cmd_ptr);
8938 if (ret < 0) {
8939 pr_err("%s: lpass core hw devote failed %d\n",
8940 __func__, ret);
8941 goto done;
8942 }
8943
8944 ret = wait_event_timeout(this_afe.lpass_core_hw_wait,
8945 (atomic_read(&this_afe.state) == 0),
8946 msecs_to_jiffies(TIMEOUT_MS));
8947 if (!ret) {
8948 pr_err("%s: timeout. waited for lpass core hw devote\n",
8949 __func__);
8950 ret = -ETIMEDOUT;
8951 goto done;
8952 } else {
8953 /* set ret to 0 as no timeout happened */
8954 ret = 0;
8955 }
8956
8957 if (atomic_read(&this_afe.status) > 0) {
8958 pr_err("%s: lpass core hw devote cmd failed [%s]\n",
8959 __func__, adsp_err_get_err_str(
8960 atomic_read(&this_afe.status)));
8961 ret = adsp_err_get_lnx_err_code(
8962 atomic_read(&this_afe.status));
8963 }
8964
8965done:
8966 mutex_unlock(&this_afe.afe_cmd_lock);
8967 return ret;
8968}
8969EXPORT_SYMBOL(afe_unvote_lpass_core_hw);
8970