blob: 688012f727d9d71d4daeecc9a5bbf55d4d7f47d9 [file] [log] [blame]
Meng Wang688a8672019-01-29 13:43:33 +08001// SPDX-License-Identifier: GPL-2.0-only
Meng Wang61af6842018-09-10 17:47:55 +08002/*
Surendar Karkade79a062018-12-05 14:18:55 +05303 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304 */
5#include <linux/module.h>
6#include <linux/slab.h>
7#include <linux/wait.h>
8#include <linux/sched.h>
9#include <linux/jiffies.h>
10#include <linux/uaccess.h>
11#include <linux/atomic.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053012#include <sound/asound.h>
Laxminath Kasam8b1366a2017-10-05 01:44:16 +053013#include <dsp/msm-dts-srs-tm-config.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053014#include <dsp/apr_audio-v2.h>
15#include <dsp/q6adm-v2.h>
16#include <dsp/q6audio-v2.h>
17#include <dsp/q6afe-v2.h>
Dieter Luecking50c55352018-09-28 14:29:17 +020018#include <dsp/q6core.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053019#include <dsp/audio_cal_utils.h>
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -080020#include <dsp/q6common.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053021#include <ipc/apr.h>
22#include "adsp_err.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053023
24#define TIMEOUT_MS 1000
25
26#define RESET_COPP_ID 99
27#define INVALID_COPP_ID 0xFF
28/* Used for inband payload copy, max size is 4k */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -080029/* 3 is to account for module, instance & param ID in payload */
30#define ADM_GET_PARAMETER_LENGTH (4096 - APR_HDR_SIZE - 3 * sizeof(uint32_t))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053031
32#define ULL_SUPPORTED_BITS_PER_SAMPLE 16
33#define ULL_SUPPORTED_SAMPLE_RATE 48000
34
35#ifndef CONFIG_DOLBY_DAP
36#undef DOLBY_ADM_COPP_TOPOLOGY_ID
37#define DOLBY_ADM_COPP_TOPOLOGY_ID 0xFFFFFFFE
38#endif
39
40#ifndef CONFIG_DOLBY_DS2
41#undef DS2_ADM_COPP_TOPOLOGY_ID
42#define DS2_ADM_COPP_TOPOLOGY_ID 0xFFFFFFFF
43#endif
44
45/* ENUM for adm_status */
46enum adm_cal_status {
47 ADM_STATUS_CALIBRATION_REQUIRED = 0,
48 ADM_STATUS_MAX,
49};
50
51struct adm_copp {
52
53 atomic_t id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
54 atomic_t cnt[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
55 atomic_t topology[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
56 atomic_t mode[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
57 atomic_t stat[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
58 atomic_t rate[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
59 atomic_t bit_width[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
60 atomic_t channels[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
61 atomic_t app_type[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
62 atomic_t acdb_id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
Surendar Karkae7507512018-07-20 15:46:54 +053063 atomic_t session_type[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053064 wait_queue_head_t wait[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
65 wait_queue_head_t adm_delay_wait[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
66 atomic_t adm_delay_stat[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
67 uint32_t adm_delay[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
68 unsigned long adm_status[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
69};
70
71struct source_tracking_data {
Banajit Goswami08bb7362017-11-03 22:48:23 -070072 struct dma_buf *dma_buf;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053073 struct param_outband memmap;
74 int apr_cmd_status;
75};
76
77struct adm_ctl {
78 void *apr;
79
80 struct adm_copp copp;
81
82 atomic_t matrix_map_stat;
83 wait_queue_head_t matrix_map_wait;
84
85 atomic_t adm_stat;
86 wait_queue_head_t adm_wait;
87
88 struct cal_type_data *cal_data[ADM_MAX_CAL_TYPES];
89
90 atomic_t mem_map_handles[ADM_MEM_MAP_INDEX_MAX];
91 atomic_t mem_map_index;
92
93 struct param_outband outband_memmap;
94 struct source_tracking_data sourceTrackingData;
95
96 int set_custom_topology;
97 int ec_ref_rx;
98 int num_ec_ref_rx_chans;
99 int ec_ref_rx_bit_width;
100 int ec_ref_rx_sampling_rate;
Dieter Luecking50c55352018-09-28 14:29:17 +0200101
102 int native_mode;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530103};
104
105static struct adm_ctl this_adm;
106
107struct adm_multi_ch_map {
108 bool set_channel_map;
Dieter Luecking50c55352018-09-28 14:29:17 +0200109 char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530110};
111
112#define ADM_MCH_MAP_IDX_PLAYBACK 0
113#define ADM_MCH_MAP_IDX_REC 1
114static struct adm_multi_ch_map multi_ch_maps[2] = {
Dieter Luecking50c55352018-09-28 14:29:17 +0200115 { false,
116 {0, 0, 0, 0, 0, 0, 0, 0,
117 0, 0, 0, 0, 0, 0, 0, 0,
118 0, 0, 0, 0, 0, 0, 0, 0,
119 0, 0, 0, 0, 0, 0, 0, 0}
120 },
121 { false,
122 {0, 0, 0, 0, 0, 0, 0, 0,
123 0, 0, 0, 0, 0, 0, 0, 0,
124 0, 0, 0, 0, 0, 0, 0, 0,
125 0, 0, 0, 0, 0, 0, 0, 0}
126 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530127};
128
129static int adm_get_parameters[MAX_COPPS_PER_PORT * ADM_GET_PARAMETER_LENGTH];
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800130static int adm_module_topo_list[MAX_COPPS_PER_PORT *
131 ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH];
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530132static struct mutex dts_srs_lock;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530133
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530134void msm_dts_srs_acquire_lock(void)
135{
136 mutex_lock(&dts_srs_lock);
137}
138
139void msm_dts_srs_release_lock(void)
140{
141 mutex_unlock(&dts_srs_lock);
142}
143
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530144static int adm_arrange_mch_map_v8(
145 struct adm_device_endpoint_payload *ep_payload,
146 int path,
147 int channel_mode);
148
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530149/**
150 * adm_validate_and_get_port_index -
151 * validate given port id
152 *
153 * @port_id: Port ID number
154 *
155 * Returns valid index on success or error on failure
156 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530157int adm_validate_and_get_port_index(int port_id)
158{
159 int index;
160 int ret;
161
162 ret = q6audio_validate_port(port_id);
163 if (ret < 0) {
164 pr_err("%s: port validation failed id 0x%x ret %d\n",
165 __func__, port_id, ret);
166 return -EINVAL;
167 }
168
169 index = afe_get_port_index(port_id);
170 if (index < 0 || index >= AFE_MAX_PORTS) {
171 pr_err("%s: Invalid port idx %d port_id 0x%x\n",
172 __func__, index,
173 port_id);
174 return -EINVAL;
175 }
176 pr_debug("%s: port_idx- %d\n", __func__, index);
177 return index;
178}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530179EXPORT_SYMBOL(adm_validate_and_get_port_index);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530180
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530181/**
182 * adm_get_default_copp_idx -
183 * retrieve default copp_idx for given port
184 *
185 * @port_id: Port ID number
186 *
187 * Returns valid value on success or error on failure
188 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530189int adm_get_default_copp_idx(int port_id)
190{
191 int port_idx = adm_validate_and_get_port_index(port_id), idx;
192
193 if (port_idx < 0) {
194 pr_err("%s: Invalid port id: 0x%x", __func__, port_id);
195 return -EINVAL;
196 }
197 pr_debug("%s: port_idx:%d\n", __func__, port_idx);
198 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
199 if (atomic_read(&this_adm.copp.id[port_idx][idx]) !=
200 RESET_COPP_ID)
201 return idx;
202 }
203 return -EINVAL;
204}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530205EXPORT_SYMBOL(adm_get_default_copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530206
207int adm_get_topology_for_port_from_copp_id(int port_id, int copp_id)
208{
209 int port_idx = adm_validate_and_get_port_index(port_id), idx;
210
211 if (port_idx < 0) {
212 pr_err("%s: Invalid port id: 0x%x", __func__, port_id);
213 return 0;
214 }
215 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
216 if (atomic_read(&this_adm.copp.id[port_idx][idx]) == copp_id)
217 return atomic_read(&this_adm.copp.topology[port_idx]
218 [idx]);
219 pr_err("%s: Invalid copp_id %d port_id 0x%x\n",
220 __func__, copp_id, port_id);
221 return 0;
222}
223
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530224/**
225 * adm_get_topology_for_port_copp_idx -
226 * retrieve topology of given port/copp_idx
227 *
228 * @port_id: Port ID number
229 * @copp_idx: copp index of ADM copp
230 *
231 * Returns valid value on success or 0 on failure
232 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530233int adm_get_topology_for_port_copp_idx(int port_id, int copp_idx)
234{
235 int port_idx = adm_validate_and_get_port_index(port_id);
236
237 if (port_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
238 pr_err("%s: Invalid port: 0x%x copp id: 0x%x",
239 __func__, port_id, copp_idx);
240 return 0;
241 }
242 return atomic_read(&this_adm.copp.topology[port_idx][copp_idx]);
243}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530244EXPORT_SYMBOL(adm_get_topology_for_port_copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530245
246int adm_get_indexes_from_copp_id(int copp_id, int *copp_idx, int *port_idx)
247{
248 int p_idx, c_idx;
249
250 for (p_idx = 0; p_idx < AFE_MAX_PORTS; p_idx++) {
251 for (c_idx = 0; c_idx < MAX_COPPS_PER_PORT; c_idx++) {
252 if (atomic_read(&this_adm.copp.id[p_idx][c_idx])
253 == copp_id) {
254 if (copp_idx != NULL)
255 *copp_idx = c_idx;
256 if (port_idx != NULL)
257 *port_idx = p_idx;
258 return 0;
259 }
260 }
261 }
262 return -EINVAL;
263}
264
265static int adm_get_copp_id(int port_idx, int copp_idx)
266{
267 pr_debug("%s: port_idx:%d copp_idx:%d\n", __func__, port_idx, copp_idx);
268
269 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
270 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
271 return -EINVAL;
272 }
273 return atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
274}
275
276static int adm_get_idx_if_copp_exists(int port_idx, int topology, int mode,
Surendar Karkae7507512018-07-20 15:46:54 +0530277 int rate, int bit_width, int app_type,
278 int session_type)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530279{
280 int idx;
281
282 pr_debug("%s: port_idx-%d, topology-0x%x, mode-%d, rate-%d, bit_width-%d\n",
283 __func__, port_idx, topology, mode, rate, bit_width);
284
285 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
286 if ((topology ==
287 atomic_read(&this_adm.copp.topology[port_idx][idx])) &&
288 (mode == atomic_read(&this_adm.copp.mode[port_idx][idx])) &&
289 (rate == atomic_read(&this_adm.copp.rate[port_idx][idx])) &&
290 (bit_width ==
291 atomic_read(&this_adm.copp.bit_width[port_idx][idx])) &&
Surendar Karkae7507512018-07-20 15:46:54 +0530292 (session_type ==
293 atomic_read(
294 &this_adm.copp.session_type[port_idx][idx])) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530295 (app_type ==
296 atomic_read(&this_adm.copp.app_type[port_idx][idx])))
297 return idx;
298 return -EINVAL;
299}
300
301static int adm_get_next_available_copp(int port_idx)
302{
303 int idx;
304
305 pr_debug("%s:\n", __func__);
306 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
307 pr_debug("%s: copp_id:0x%x port_idx:%d idx:%d\n", __func__,
308 atomic_read(&this_adm.copp.id[port_idx][idx]),
309 port_idx, idx);
310 if (atomic_read(&this_adm.copp.id[port_idx][idx]) ==
311 RESET_COPP_ID)
312 break;
313 }
314 return idx;
315}
316
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530317/**
318 * srs_trumedia_open -
319 * command to set SRS trumedia open
320 *
321 * @port_id: Port ID number
322 * @copp_idx: copp index of ADM copp
323 * @srs_tech_id: SRS tech index
324 * @srs_params: params pointer
325 *
326 * Returns 0 on success or error on failure
327 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530328int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id,
329 void *srs_params)
330{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800331 struct param_hdr_v3 param_hdr;
332 struct mem_mapping_hdr mem_hdr;
333 u32 total_param_size = 0;
334 bool outband = false;
335 int port_idx;
336 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530337
338 pr_debug("SRS - %s", __func__);
339
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800340 memset(&param_hdr, 0, sizeof(param_hdr));
341 memset(&mem_hdr, 0, sizeof(mem_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530342 port_id = afe_convert_virtual_to_portid(port_id);
343 port_idx = adm_validate_and_get_port_index(port_id);
344 if (port_idx < 0) {
345 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
346 return -EINVAL;
347 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800348
349 param_hdr.module_id = SRS_TRUMEDIA_MODULE_ID;
350 param_hdr.instance_id = INSTANCE_ID_0;
351
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530352 switch (srs_tech_id) {
353 case SRS_ID_GLOBAL: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800354 param_hdr.param_id = SRS_TRUMEDIA_PARAMS;
355 param_hdr.param_size =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530356 sizeof(struct srs_trumedia_params_GLOBAL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530357 break;
358 }
359 case SRS_ID_WOWHD: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800360 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_WOWHD;
361 param_hdr.param_size = sizeof(struct srs_trumedia_params_WOWHD);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530362 break;
363 }
364 case SRS_ID_CSHP: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800365 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_CSHP;
366 param_hdr.param_size = sizeof(struct srs_trumedia_params_CSHP);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530367 break;
368 }
369 case SRS_ID_HPF: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800370 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_HPF;
371 param_hdr.param_size = sizeof(struct srs_trumedia_params_HPF);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530372 break;
373 }
374 case SRS_ID_AEQ: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800375 u8 *update_params_ptr = (u8 *) this_adm.outband_memmap.kvaddr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530376
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800377 outband = true;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530378
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530379 if (update_params_ptr == NULL) {
380 pr_err("ADM_SRS_TRUMEDIA - %s: null memmap for AEQ params\n",
381 __func__);
382 ret = -EINVAL;
383 goto fail_cmd;
384 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530385
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800386 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_AEQ;
387 param_hdr.param_size = sizeof(struct srs_trumedia_params_AEQ);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530388
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800389 ret = q6common_pack_pp_params(update_params_ptr, &param_hdr,
390 srs_params, &total_param_size);
391 if (ret) {
392 pr_err("%s: Failed to pack param header and data, error %d\n",
393 __func__, ret);
394 goto fail_cmd;
395 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530396 break;
397 }
398 case SRS_ID_HL: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800399 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_HL;
400 param_hdr.param_size = sizeof(struct srs_trumedia_params_HL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530401 break;
402 }
403 case SRS_ID_GEQ: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800404 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_GEQ;
405 param_hdr.param_size = sizeof(struct srs_trumedia_params_GEQ);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530406 break;
407 }
408 default:
409 goto fail_cmd;
410 }
411
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530412 if (outband && this_adm.outband_memmap.paddr) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800413 mem_hdr.data_payload_addr_lsw =
414 lower_32_bits(this_adm.outband_memmap.paddr);
415 mem_hdr.data_payload_addr_msw =
416 msm_audio_populate_upper_32_bits(
417 this_adm.outband_memmap.paddr);
418 mem_hdr.mem_map_handle = atomic_read(
419 &this_adm.mem_map_handles[ADM_SRS_TRUMEDIA]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530420
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800421 ret = adm_set_pp_params(port_id, copp_idx, &mem_hdr, NULL,
422 total_param_size);
423 } else {
424 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx,
425 param_hdr,
426 (u8 *) srs_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530427 }
428
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800429 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530430 pr_err("SRS - %s: ADM enable for port %d failed\n", __func__,
431 port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530432
433fail_cmd:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530434 return ret;
435}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530436EXPORT_SYMBOL(srs_trumedia_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530437
438static int adm_populate_channel_weight(u16 *ptr,
439 struct msm_pcm_channel_mixer *ch_mixer,
440 int channel_index)
441{
442 u16 i, j, start_index = 0;
443
444 if (channel_index > ch_mixer->output_channel) {
445 pr_err("%s: channel index %d is larger than output_channel %d\n",
446 __func__, channel_index, ch_mixer->output_channel);
447 return -EINVAL;
448 }
449
450 for (i = 0; i < ch_mixer->output_channel; i++) {
451 pr_debug("%s: weight for output %d:", __func__, i);
452 for (j = 0; j < ADM_MAX_CHANNELS; j++)
453 pr_debug(" %d",
454 ch_mixer->channel_weight[i][j]);
455 pr_debug("\n");
456 }
457
458 for (i = 0; i < channel_index; ++i)
459 start_index += ch_mixer->input_channels[i];
460
461 for (i = 0; i < ch_mixer->output_channel; ++i) {
462 for (j = start_index;
463 j < start_index +
464 ch_mixer->input_channels[channel_index]; j++) {
465 *ptr = ch_mixer->channel_weight[i][j];
466 pr_debug("%s: ptr[%d][%d] = %d\n",
467 __func__, i, j, *ptr);
468 ptr++;
469 }
470 }
471
472 return 0;
473}
474
475/*
476 * adm_programable_channel_mixer
477 *
478 * Receives port_id, copp_idx, session_id, session_type, ch_mixer
479 * and channel_index to send ADM command to mix COPP data.
480 *
481 * port_id - Passed value, port_id for which backend is wanted
482 * copp_idx - Passed value, copp_idx for which COPP is wanted
483 * session_id - Passed value, session_id for which session is needed
484 * session_type - Passed value, session_type for RX or TX
485 * ch_mixer - Passed value, ch_mixer for which channel mixer config is needed
486 * channel_index - Passed value, channel_index for which channel is needed
487 */
488int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
489 int session_type,
490 struct msm_pcm_channel_mixer *ch_mixer,
491 int channel_index)
492{
493 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700494 struct param_hdr_v1 data_v5;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530495 int ret = 0, port_idx, sz = 0, param_size = 0;
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530496 struct adm_device_endpoint_payload ep_params = {0, 0, 0, {0}};
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530497 u16 *adm_pspd_params;
498 u16 *ptr;
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530499 int index = 0, i = 0, path_type = ADM_PATH_PLAYBACK;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530500
501 pr_debug("%s: port_id = %d\n", __func__, port_id);
502 port_id = afe_convert_virtual_to_portid(port_id);
503 port_idx = adm_validate_and_get_port_index(port_id);
504 if (port_idx < 0) {
505 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
506 return -EINVAL;
507 }
508 /*
509 * First 8 bytes are 4 bytes as rule number, 2 bytes as output
510 * channel and 2 bytes as input channel.
511 * 2 * ch_mixer->output_channel means output channel mapping.
512 * 2 * ch_mixer->input_channels[channel_index]) means input
513 * channel mapping.
514 * 2 * ch_mixer->input_channels[channel_index] *
515 * ch_mixer->output_channel) means the channel mixer weighting
516 * coefficients.
517 * param_size needs to be a multiple of 4 bytes.
518 */
519
520 param_size = 2 * (4 + ch_mixer->output_channel +
521 ch_mixer->input_channels[channel_index] +
522 ch_mixer->input_channels[channel_index] *
523 ch_mixer->output_channel);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530524 param_size = roundup(param_size, 4);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530525
526 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800527 sizeof(struct default_chmixer_param_id_coeff) +
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700528 sizeof(struct param_hdr_v1) + param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530529 pr_debug("%s: sz = %d\n", __func__, sz);
530 adm_params = kzalloc(sz, GFP_KERNEL);
531 if (!adm_params)
532 return -ENOMEM;
533
534 adm_params->payload_addr_lsw = 0;
535 adm_params->payload_addr_msw = 0;
536 adm_params->mem_map_handle = 0;
537 adm_params->direction = session_type;
538 adm_params->sessionid = session_id;
539 pr_debug("%s: copp_id = %d, session id %d\n", __func__,
540 atomic_read(&this_adm.copp.id[port_idx][copp_idx]),
541 session_id);
542 adm_params->deviceid = atomic_read(
543 &this_adm.copp.id[port_idx][copp_idx]);
544 adm_params->reserved = 0;
545
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800546 /*
547 * This module is internal to ADSP and cannot be configured with
548 * an instance id
549 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530550 data_v5.module_id = MTMX_MODULE_ID_DEFAULT_CHMIXER;
551 data_v5.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
552 data_v5.reserved = 0;
553 data_v5.param_size = param_size;
554 adm_params->payload_size =
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800555 sizeof(struct default_chmixer_param_id_coeff) +
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700556 sizeof(struct param_hdr_v1) + data_v5.param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530557 adm_pspd_params = (u16 *)((u8 *)adm_params +
558 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5));
559 memcpy(adm_pspd_params, &data_v5, sizeof(data_v5));
560
561 adm_pspd_params = (u16 *)((u8 *)adm_params +
562 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)
563 + sizeof(data_v5));
564
565 adm_pspd_params[0] = ch_mixer->rule;
566 adm_pspd_params[2] = ch_mixer->output_channel;
567 adm_pspd_params[3] = ch_mixer->input_channels[channel_index];
568 index = 4;
569
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530570 path_type = (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) ?
571 ADM_PATH_PLAYBACK : ADM_PATH_LIVE_REC;
572
573 if (ch_mixer->override_out_ch_map) {
574 memcpy(&adm_pspd_params[index], &ch_mixer->out_ch_map,
575 ch_mixer->output_channel * sizeof(uint16_t));
576 index += ch_mixer->output_channel;
577 } else {
578 ep_params.dev_num_channel = ch_mixer->output_channel;
579 adm_arrange_mch_map_v8(&ep_params, path_type, ep_params.dev_num_channel);
580 for (i = 0; i < ch_mixer->output_channel; i++)
581 adm_pspd_params[index++] = ep_params.dev_channel_mapping[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530582 }
583
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530584 if (ch_mixer->override_in_ch_map) {
585 memcpy(&adm_pspd_params[index], &ch_mixer->in_ch_map,
586 ch_mixer->input_channel * sizeof(uint16_t));
587 index += ch_mixer->input_channel;
588 } else {
589 ep_params.dev_num_channel = ch_mixer->input_channels[channel_index];
590 adm_arrange_mch_map_v8(&ep_params, path_type, ep_params.dev_num_channel);
591 for (i = 0; i < ch_mixer->input_channels[channel_index]; i++)
592 adm_pspd_params[index++] = ep_params.dev_channel_mapping[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530593 }
594
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530595 ret = adm_populate_channel_weight(&adm_pspd_params[index],
596 ch_mixer, channel_index);
Meng Wangd9fa69c2018-01-23 12:42:52 +0800597 if (ret) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530598 pr_err("%s: fail to get channel weight with error %d\n",
599 __func__, ret);
600 goto fail_cmd;
601 }
602
603 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
604 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
605 adm_params->hdr.src_svc = APR_SVC_ADM;
606 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
607 adm_params->hdr.src_port = port_id;
608 adm_params->hdr.dest_svc = APR_SVC_ADM;
609 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
610 adm_params->hdr.dest_port =
611 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
612 adm_params->hdr.token = port_idx << 16 | copp_idx;
613 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
614 adm_params->hdr.pkt_size = sz;
615 adm_params->payload_addr_lsw = 0;
616 adm_params->payload_addr_msw = 0;
617 adm_params->mem_map_handle = 0;
618 adm_params->reserved = 0;
619
620 ptr = (u16 *)adm_params;
621 for (index = 0; index < (sz / 2); index++)
622 pr_debug("%s: adm_params[%d] = 0x%x\n",
623 __func__, index, (unsigned int)ptr[index]);
624
625 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], 0);
626 ret = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
627 if (ret < 0) {
628 pr_err("%s: Set params failed port %d rc %d\n", __func__,
629 port_id, ret);
630 ret = -EINVAL;
631 goto fail_cmd;
632 }
633
634 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
635 atomic_read(
636 &this_adm.copp.stat[port_idx][copp_idx]) >= 0,
637 msecs_to_jiffies(TIMEOUT_MS));
638 if (!ret) {
639 pr_err("%s: set params timed out port = %d\n",
640 __func__, port_id);
641 ret = -ETIMEDOUT;
642 goto fail_cmd;
643 }
644 ret = 0;
645fail_cmd:
646 kfree(adm_params);
647
648 return ret;
649}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530650EXPORT_SYMBOL(adm_programable_channel_mixer);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530651
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530652/**
653 * adm_set_stereo_to_custom_stereo -
654 * command to update custom stereo
655 *
656 * @port_id: Port ID number
657 * @copp_idx: copp index of ADM copp
658 * @session_id: session id to be updated
659 * @params: params pointer
660 * @param_length: length of params
661 *
662 * Returns 0 on success or error on failure
663 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530664int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx,
665 unsigned int session_id, char *params,
666 uint32_t params_length)
667{
668 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
669 int sz, rc = 0, port_idx;
670
671 pr_debug("%s:\n", __func__);
672 port_id = afe_convert_virtual_to_portid(port_id);
673 port_idx = adm_validate_and_get_port_index(port_id);
674 if (port_idx < 0) {
675 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
676 return -EINVAL;
677 }
678
679 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
680 params_length;
681 adm_params = kzalloc(sz, GFP_KERNEL);
682 if (!adm_params) {
683 pr_err("%s, adm params memory alloc failed\n", __func__);
684 return -ENOMEM;
685 }
686
687 memcpy(((u8 *)adm_params +
688 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)),
689 params, params_length);
690 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
691 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
692 adm_params->hdr.pkt_size = sz;
693 adm_params->hdr.src_svc = APR_SVC_ADM;
694 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
695 adm_params->hdr.src_port = port_id;
696 adm_params->hdr.dest_svc = APR_SVC_ADM;
697 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
698 adm_params->hdr.dest_port = 0; /* Ignored */;
699 adm_params->hdr.token = port_idx << 16 | copp_idx;
700 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
701 adm_params->payload_addr_lsw = 0;
702 adm_params->payload_addr_msw = 0;
703 adm_params->mem_map_handle = 0;
704 adm_params->payload_size = params_length;
705 /* direction RX as 0 */
706 adm_params->direction = ADM_MATRIX_ID_AUDIO_RX;
707 /* session id for this cmd to be applied on */
708 adm_params->sessionid = session_id;
709 adm_params->deviceid =
710 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
711 adm_params->reserved = 0;
712 pr_debug("%s: deviceid %d, session_id %d, src_port %d, dest_port %d\n",
713 __func__, adm_params->deviceid, adm_params->sessionid,
714 adm_params->hdr.src_port, adm_params->hdr.dest_port);
715 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
716 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
717 if (rc < 0) {
718 pr_err("%s: Set params failed port = 0x%x rc %d\n",
719 __func__, port_id, rc);
720 rc = -EINVAL;
721 goto set_stereo_to_custom_stereo_return;
722 }
723 /* Wait for the callback */
724 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
725 atomic_read(&this_adm.copp.stat
726 [port_idx][copp_idx]) >= 0,
727 msecs_to_jiffies(TIMEOUT_MS));
728 if (!rc) {
729 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
730 port_id);
731 rc = -EINVAL;
732 goto set_stereo_to_custom_stereo_return;
733 } else if (atomic_read(&this_adm.copp.stat
734 [port_idx][copp_idx]) > 0) {
735 pr_err("%s: DSP returned error[%s]\n", __func__,
736 adsp_err_get_err_str(atomic_read(
737 &this_adm.copp.stat
738 [port_idx][copp_idx])));
739 rc = adsp_err_get_lnx_err_code(
740 atomic_read(&this_adm.copp.stat
741 [port_idx][copp_idx]));
742 goto set_stereo_to_custom_stereo_return;
743 }
744 rc = 0;
745set_stereo_to_custom_stereo_return:
746 kfree(adm_params);
747 return rc;
748}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530749EXPORT_SYMBOL(adm_set_stereo_to_custom_stereo);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530750
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800751/*
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -0700752 * adm_set_custom_chmix_cfg:
753 * Set the custom channel mixer configuration for ADM
754 *
755 * @port_id: Backend port id
756 * @copp_idx: ADM copp index
757 * @session_id: ID of the requesting session
758 * @params: Expected packaged params for channel mixer
759 * @params_length: Length of the params to be set
760 * @direction: RX or TX direction
761 * @stream_type: Audio or Listen stream type
762 */
763int adm_set_custom_chmix_cfg(int port_id, int copp_idx,
764 unsigned int session_id, char *params,
765 uint32_t params_length, int direction,
766 int stream_type)
767{
768 struct adm_cmd_set_pspd_mtmx_strtr_params_v6 *adm_params = NULL;
769 int sz, rc = 0, port_idx;
770
771 port_id = afe_convert_virtual_to_portid(port_id);
772 port_idx = adm_validate_and_get_port_index(port_id);
773 if (port_idx < 0) {
774 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
775 return -EINVAL;
776 }
777
778 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v6) +
779 params_length;
780 adm_params = kzalloc(sz, GFP_KERNEL);
781 if (!adm_params) {
782 pr_err("%s, adm params memory alloc failed\n", __func__);
783 return -ENOMEM;
784 }
785
786 memcpy(((u8 *)adm_params +
787 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v6)),
788 params, params_length);
789 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
790 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
791 adm_params->hdr.pkt_size = sz;
792 adm_params->hdr.src_svc = APR_SVC_ADM;
793 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
794 adm_params->hdr.src_port = port_id;
795 adm_params->hdr.dest_svc = APR_SVC_ADM;
796 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
797 adm_params->hdr.dest_port = 0; /* Ignored */;
798 adm_params->hdr.token = port_idx << 16 | copp_idx;
799 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6;
800 adm_params->payload_addr_lsw = 0;
801 adm_params->payload_addr_msw = 0;
802 adm_params->mem_map_handle = 0;
803 adm_params->payload_size = params_length;
804 adm_params->direction = direction;
805 /* session id for this cmd to be applied on */
806 adm_params->sessionid = session_id;
807 adm_params->deviceid =
808 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
809 /* connecting stream type i.e. lsm or asm */
810 adm_params->stream_type = stream_type;
811 pr_debug("%s: deviceid %d, session_id %d, src_port %d, dest_port %d\n",
812 __func__, adm_params->deviceid, adm_params->sessionid,
813 adm_params->hdr.src_port, adm_params->hdr.dest_port);
814 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
815 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
816 if (rc < 0) {
817 pr_err("%s: Set params failed port = 0x%x rc %d\n",
818 __func__, port_id, rc);
819 rc = -EINVAL;
820 goto exit;
821 }
822 /* Wait for the callback */
823 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
824 atomic_read(&this_adm.copp.stat
825 [port_idx][copp_idx]),
826 msecs_to_jiffies(TIMEOUT_MS));
827 if (!rc) {
828 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
829 port_id);
830 rc = -EINVAL;
831 goto exit;
832 } else if (atomic_read(&this_adm.copp.stat
833 [port_idx][copp_idx]) > 0) {
834 pr_err("%s: DSP returned error[%s]\n", __func__,
835 adsp_err_get_err_str(atomic_read(
836 &this_adm.copp.stat
837 [port_idx][copp_idx])));
838 rc = adsp_err_get_lnx_err_code(
839 atomic_read(&this_adm.copp.stat
840 [port_idx][copp_idx]));
841 goto exit;
842 }
843
844 rc = 0;
845exit:
846 kfree(adm_params);
847 return rc;
848}
849EXPORT_SYMBOL(adm_set_custom_chmix_cfg);
850
851/*
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800852 * With pre-packed data, only the opcode differes from V5 and V6.
853 * Use q6common_pack_pp_params to pack the data correctly.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530854 */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800855int adm_set_pp_params(int port_id, int copp_idx,
856 struct mem_mapping_hdr *mem_hdr, u8 *param_data,
857 u32 param_size)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530858{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800859 struct adm_cmd_set_pp_params *adm_set_params = NULL;
860 int size = 0;
861 int port_idx = 0;
862 atomic_t *copp_stat = NULL;
863 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530864
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530865 port_id = afe_convert_virtual_to_portid(port_id);
866 port_idx = adm_validate_and_get_port_index(port_id);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800867 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
868 pr_err("%s: Invalid port_idx 0x%x\n", __func__, port_idx);
869 return -EINVAL;
870 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
871 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530872 return -EINVAL;
873 }
874
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800875 /* Only add params_size in inband case */
876 size = sizeof(struct adm_cmd_set_pp_params);
877 if (param_data != NULL)
878 size += param_size;
879 adm_set_params = kzalloc(size, GFP_KERNEL);
880 if (!adm_set_params)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530881 return -ENOMEM;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800882
883 adm_set_params->apr_hdr.hdr_field =
884 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
885 APR_PKT_VER);
886 adm_set_params->apr_hdr.pkt_size = size;
887 adm_set_params->apr_hdr.src_svc = APR_SVC_ADM;
888 adm_set_params->apr_hdr.src_domain = APR_DOMAIN_APPS;
889 adm_set_params->apr_hdr.src_port = port_id;
890 adm_set_params->apr_hdr.dest_svc = APR_SVC_ADM;
891 adm_set_params->apr_hdr.dest_domain = APR_DOMAIN_ADSP;
892 adm_set_params->apr_hdr.dest_port =
893 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
894 adm_set_params->apr_hdr.token = port_idx << 16 | copp_idx;
895
896 if (q6common_is_instance_id_supported())
897 adm_set_params->apr_hdr.opcode = ADM_CMD_SET_PP_PARAMS_V6;
898 else
899 adm_set_params->apr_hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
900
901 adm_set_params->payload_size = param_size;
902
903 if (mem_hdr != NULL) {
904 /* Out of Band Case */
905 adm_set_params->mem_hdr = *mem_hdr;
906 } else if (param_data != NULL) {
907 /*
908 * In band case. Parameter data must be pre-packed with its
909 * header before calling this function. Use
910 * q6common_pack_pp_params to pack parameter data and header
911 * correctly.
912 */
913 memcpy(&adm_set_params->param_data, param_data, param_size);
914 } else {
915 pr_err("%s: Received NULL pointers for both memory header and param data\n",
916 __func__);
917 ret = -EINVAL;
918 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530919 }
920
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800921 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
922 atomic_set(copp_stat, -1);
923 ret = apr_send_pkt(this_adm.apr, (uint32_t *) adm_set_params);
924 if (ret < 0) {
925 pr_err("%s: Set params APR send failed port = 0x%x ret %d\n",
926 __func__, port_id, ret);
927 goto done;
928 }
929 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
930 atomic_read(copp_stat) >= 0,
931 msecs_to_jiffies(TIMEOUT_MS));
932 if (!ret) {
933 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
934 port_id);
935 ret = -ETIMEDOUT;
936 goto done;
937 }
938 if (atomic_read(copp_stat) > 0) {
939 pr_err("%s: DSP returned error[%s]\n", __func__,
940 adsp_err_get_err_str(atomic_read(copp_stat)));
941 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
942 goto done;
943 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530944
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800945 ret = 0;
946done:
947 kfree(adm_set_params);
948 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530949}
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800950EXPORT_SYMBOL(adm_set_pp_params);
951
952int adm_pack_and_set_one_pp_param(int port_id, int copp_idx,
953 struct param_hdr_v3 param_hdr, u8 *param_data)
954{
955 u8 *packed_data = NULL;
956 u32 total_size = 0;
957 int ret = 0;
958
959 total_size = sizeof(union param_hdrs) + param_hdr.param_size;
960 packed_data = kzalloc(total_size, GFP_KERNEL);
961 if (!packed_data)
962 return -ENOMEM;
963
964 ret = q6common_pack_pp_params(packed_data, &param_hdr, param_data,
965 &total_size);
966 if (ret) {
967 pr_err("%s: Failed to pack parameter data, error %d\n",
968 __func__, ret);
969 goto done;
970 }
971
972 ret = adm_set_pp_params(port_id, copp_idx, NULL, packed_data,
973 total_size);
974 if (ret)
975 pr_err("%s: Failed to set parameter data, error %d\n", __func__,
976 ret);
977done:
978 kfree(packed_data);
979 return ret;
980}
981EXPORT_SYMBOL(adm_pack_and_set_one_pp_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530982
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800983/*
984 * Only one parameter can be requested at a time. Therefore, packing and sending
985 * the request can be handled locally.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530986 */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800987int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id,
988 struct mem_mapping_hdr *mem_hdr,
989 struct param_hdr_v3 *param_hdr, u8 *returned_param_data)
990{
991 struct adm_cmd_get_pp_params adm_get_params;
992 int total_size = 0;
993 int get_param_array_sz = ARRAY_SIZE(adm_get_parameters);
994 int returned_param_size = 0;
995 int returned_param_size_in_bytes = 0;
996 int port_idx = 0;
997 int idx = 0;
998 atomic_t *copp_stat = NULL;
999 int ret = 0;
1000
1001 if (param_hdr == NULL) {
1002 pr_err("%s: Received NULL pointer for parameter header\n",
1003 __func__);
1004 return -EINVAL;
1005 }
1006
1007 port_id = afe_convert_virtual_to_portid(port_id);
1008 port_idx = adm_validate_and_get_port_index(port_id);
1009 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1010 pr_err("%s: Invalid port_idx 0x%x\n", __func__, port_idx);
1011 return -EINVAL;
1012 }
1013 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1014 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
1015 return -EINVAL;
1016 }
1017
1018 memset(&adm_get_params, 0, sizeof(adm_get_params));
1019
1020 if (mem_hdr != NULL)
1021 adm_get_params.mem_hdr = *mem_hdr;
1022
1023 q6common_pack_pp_params((u8 *) &adm_get_params.param_hdr, param_hdr,
1024 NULL, &total_size);
1025
1026 /* Pack APR header after filling body so total_size has correct value */
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001027 adm_get_params.apr_hdr.hdr_field =
1028 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1029 APR_PKT_VER);
1030 adm_get_params.apr_hdr.pkt_size = sizeof(adm_get_params);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001031 adm_get_params.apr_hdr.src_svc = APR_SVC_ADM;
1032 adm_get_params.apr_hdr.src_domain = APR_DOMAIN_APPS;
1033 adm_get_params.apr_hdr.src_port = port_id;
1034 adm_get_params.apr_hdr.dest_svc = APR_SVC_ADM;
1035 adm_get_params.apr_hdr.dest_domain = APR_DOMAIN_ADSP;
1036 adm_get_params.apr_hdr.dest_port =
1037 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1038 adm_get_params.apr_hdr.token =
1039 port_idx << 16 | client_id << 8 | copp_idx;
1040
1041 if (q6common_is_instance_id_supported())
1042 adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V6;
1043 else
1044 adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
1045
1046 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
1047 atomic_set(copp_stat, -1);
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001048
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001049 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_params);
Vidyakumar Athotae427c412018-06-16 00:02:46 -07001050 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001051 pr_err("%s: Get params APR send failed port = 0x%x ret %d\n",
1052 __func__, port_id, ret);
1053 ret = -EINVAL;
1054 goto done;
1055 }
1056 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1057 atomic_read(copp_stat) >= 0,
1058 msecs_to_jiffies(TIMEOUT_MS));
1059 if (!ret) {
1060 pr_err("%s: Get params timed out port = 0x%x\n", __func__,
1061 port_id);
1062 ret = -ETIMEDOUT;
1063 goto done;
1064 }
1065 if (atomic_read(copp_stat) > 0) {
1066 pr_err("%s: DSP returned error[%s]\n", __func__,
1067 adsp_err_get_err_str(atomic_read(copp_stat)));
1068 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
1069 goto done;
1070 }
1071
1072 ret = 0;
1073
1074 /* Copy data to caller if sent in band */
1075 if (!returned_param_data) {
1076 pr_debug("%s: Received NULL pointer for param destination, not copying payload\n",
1077 __func__);
1078 return 0;
1079 }
1080
1081 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
1082 returned_param_size = adm_get_parameters[idx];
1083 if (returned_param_size < 0 ||
1084 returned_param_size + idx + 1 > get_param_array_sz) {
1085 pr_err("%s: Invalid parameter size %d\n", __func__,
1086 returned_param_size);
1087 return -EINVAL;
1088 }
1089
1090 returned_param_size_in_bytes = returned_param_size * sizeof(uint32_t);
1091 if (param_hdr->param_size < returned_param_size_in_bytes) {
1092 pr_err("%s: Provided buffer is not big enough, provided buffer size(%d) size needed(%d)\n",
1093 __func__, param_hdr->param_size,
1094 returned_param_size_in_bytes);
1095 return -EINVAL;
1096 }
1097
1098 memcpy(returned_param_data, &adm_get_parameters[idx + 1],
1099 returned_param_size_in_bytes);
1100done:
1101 return ret;
1102}
1103EXPORT_SYMBOL(adm_get_pp_params);
1104
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001105int adm_get_pp_topo_module_list_v2(int port_id, int copp_idx,
1106 int32_t param_length,
1107 int32_t *returned_params)
1108{
1109 struct adm_cmd_get_pp_topo_module_list adm_get_module_list;
1110 bool iid_supported = q6common_is_instance_id_supported();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301111 int *topo_list;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001112 int num_modules = 0;
1113 int list_size = 0;
1114 int port_idx, idx;
1115 int i = 0;
1116 atomic_t *copp_stat = NULL;
1117 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301118
1119 pr_debug("%s : port_id %x", __func__, port_id);
1120 port_id = afe_convert_virtual_to_portid(port_id);
1121 port_idx = adm_validate_and_get_port_index(port_id);
1122 if (port_idx < 0) {
1123 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1124 return -EINVAL;
1125 }
1126
1127 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1128 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
1129 return -EINVAL;
1130 }
1131
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001132 memset(&adm_get_module_list, 0, sizeof(adm_get_module_list));
1133
1134 adm_get_module_list.apr_hdr.pkt_size = sizeof(adm_get_module_list);
1135 adm_get_module_list.apr_hdr.src_svc = APR_SVC_ADM;
1136 adm_get_module_list.apr_hdr.src_domain = APR_DOMAIN_APPS;
1137 adm_get_module_list.apr_hdr.src_port = port_id;
1138 adm_get_module_list.apr_hdr.dest_svc = APR_SVC_ADM;
1139 adm_get_module_list.apr_hdr.dest_domain = APR_DOMAIN_ADSP;
1140 adm_get_module_list.apr_hdr.dest_port =
1141 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1142 adm_get_module_list.apr_hdr.token = port_idx << 16 | copp_idx;
1143 /*
1144 * Out of band functionality is not currently utilized.
1145 * Assume in band.
1146 */
1147 if (iid_supported) {
1148 adm_get_module_list.apr_hdr.opcode =
1149 ADM_CMD_GET_PP_TOPO_MODULE_LIST_V2;
1150 adm_get_module_list.param_max_size = param_length;
1151 } else {
1152 adm_get_module_list.apr_hdr.opcode =
1153 ADM_CMD_GET_PP_TOPO_MODULE_LIST;
1154
1155 if (param_length > U16_MAX) {
1156 pr_err("%s: Invalid param length for V1 %d\n", __func__,
1157 param_length);
1158 return -EINVAL;
1159 }
1160 adm_get_module_list.param_max_size = param_length << 16;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301161 }
1162
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001163 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
1164 atomic_set(copp_stat, -1);
1165 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_module_list);
Vidyakumar Athotae427c412018-06-16 00:02:46 -07001166 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001167 pr_err("%s: APR send pkt failed for port_id: 0x%x failed ret %d\n",
1168 __func__, port_id, ret);
1169 ret = -EINVAL;
1170 goto done;
1171 }
1172 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1173 atomic_read(copp_stat) >= 0,
1174 msecs_to_jiffies(TIMEOUT_MS));
1175 if (!ret) {
1176 pr_err("%s: Timeout for port_id: 0x%x\n", __func__, port_id);
1177 ret = -ETIMEDOUT;
1178 goto done;
1179 }
1180 if (atomic_read(copp_stat) > 0) {
1181 pr_err("%s: DSP returned error[%s]\n", __func__,
1182 adsp_err_get_err_str(atomic_read(copp_stat)));
1183 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
1184 goto done;
1185 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301186
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001187 ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301188
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001189 if (returned_params) {
1190 /*
1191 * When processing ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST IID is
1192 * added since it is not present. Therefore, there is no need to
1193 * do anything different if IID is not supported here as it is
1194 * already taken care of.
1195 */
1196 idx = ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH * copp_idx;
1197 num_modules = adm_module_topo_list[idx];
1198 if (num_modules < 0 || num_modules > MAX_MODULES_IN_TOPO) {
1199 pr_err("%s: Invalid number of modules returned %d\n",
1200 __func__, num_modules);
1201 return -EINVAL;
1202 }
1203
1204 list_size = num_modules * sizeof(struct module_instance_info);
1205 if (param_length < list_size) {
1206 pr_err("%s: Provided buffer not big enough to hold module-instance list, provided size %d, needed size %d\n",
1207 __func__, param_length, list_size);
1208 return -EINVAL;
1209 }
1210
1211 topo_list = (int32_t *) (&adm_module_topo_list[idx]);
1212 memcpy(returned_params, topo_list, list_size);
1213 for (i = 1; i <= num_modules; i += 2) {
1214 pr_debug("module = 0x%x instance = 0x%x\n",
1215 returned_params[i], returned_params[i + 1]);
1216 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301217 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001218done:
1219 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301220}
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001221EXPORT_SYMBOL(adm_get_pp_topo_module_list_v2);
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301222
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301223static void adm_callback_debug_print(struct apr_client_data *data)
1224{
1225 uint32_t *payload;
1226
1227 payload = data->payload;
1228
1229 if (data->payload_size >= 8)
1230 pr_debug("%s: code = 0x%x PL#0[0x%x], PL#1[0x%x], size = %d\n",
1231 __func__, data->opcode, payload[0], payload[1],
1232 data->payload_size);
1233 else if (data->payload_size >= 4)
1234 pr_debug("%s: code = 0x%x PL#0[0x%x], size = %d\n",
1235 __func__, data->opcode, payload[0],
1236 data->payload_size);
1237 else
1238 pr_debug("%s: code = 0x%x, size = %d\n",
1239 __func__, data->opcode, data->payload_size);
1240}
1241
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301242/**
1243 * adm_set_multi_ch_map -
1244 * Update multi channel map info
1245 *
1246 * @channel_map: pointer with channel map info
1247 * @path: direction or ADM path type
1248 *
1249 * Returns 0 on success or error on failure
1250 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301251int adm_set_multi_ch_map(char *channel_map, int path)
1252{
1253 int idx;
1254
1255 if (path == ADM_PATH_PLAYBACK) {
1256 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1257 } else if (path == ADM_PATH_LIVE_REC) {
1258 idx = ADM_MCH_MAP_IDX_REC;
1259 } else {
1260 pr_err("%s: invalid attempt to set path %d\n", __func__, path);
1261 return -EINVAL;
1262 }
1263
1264 memcpy(multi_ch_maps[idx].channel_mapping, channel_map,
Dieter Luecking50c55352018-09-28 14:29:17 +02001265 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301266 multi_ch_maps[idx].set_channel_map = true;
1267
1268 return 0;
1269}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301270EXPORT_SYMBOL(adm_set_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301271
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301272/**
1273 * adm_get_multi_ch_map -
1274 * Retrieves multi channel map info
1275 *
1276 * @channel_map: pointer to be updated with channel map
1277 * @path: direction or ADM path type
1278 *
1279 * Returns 0 on success or error on failure
1280 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301281int adm_get_multi_ch_map(char *channel_map, int path)
1282{
1283 int idx;
1284
1285 if (path == ADM_PATH_PLAYBACK) {
1286 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1287 } else if (path == ADM_PATH_LIVE_REC) {
1288 idx = ADM_MCH_MAP_IDX_REC;
1289 } else {
1290 pr_err("%s: invalid attempt to get path %d\n", __func__, path);
1291 return -EINVAL;
1292 }
1293
1294 if (multi_ch_maps[idx].set_channel_map) {
1295 memcpy(channel_map, multi_ch_maps[idx].channel_mapping,
Dieter Luecking50c55352018-09-28 14:29:17 +02001296 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301297 }
1298
1299 return 0;
1300}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301301EXPORT_SYMBOL(adm_get_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301302
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001303static int adm_process_get_param_response(u32 opcode, u32 idx, u32 *payload,
1304 u32 payload_size)
1305{
1306 struct adm_cmd_rsp_get_pp_params_v5 *v5_rsp = NULL;
1307 struct adm_cmd_rsp_get_pp_params_v6 *v6_rsp = NULL;
1308 u32 *param_data = NULL;
1309 int data_size = 0;
1310 int struct_size = 0;
1311
1312 if (payload == NULL) {
1313 pr_err("%s: Payload is NULL\n", __func__);
1314 return -EINVAL;
1315 }
1316
1317 switch (opcode) {
1318 case ADM_CMDRSP_GET_PP_PARAMS_V5:
1319 struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v5);
1320 v5_rsp = (struct adm_cmd_rsp_get_pp_params_v5 *) payload;
1321 data_size = v5_rsp->param_hdr.param_size;
1322 param_data = v5_rsp->param_data;
1323 break;
1324 case ADM_CMDRSP_GET_PP_PARAMS_V6:
1325 struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v6);
1326 v6_rsp = (struct adm_cmd_rsp_get_pp_params_v6 *) payload;
1327 data_size = v6_rsp->param_hdr.param_size;
1328 param_data = v6_rsp->param_data;
1329 break;
1330 default:
1331 pr_err("%s: Invalid opcode %d\n", __func__, opcode);
1332 return -EINVAL;
1333 }
1334
1335 /*
1336 * Just store the returned parameter data, not the header. The calling
1337 * function is expected to know what it asked for. Therefore, there is
1338 * no difference between V5 and V6.
1339 */
1340 if ((payload_size >= struct_size + data_size) &&
1341 (ARRAY_SIZE(adm_get_parameters) > idx) &&
Karthikeyan Mani95be5b12018-11-09 14:57:32 -08001342 (ARRAY_SIZE(adm_get_parameters) > idx + 1 + data_size)) {
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001343 pr_debug("%s: Received parameter data in band\n",
1344 __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001345 /*
1346 * data_size is expressed in number of bytes, store in number of
1347 * ints
1348 */
1349 adm_get_parameters[idx] =
1350 data_size / sizeof(*adm_get_parameters);
1351 pr_debug("%s: GET_PP PARAM: received parameter length: 0x%x\n",
1352 __func__, adm_get_parameters[idx]);
1353 /* store params after param_size */
1354 memcpy(&adm_get_parameters[idx + 1], param_data, data_size);
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001355 } else if (payload_size == sizeof(uint32_t)) {
1356 adm_get_parameters[idx] = -1;
1357 pr_debug("%s: Out of band case, setting size to %d\n",
1358 __func__, adm_get_parameters[idx]);
1359 } else {
1360 pr_err("%s: Invalid parameter combination, payload_size %d, idx %d\n",
1361 __func__, payload_size, idx);
1362 return -EINVAL;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001363 }
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001364 return 0;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001365}
1366
1367static int adm_process_get_topo_list_response(u32 opcode, int copp_idx,
1368 u32 num_modules, u32 *payload,
1369 u32 payload_size)
1370{
1371 u32 *fill_list = NULL;
1372 int idx = 0;
1373 int i = 0;
1374 int j = 0;
1375
1376 if (payload == NULL) {
1377 pr_err("%s: Payload is NULL\n", __func__);
1378 return -EINVAL;
1379 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1380 pr_err("%s: Invalid COPP index %d\n", __func__, copp_idx);
1381 return -EINVAL;
1382 }
1383
1384 idx = ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH * copp_idx;
1385 fill_list = adm_module_topo_list + idx;
1386 *fill_list++ = num_modules;
1387 for (i = 0; i < num_modules; i++) {
1388 if (j > payload_size / sizeof(u32)) {
1389 pr_err("%s: Invalid number of modules specified %d\n",
1390 __func__, num_modules);
1391 return -EINVAL;
1392 }
1393
1394 /* store module ID */
1395 *fill_list++ = payload[j];
1396 j++;
1397
1398 switch (opcode) {
1399 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
1400 /* store instance ID */
1401 *fill_list++ = payload[j];
1402 j++;
1403 break;
1404 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
1405 /* Insert IID 0 when repacking */
1406 *fill_list++ = INSTANCE_ID_0;
1407 break;
1408 default:
1409 pr_err("%s: Invalid opcode %d\n", __func__, opcode);
1410 return -EINVAL;
1411 }
1412 }
1413
1414 return 0;
1415}
1416
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301417static void adm_reset_data(void)
1418{
1419 int i, j;
1420
1421 apr_reset(this_adm.apr);
1422 for (i = 0; i < AFE_MAX_PORTS; i++) {
1423 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
1424 atomic_set(&this_adm.copp.id[i][j],
1425 RESET_COPP_ID);
1426 atomic_set(&this_adm.copp.cnt[i][j], 0);
1427 atomic_set(
1428 &this_adm.copp.topology[i][j], 0);
1429 atomic_set(&this_adm.copp.mode[i][j],
1430 0);
1431 atomic_set(&this_adm.copp.stat[i][j],
1432 0);
1433 atomic_set(&this_adm.copp.rate[i][j],
1434 0);
1435 atomic_set(
1436 &this_adm.copp.channels[i][j],
1437 0);
1438 atomic_set(
1439 &this_adm.copp.bit_width[i][j], 0);
1440 atomic_set(
1441 &this_adm.copp.app_type[i][j], 0);
1442 atomic_set(
1443 &this_adm.copp.acdb_id[i][j], 0);
Surendar Karkae7507512018-07-20 15:46:54 +05301444 atomic_set(
1445 &this_adm.copp.session_type[i][j], 0);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301446 this_adm.copp.adm_status[i][j] =
1447 ADM_STATUS_CALIBRATION_REQUIRED;
1448 }
1449 }
1450 this_adm.apr = NULL;
1451 cal_utils_clear_cal_block_q6maps(ADM_MAX_CAL_TYPES,
1452 this_adm.cal_data);
1453 mutex_lock(&this_adm.cal_data
1454 [ADM_CUSTOM_TOP_CAL]->lock);
1455 this_adm.set_custom_topology = 1;
1456 mutex_unlock(&this_adm.cal_data[
1457 ADM_CUSTOM_TOP_CAL]->lock);
1458 rtac_clear_mapping(ADM_RTAC_CAL);
1459 /*
1460 * Free the ION memory and clear the map handles
1461 * for Source Tracking
1462 */
1463 if (this_adm.sourceTrackingData.memmap.paddr != 0) {
1464 msm_audio_ion_free(
1465 this_adm.sourceTrackingData.dma_buf);
1466 this_adm.sourceTrackingData.dma_buf = NULL;
1467 this_adm.sourceTrackingData.memmap.size = 0;
1468 this_adm.sourceTrackingData.memmap.kvaddr =
1469 NULL;
1470 this_adm.sourceTrackingData.memmap.paddr = 0;
1471 this_adm.sourceTrackingData.apr_cmd_status = -1;
1472 atomic_set(&this_adm.mem_map_handles[
1473 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
1474 }
1475}
1476
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301477static int32_t adm_callback(struct apr_client_data *data, void *priv)
1478{
1479 uint32_t *payload;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001480 int port_idx, copp_idx, idx, client_id;
1481 int num_modules;
1482 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301483
1484 if (data == NULL) {
1485 pr_err("%s: data parameter is null\n", __func__);
1486 return -EINVAL;
1487 }
1488
1489 payload = data->payload;
1490
1491 if (data->opcode == RESET_EVENTS) {
1492 pr_debug("%s: Reset event is received: %d %d apr[%pK]\n",
1493 __func__,
1494 data->reset_event, data->reset_proc, this_adm.apr);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301495 if (this_adm.apr)
1496 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301497 return 0;
1498 }
1499
1500 adm_callback_debug_print(data);
1501 if (data->payload_size) {
1502 copp_idx = (data->token) & 0XFF;
1503 port_idx = ((data->token) >> 16) & 0xFF;
1504 client_id = ((data->token) >> 8) & 0xFF;
1505 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1506 pr_err("%s: Invalid port idx %d token %d\n",
1507 __func__, port_idx, data->token);
1508 return 0;
1509 }
1510 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1511 pr_err("%s: Invalid copp idx %d token %d\n",
1512 __func__, copp_idx, data->token);
1513 return 0;
1514 }
1515 if (client_id < 0 || client_id >= ADM_CLIENT_ID_MAX) {
1516 pr_err("%s: Invalid client id %d\n", __func__,
1517 client_id);
1518 return 0;
1519 }
1520 if (data->opcode == APR_BASIC_RSP_RESULT) {
1521 pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
1522 __func__, payload[0]);
1523 if (payload[1] != 0) {
1524 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
1525 __func__, payload[0], payload[1]);
1526 }
1527 switch (payload[0]) {
1528 case ADM_CMD_SET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001529 case ADM_CMD_SET_PP_PARAMS_V6:
1530 pr_debug("%s: ADM_CMD_SET_PP_PARAMS\n",
1531 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301532 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1533 this_adm.sourceTrackingData.
1534 apr_cmd_status = payload[1];
1535 else if (rtac_make_adm_callback(payload,
1536 data->payload_size))
1537 break;
1538 /*
1539 * if soft volume is called and already
1540 * interrupted break out of the sequence here
1541 */
1542 case ADM_CMD_DEVICE_OPEN_V5:
1543 case ADM_CMD_DEVICE_CLOSE_V5:
1544 case ADM_CMD_DEVICE_OPEN_V6:
Dieter Luecking50c55352018-09-28 14:29:17 +02001545 case ADM_CMD_DEVICE_OPEN_V8:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301546 pr_debug("%s: Basic callback received, wake up.\n",
1547 __func__);
1548 atomic_set(&this_adm.copp.stat[port_idx]
1549 [copp_idx], payload[1]);
1550 wake_up(
1551 &this_adm.copp.wait[port_idx][copp_idx]);
1552 break;
1553 case ADM_CMD_ADD_TOPOLOGIES:
1554 pr_debug("%s: callback received, ADM_CMD_ADD_TOPOLOGIES.\n",
1555 __func__);
1556 atomic_set(&this_adm.adm_stat, payload[1]);
1557 wake_up(&this_adm.adm_wait);
1558 break;
1559 case ADM_CMD_MATRIX_MAP_ROUTINGS_V5:
1560 case ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5:
1561 pr_debug("%s: Basic callback received, wake up.\n",
1562 __func__);
1563 atomic_set(&this_adm.matrix_map_stat,
1564 payload[1]);
1565 wake_up(&this_adm.matrix_map_wait);
1566 break;
1567 case ADM_CMD_SHARED_MEM_UNMAP_REGIONS:
1568 pr_debug("%s: ADM_CMD_SHARED_MEM_UNMAP_REGIONS\n",
1569 __func__);
1570 atomic_set(&this_adm.adm_stat, payload[1]);
1571 wake_up(&this_adm.adm_wait);
1572 break;
1573 case ADM_CMD_SHARED_MEM_MAP_REGIONS:
1574 pr_debug("%s: ADM_CMD_SHARED_MEM_MAP_REGIONS\n",
1575 __func__);
1576 /* Should only come here if there is an APR */
1577 /* error or malformed APR packet. Otherwise */
1578 /* response will be returned as */
1579 if (payload[1] != 0) {
1580 pr_err("%s: ADM map error, resuming\n",
1581 __func__);
1582 atomic_set(&this_adm.adm_stat,
1583 payload[1]);
1584 wake_up(&this_adm.adm_wait);
1585 }
1586 break;
1587 case ADM_CMD_GET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001588 case ADM_CMD_GET_PP_PARAMS_V6:
1589 pr_debug("%s: ADM_CMD_GET_PP_PARAMS\n",
1590 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301591 /* Should only come here if there is an APR */
1592 /* error or malformed APR packet. Otherwise */
1593 /* response will be returned as */
1594 /* ADM_CMDRSP_GET_PP_PARAMS_V5 */
1595 if (client_id ==
1596 ADM_CLIENT_ID_SOURCE_TRACKING) {
1597 this_adm.sourceTrackingData.
1598 apr_cmd_status = payload[1];
1599 if (payload[1] != 0)
1600 pr_err("%s: ADM get param error = %d\n",
1601 __func__, payload[1]);
1602
1603 atomic_set(&this_adm.copp.stat
1604 [port_idx][copp_idx],
1605 payload[1]);
1606 wake_up(&this_adm.copp.wait
1607 [port_idx][copp_idx]);
1608 } else {
1609 if (payload[1] != 0) {
1610 pr_err("%s: ADM get param error = %d, resuming\n",
1611 __func__, payload[1]);
1612
1613 rtac_make_adm_callback(payload,
1614 data->payload_size);
1615 }
1616 }
1617 break;
1618 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5:
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -07001619 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6:
1620 pr_debug("%s:callback received PSPD MTMX, wake up\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301621 __func__);
1622 atomic_set(&this_adm.copp.stat[port_idx]
1623 [copp_idx], payload[1]);
1624 wake_up(
1625 &this_adm.copp.wait[port_idx][copp_idx]);
1626 break;
1627 case ADM_CMD_GET_PP_TOPO_MODULE_LIST:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001628 case ADM_CMD_GET_PP_TOPO_MODULE_LIST_V2:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301629 pr_debug("%s:ADM_CMD_GET_PP_TOPO_MODULE_LIST\n",
1630 __func__);
1631 if (payload[1] != 0)
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001632 pr_err("%s: ADM get topo list error = %d\n",
1633 __func__, payload[1]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301634 break;
1635 default:
1636 pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
1637 payload[0]);
1638 break;
1639 }
1640 return 0;
1641 }
1642
1643 switch (data->opcode) {
1644 case ADM_CMDRSP_DEVICE_OPEN_V5:
Dieter Luecking50c55352018-09-28 14:29:17 +02001645 case ADM_CMDRSP_DEVICE_OPEN_V6:
1646 case ADM_CMDRSP_DEVICE_OPEN_V8: {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301647 struct adm_cmd_rsp_device_open_v5 *open =
1648 (struct adm_cmd_rsp_device_open_v5 *)data->payload;
1649
1650 if (open->copp_id == INVALID_COPP_ID) {
1651 pr_err("%s: invalid coppid rxed %d\n",
1652 __func__, open->copp_id);
1653 atomic_set(&this_adm.copp.stat[port_idx]
1654 [copp_idx], ADSP_EBADPARAM);
1655 wake_up(
1656 &this_adm.copp.wait[port_idx][copp_idx]);
1657 break;
1658 }
1659 atomic_set(&this_adm.copp.stat
1660 [port_idx][copp_idx], payload[0]);
1661 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
1662 open->copp_id);
1663 pr_debug("%s: coppid rxed=%d\n", __func__,
1664 open->copp_id);
1665 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1666 }
1667 break;
1668 case ADM_CMDRSP_GET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001669 case ADM_CMDRSP_GET_PP_PARAMS_V6:
1670 pr_debug("%s: ADM_CMDRSP_GET_PP_PARAMS\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301671 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1672 this_adm.sourceTrackingData.apr_cmd_status =
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001673 payload[0];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301674 else if (rtac_make_adm_callback(payload,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001675 data->payload_size))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301676 break;
1677
1678 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001679 if (payload[0] == 0 && data->payload_size > 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001680 ret = adm_process_get_param_response(
1681 data->opcode, idx, payload,
1682 data->payload_size);
1683 if (ret)
1684 pr_err("%s: Failed to process get param response, error %d\n",
1685 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301686 } else {
1687 adm_get_parameters[idx] = -1;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001688 pr_err("%s: ADM_CMDRSP_GET_PP_PARAMS returned error 0x%x\n",
1689 __func__, payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301690 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001691 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1692 payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301693 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1694 break;
1695 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001696 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301697 pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n",
1698 __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001699 num_modules = payload[1];
1700 pr_debug("%s: Num modules %d\n", __func__, num_modules);
1701 if (payload[0]) {
1702 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
1703 __func__, payload[0]);
1704 } else if (num_modules > MAX_MODULES_IN_TOPO) {
1705 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n",
1706 __func__, num_modules);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301707 } else {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001708 ret = adm_process_get_topo_list_response(
1709 data->opcode, copp_idx, num_modules,
1710 payload, data->payload_size);
1711 if (ret)
1712 pr_err("%s: Failed to process get topo modules list response, error %d\n",
1713 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301714 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001715 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1716 payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301717 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1718 break;
1719 case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
1720 pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
1721 __func__);
1722 atomic_set(&this_adm.mem_map_handles[
1723 atomic_read(&this_adm.mem_map_index)],
1724 *payload);
1725 atomic_set(&this_adm.adm_stat, 0);
1726 wake_up(&this_adm.adm_wait);
1727 break;
1728 default:
1729 pr_err("%s: Unknown cmd:0x%x\n", __func__,
1730 data->opcode);
1731 break;
1732 }
1733 }
1734 return 0;
1735}
1736
1737static int adm_memory_map_regions(phys_addr_t *buf_add, uint32_t mempool_id,
1738 uint32_t *bufsz, uint32_t bufcnt)
1739{
1740 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
1741 struct avs_shared_map_region_payload *mregions = NULL;
1742 void *mmap_region_cmd = NULL;
1743 void *payload = NULL;
1744 int ret = 0;
1745 int i = 0;
1746 int cmd_size = 0;
1747
1748 pr_debug("%s:\n", __func__);
1749 if (this_adm.apr == NULL) {
1750 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
1751 0xFFFFFFFF, &this_adm);
1752 if (this_adm.apr == NULL) {
1753 pr_err("%s: Unable to register ADM\n", __func__);
1754 ret = -ENODEV;
1755 return ret;
1756 }
1757 rtac_set_adm_handle(this_adm.apr);
1758 }
1759
1760 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
1761 + sizeof(struct avs_shared_map_region_payload)
1762 * bufcnt;
1763
1764 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1765 if (!mmap_region_cmd)
1766 return -ENOMEM;
1767
1768 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)mmap_region_cmd;
1769 mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1770 APR_HDR_LEN(APR_HDR_SIZE),
1771 APR_PKT_VER);
1772 mmap_regions->hdr.pkt_size = cmd_size;
1773 mmap_regions->hdr.src_port = 0;
1774
1775 mmap_regions->hdr.dest_port = 0;
1776 mmap_regions->hdr.token = 0;
1777 mmap_regions->hdr.opcode = ADM_CMD_SHARED_MEM_MAP_REGIONS;
1778 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL & 0x00ff;
1779 mmap_regions->num_regions = bufcnt & 0x00ff;
1780 mmap_regions->property_flag = 0x00;
1781
1782 pr_debug("%s: map_regions->num_regions = %d\n", __func__,
1783 mmap_regions->num_regions);
1784 payload = ((u8 *) mmap_region_cmd +
1785 sizeof(struct avs_cmd_shared_mem_map_regions));
1786 mregions = (struct avs_shared_map_region_payload *)payload;
1787
1788 for (i = 0; i < bufcnt; i++) {
1789 mregions->shm_addr_lsw = lower_32_bits(buf_add[i]);
1790 mregions->shm_addr_msw =
1791 msm_audio_populate_upper_32_bits(buf_add[i]);
1792 mregions->mem_size_bytes = bufsz[i];
1793 ++mregions;
1794 }
1795
1796 atomic_set(&this_adm.adm_stat, -1);
1797 ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
1798 if (ret < 0) {
1799 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1800 mmap_regions->hdr.opcode, ret);
1801 ret = -EINVAL;
1802 goto fail_cmd;
1803 }
1804
1805 ret = wait_event_timeout(this_adm.adm_wait,
1806 atomic_read(&this_adm.adm_stat) >= 0,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001807 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301808 if (!ret) {
1809 pr_err("%s: timeout. waited for memory_map\n", __func__);
1810 ret = -EINVAL;
1811 goto fail_cmd;
1812 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1813 pr_err("%s: DSP returned error[%s]\n",
1814 __func__, adsp_err_get_err_str(
1815 atomic_read(&this_adm.adm_stat)));
1816 ret = adsp_err_get_lnx_err_code(
1817 atomic_read(&this_adm.adm_stat));
1818 goto fail_cmd;
1819 }
1820fail_cmd:
1821 kfree(mmap_region_cmd);
1822 return ret;
1823}
1824
1825static int adm_memory_unmap_regions(void)
1826{
1827 struct avs_cmd_shared_mem_unmap_regions unmap_regions;
1828 int ret = 0;
1829
1830 pr_debug("%s:\n", __func__);
1831 if (this_adm.apr == NULL) {
1832 pr_err("%s: APR handle NULL\n", __func__);
1833 return -EINVAL;
1834 }
1835
1836 unmap_regions.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1837 APR_HDR_LEN(APR_HDR_SIZE),
1838 APR_PKT_VER);
1839 unmap_regions.hdr.pkt_size = sizeof(unmap_regions);
1840 unmap_regions.hdr.src_port = 0;
1841 unmap_regions.hdr.dest_port = 0;
1842 unmap_regions.hdr.token = 0;
1843 unmap_regions.hdr.opcode = ADM_CMD_SHARED_MEM_UNMAP_REGIONS;
1844 unmap_regions.mem_map_handle = atomic_read(&this_adm.
1845 mem_map_handles[atomic_read(&this_adm.mem_map_index)]);
1846 atomic_set(&this_adm.adm_stat, -1);
1847 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &unmap_regions);
1848 if (ret < 0) {
1849 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1850 unmap_regions.hdr.opcode, ret);
1851 ret = -EINVAL;
1852 goto fail_cmd;
1853 }
1854
1855 ret = wait_event_timeout(this_adm.adm_wait,
1856 atomic_read(&this_adm.adm_stat) >= 0,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001857 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301858 if (!ret) {
1859 pr_err("%s: timeout. waited for memory_unmap\n",
1860 __func__);
1861 ret = -EINVAL;
1862 goto fail_cmd;
1863 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1864 pr_err("%s: DSP returned error[%s]\n",
1865 __func__, adsp_err_get_err_str(
1866 atomic_read(&this_adm.adm_stat)));
1867 ret = adsp_err_get_lnx_err_code(
1868 atomic_read(&this_adm.adm_stat));
1869 goto fail_cmd;
1870 } else {
1871 pr_debug("%s: Unmap handle 0x%x succeeded\n", __func__,
1872 unmap_regions.mem_map_handle);
1873 }
1874fail_cmd:
1875 return ret;
1876}
1877
1878static int remap_cal_data(struct cal_block_data *cal_block, int cal_index)
1879{
1880 int ret = 0;
1881
Banajit Goswami08bb7362017-11-03 22:48:23 -07001882 if (cal_block->map_data.dma_buf == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301883 pr_err("%s: No ION allocation for cal index %d!\n",
1884 __func__, cal_index);
1885 ret = -EINVAL;
1886 goto done;
1887 }
1888
1889 if ((cal_block->map_data.map_size > 0) &&
1890 (cal_block->map_data.q6map_handle == 0)) {
1891 atomic_set(&this_adm.mem_map_index, cal_index);
1892 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
1893 (uint32_t *)&cal_block->map_data.map_size, 1);
1894 if (ret < 0) {
1895 pr_err("%s: ADM mmap did not work! size = %zd ret %d\n",
1896 __func__,
1897 cal_block->map_data.map_size, ret);
1898 pr_debug("%s: ADM mmap did not work! addr = 0x%pK, size = %zd ret %d\n",
1899 __func__,
1900 &cal_block->cal_data.paddr,
1901 cal_block->map_data.map_size, ret);
1902 goto done;
1903 }
1904 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
1905 mem_map_handles[cal_index]);
1906 }
1907done:
1908 return ret;
1909}
1910
1911static void send_adm_custom_topology(void)
1912{
1913 struct cal_block_data *cal_block = NULL;
1914 struct cmd_set_topologies adm_top;
1915 int cal_index = ADM_CUSTOM_TOP_CAL;
1916 int result;
1917
1918 if (this_adm.cal_data[cal_index] == NULL)
1919 goto done;
1920
1921 mutex_lock(&this_adm.cal_data[cal_index]->lock);
1922 if (!this_adm.set_custom_topology)
1923 goto unlock;
1924 this_adm.set_custom_topology = 0;
1925
1926 cal_block = cal_utils_get_only_cal_block(this_adm.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07001927 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301928 goto unlock;
1929
1930 pr_debug("%s: Sending cal_index %d\n", __func__, cal_index);
1931
1932 result = remap_cal_data(cal_block, cal_index);
1933 if (result) {
1934 pr_err("%s: Remap_cal_data failed for cal %d!\n",
1935 __func__, cal_index);
1936 goto unlock;
1937 }
1938 atomic_set(&this_adm.mem_map_index, cal_index);
1939 atomic_set(&this_adm.mem_map_handles[cal_index],
1940 cal_block->map_data.q6map_handle);
1941
1942 if (cal_block->cal_data.size == 0) {
1943 pr_debug("%s: No ADM cal to send\n", __func__);
1944 goto unlock;
1945 }
1946
1947 adm_top.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1948 APR_HDR_LEN(20), APR_PKT_VER);
1949 adm_top.hdr.pkt_size = sizeof(adm_top);
1950 adm_top.hdr.src_svc = APR_SVC_ADM;
1951 adm_top.hdr.src_domain = APR_DOMAIN_APPS;
1952 adm_top.hdr.src_port = 0;
1953 adm_top.hdr.dest_svc = APR_SVC_ADM;
1954 adm_top.hdr.dest_domain = APR_DOMAIN_ADSP;
1955 adm_top.hdr.dest_port = 0;
1956 adm_top.hdr.token = 0;
1957 adm_top.hdr.opcode = ADM_CMD_ADD_TOPOLOGIES;
1958 adm_top.payload_addr_lsw = lower_32_bits(cal_block->cal_data.paddr);
1959 adm_top.payload_addr_msw = msm_audio_populate_upper_32_bits(
1960 cal_block->cal_data.paddr);
1961 adm_top.mem_map_handle = cal_block->map_data.q6map_handle;
1962 adm_top.payload_size = cal_block->cal_data.size;
1963
1964 atomic_set(&this_adm.adm_stat, -1);
1965 pr_debug("%s: Sending ADM_CMD_ADD_TOPOLOGIES payload = 0x%pK, size = %d\n",
1966 __func__, &cal_block->cal_data.paddr,
1967 adm_top.payload_size);
1968 result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_top);
1969 if (result < 0) {
1970 pr_err("%s: Set topologies failed payload size = %zd result %d\n",
1971 __func__, cal_block->cal_data.size, result);
1972 goto unlock;
1973 }
1974 /* Wait for the callback */
1975 result = wait_event_timeout(this_adm.adm_wait,
1976 atomic_read(&this_adm.adm_stat) >= 0,
1977 msecs_to_jiffies(TIMEOUT_MS));
1978 if (!result) {
1979 pr_err("%s: Set topologies timed out payload size = %zd\n",
1980 __func__, cal_block->cal_data.size);
1981 goto unlock;
1982 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1983 pr_err("%s: DSP returned error[%s]\n",
1984 __func__, adsp_err_get_err_str(
1985 atomic_read(&this_adm.adm_stat)));
1986 result = adsp_err_get_lnx_err_code(
1987 atomic_read(&this_adm.adm_stat));
1988 goto unlock;
1989 }
1990unlock:
1991 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
1992done:
1993 return;
1994}
1995
1996static int send_adm_cal_block(int port_id, int copp_idx,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001997 struct cal_block_data *cal_block, int perf_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301998{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001999 struct mem_mapping_hdr mem_hdr;
2000 int payload_size = 0;
2001 int port_idx = 0;
2002 int topology = 0;
2003 int result = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302004
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002005 pr_debug("%s: Port id 0x%x,\n", __func__, port_id);
2006
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302007 if (!cal_block) {
2008 pr_debug("%s: No ADM cal to send for port_id = 0x%x!\n",
2009 __func__, port_id);
2010 result = -EINVAL;
2011 goto done;
2012 }
2013 if (cal_block->cal_data.size <= 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002014 pr_debug("%s: No ADM cal sent for port_id = 0x%x!\n", __func__,
2015 port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302016 result = -EINVAL;
2017 goto done;
2018 }
2019
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002020 memset(&mem_hdr, 0, sizeof(mem_hdr));
2021 port_id = afe_convert_virtual_to_portid(port_id);
2022 port_idx = adm_validate_and_get_port_index(port_id);
2023 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
2024 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2025 return -EINVAL;
2026 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
2027 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
2028 return -EINVAL;
2029 }
2030
2031 topology = atomic_read(&this_adm.copp.topology[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302032 if (perf_mode == LEGACY_PCM_MODE &&
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002033 topology == DS2_ADM_COPP_TOPOLOGY_ID) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302034 pr_err("%s: perf_mode %d, topology 0x%x\n", __func__, perf_mode,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002035 topology);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302036 goto done;
2037 }
2038
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002039 mem_hdr.data_payload_addr_lsw =
2040 lower_32_bits(cal_block->cal_data.paddr);
2041 mem_hdr.data_payload_addr_msw =
2042 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
2043 mem_hdr.mem_map_handle = cal_block->map_data.q6map_handle;
2044 payload_size = cal_block->cal_data.size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302045
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002046 adm_set_pp_params(port_id, copp_idx, &mem_hdr, NULL, payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302047
2048done:
2049 return result;
2050}
2051
2052static struct cal_block_data *adm_find_cal_by_path(int cal_index, int path)
2053{
2054 struct list_head *ptr, *next;
2055 struct cal_block_data *cal_block = NULL;
2056 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2057 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2058
2059 pr_debug("%s:\n", __func__);
2060
2061 list_for_each_safe(ptr, next,
2062 &this_adm.cal_data[cal_index]->cal_blocks) {
2063
2064 cal_block = list_entry(ptr,
2065 struct cal_block_data, list);
2066
Vikram Panduranga770b8382017-09-27 12:17:36 -07002067 if (cal_utils_is_cal_stale(cal_block))
2068 continue;
2069
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302070 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002071 cal_index == ADM_LSM_AUDPROC_CAL ||
2072 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302073 audproc_cal_info = cal_block->cal_info;
2074 if ((audproc_cal_info->path == path) &&
2075 (cal_block->cal_data.size > 0))
2076 return cal_block;
2077 } else if (cal_index == ADM_AUDVOL_CAL) {
2078 audvol_cal_info = cal_block->cal_info;
2079 if ((audvol_cal_info->path == path) &&
2080 (cal_block->cal_data.size > 0))
2081 return cal_block;
2082 }
2083 }
2084 pr_debug("%s: Can't find ADM cal for cal_index %d, path %d\n",
2085 __func__, cal_index, path);
2086 return NULL;
2087}
2088
2089static struct cal_block_data *adm_find_cal_by_app_type(int cal_index, int path,
2090 int app_type)
2091{
2092 struct list_head *ptr, *next;
2093 struct cal_block_data *cal_block = NULL;
2094 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2095 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2096
2097 pr_debug("%s\n", __func__);
2098
2099 list_for_each_safe(ptr, next,
2100 &this_adm.cal_data[cal_index]->cal_blocks) {
2101
2102 cal_block = list_entry(ptr,
2103 struct cal_block_data, list);
2104
Vikram Panduranga770b8382017-09-27 12:17:36 -07002105 if (cal_utils_is_cal_stale(cal_block))
2106 continue;
2107
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302108 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002109 cal_index == ADM_LSM_AUDPROC_CAL ||
2110 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302111 audproc_cal_info = cal_block->cal_info;
2112 if ((audproc_cal_info->path == path) &&
2113 (audproc_cal_info->app_type == app_type) &&
2114 (cal_block->cal_data.size > 0))
2115 return cal_block;
2116 } else if (cal_index == ADM_AUDVOL_CAL) {
2117 audvol_cal_info = cal_block->cal_info;
2118 if ((audvol_cal_info->path == path) &&
2119 (audvol_cal_info->app_type == app_type) &&
2120 (cal_block->cal_data.size > 0))
2121 return cal_block;
2122 }
2123 }
2124 pr_debug("%s: Can't find ADM cali for cal_index %d, path %d, app %d, defaulting to search by path\n",
2125 __func__, cal_index, path, app_type);
2126 return adm_find_cal_by_path(cal_index, path);
2127}
2128
2129
2130static struct cal_block_data *adm_find_cal(int cal_index, int path,
2131 int app_type, int acdb_id,
2132 int sample_rate)
2133{
2134 struct list_head *ptr, *next;
2135 struct cal_block_data *cal_block = NULL;
2136 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2137 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2138
2139 pr_debug("%s:\n", __func__);
2140
2141 list_for_each_safe(ptr, next,
2142 &this_adm.cal_data[cal_index]->cal_blocks) {
2143
2144 cal_block = list_entry(ptr,
2145 struct cal_block_data, list);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002146 if (cal_utils_is_cal_stale(cal_block))
2147 continue;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302148
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302149 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002150 cal_index == ADM_LSM_AUDPROC_CAL ||
2151 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302152 audproc_cal_info = cal_block->cal_info;
2153 if ((audproc_cal_info->path == path) &&
2154 (audproc_cal_info->app_type == app_type) &&
2155 (audproc_cal_info->acdb_id == acdb_id) &&
2156 (audproc_cal_info->sample_rate == sample_rate) &&
2157 (cal_block->cal_data.size > 0))
2158 return cal_block;
2159 } else if (cal_index == ADM_AUDVOL_CAL) {
2160 audvol_cal_info = cal_block->cal_info;
2161 if ((audvol_cal_info->path == path) &&
2162 (audvol_cal_info->app_type == app_type) &&
2163 (audvol_cal_info->acdb_id == acdb_id) &&
2164 (cal_block->cal_data.size > 0))
2165 return cal_block;
2166 }
2167 }
2168 pr_debug("%s: Can't find ADM cal for cal_index %d, path %d, app %d, acdb_id %d sample_rate %d defaulting to search by app type\n",
2169 __func__, cal_index, path, app_type, acdb_id, sample_rate);
2170 return adm_find_cal_by_app_type(cal_index, path, app_type);
2171}
2172
2173static int adm_remap_and_send_cal_block(int cal_index, int port_id,
2174 int copp_idx, struct cal_block_data *cal_block, int perf_mode,
2175 int app_type, int acdb_id, int sample_rate)
2176{
2177 int ret = 0;
2178
2179 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
2180 ret = remap_cal_data(cal_block, cal_index);
2181 if (ret) {
2182 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2183 __func__, cal_index);
2184 goto done;
2185 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002186 ret = send_adm_cal_block(port_id, copp_idx, cal_block, perf_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302187 if (ret < 0)
2188 pr_debug("%s: No cal sent for cal_index %d, port_id = 0x%x! ret %d sample_rate %d\n",
2189 __func__, cal_index, port_id, ret, sample_rate);
2190done:
2191 return ret;
2192}
2193
2194static void send_adm_cal_type(int cal_index, int path, int port_id,
2195 int copp_idx, int perf_mode, int app_type,
2196 int acdb_id, int sample_rate)
2197{
2198 struct cal_block_data *cal_block = NULL;
2199 int ret;
2200
2201 pr_debug("%s: cal index %d\n", __func__, cal_index);
2202
2203 if (this_adm.cal_data[cal_index] == NULL) {
2204 pr_debug("%s: cal_index %d not allocated!\n",
2205 __func__, cal_index);
2206 goto done;
2207 }
2208
2209 mutex_lock(&this_adm.cal_data[cal_index]->lock);
2210 cal_block = adm_find_cal(cal_index, path, app_type, acdb_id,
2211 sample_rate);
2212 if (cal_block == NULL)
2213 goto unlock;
2214
2215 ret = adm_remap_and_send_cal_block(cal_index, port_id, copp_idx,
2216 cal_block, perf_mode, app_type, acdb_id, sample_rate);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002217
2218 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302219unlock:
2220 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2221done:
2222 return;
2223}
2224
2225static int get_cal_path(int path)
2226{
2227 if (path == 0x1)
2228 return RX_DEVICE;
2229 else
2230 return TX_DEVICE;
2231}
2232
2233static void send_adm_cal(int port_id, int copp_idx, int path, int perf_mode,
Aditya Bavanari5106b562018-01-08 13:16:32 +05302234 int app_type, int acdb_id, int sample_rate,
2235 int passthr_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302236{
2237 pr_debug("%s: port id 0x%x copp_idx %d\n", __func__, port_id, copp_idx);
2238
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002239 if (passthr_mode != LISTEN) {
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302240 send_adm_cal_type(ADM_AUDPROC_CAL, path, port_id, copp_idx,
2241 perf_mode, app_type, acdb_id, sample_rate);
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002242 } else {
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302243 send_adm_cal_type(ADM_LSM_AUDPROC_CAL, path, port_id, copp_idx,
2244 perf_mode, app_type, acdb_id, sample_rate);
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002245
2246 send_adm_cal_type(ADM_LSM_AUDPROC_PERSISTENT_CAL, path,
2247 port_id, copp_idx, perf_mode, app_type,
2248 acdb_id, sample_rate);
2249 }
2250
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302251 send_adm_cal_type(ADM_AUDVOL_CAL, path, port_id, copp_idx, perf_mode,
2252 app_type, acdb_id, sample_rate);
2253}
2254
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302255/**
2256 * adm_connect_afe_port -
2257 * command to send ADM connect AFE port
2258 *
2259 * @mode: value of mode for ADM connect AFE
2260 * @session_id: session active to connect
2261 * @port_id: Port ID number
2262 *
2263 * Returns 0 on success or error on failure
2264 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302265int adm_connect_afe_port(int mode, int session_id, int port_id)
2266{
2267 struct adm_cmd_connect_afe_port_v5 cmd;
2268 int ret = 0;
2269 int port_idx, copp_idx = 0;
2270
2271 pr_debug("%s: port_id: 0x%x session id:%d mode:%d\n", __func__,
2272 port_id, session_id, mode);
2273
2274 port_id = afe_convert_virtual_to_portid(port_id);
2275 port_idx = adm_validate_and_get_port_index(port_id);
2276 if (port_idx < 0) {
2277 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2278 return -EINVAL;
2279 }
2280
2281 if (this_adm.apr == NULL) {
2282 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
2283 0xFFFFFFFF, &this_adm);
2284 if (this_adm.apr == NULL) {
2285 pr_err("%s: Unable to register ADM\n", __func__);
2286 ret = -ENODEV;
2287 return ret;
2288 }
2289 rtac_set_adm_handle(this_adm.apr);
2290 }
2291 pr_debug("%s: Port ID 0x%x, index %d\n", __func__, port_id, port_idx);
2292
2293 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2294 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2295 cmd.hdr.pkt_size = sizeof(cmd);
2296 cmd.hdr.src_svc = APR_SVC_ADM;
2297 cmd.hdr.src_domain = APR_DOMAIN_APPS;
2298 cmd.hdr.src_port = port_id;
2299 cmd.hdr.dest_svc = APR_SVC_ADM;
2300 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
2301 cmd.hdr.dest_port = 0; /* Ignored */
2302 cmd.hdr.token = port_idx << 16 | copp_idx;
2303 cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V5;
2304
2305 cmd.mode = mode;
2306 cmd.session_id = session_id;
2307 cmd.afe_port_id = port_id;
2308
2309 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
2310 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
2311 if (ret < 0) {
2312 pr_err("%s: ADM enable for port_id: 0x%x failed ret %d\n",
2313 __func__, port_id, ret);
2314 ret = -EINVAL;
2315 goto fail_cmd;
2316 }
2317 /* Wait for the callback with copp id */
2318 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
2319 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
2320 msecs_to_jiffies(TIMEOUT_MS));
2321 if (!ret) {
2322 pr_err("%s: ADM connect timedout for port_id: 0x%x\n",
2323 __func__, port_id);
2324 ret = -EINVAL;
2325 goto fail_cmd;
2326 } else if (atomic_read(&this_adm.copp.stat
2327 [port_idx][copp_idx]) > 0) {
2328 pr_err("%s: DSP returned error[%s]\n",
2329 __func__, adsp_err_get_err_str(
2330 atomic_read(&this_adm.copp.stat
2331 [port_idx][copp_idx])));
2332 ret = adsp_err_get_lnx_err_code(
2333 atomic_read(&this_adm.copp.stat
2334 [port_idx][copp_idx]));
2335 goto fail_cmd;
2336 }
2337 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
2338 return 0;
2339
2340fail_cmd:
2341
2342 return ret;
2343}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302344EXPORT_SYMBOL(adm_connect_afe_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302345
2346int adm_arrange_mch_map(struct adm_cmd_device_open_v5 *open, int path,
2347 int channel_mode)
2348{
2349 int rc = 0, idx;
2350
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -07002351 pr_debug("%s: channel mode %d", __func__, channel_mode);
2352
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302353 memset(open->dev_channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
2354 switch (path) {
2355 case ADM_PATH_PLAYBACK:
2356 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2357 break;
2358 case ADM_PATH_LIVE_REC:
2359 case ADM_PATH_NONLIVE_REC:
2360 idx = ADM_MCH_MAP_IDX_REC;
2361 break;
2362 default:
2363 goto non_mch_path;
2364 };
2365 if ((open->dev_num_channel > 2) && multi_ch_maps[idx].set_channel_map) {
2366 memcpy(open->dev_channel_mapping,
2367 multi_ch_maps[idx].channel_mapping,
2368 PCM_FORMAT_MAX_NUM_CHANNEL);
2369 } else {
2370 if (channel_mode == 1) {
2371 open->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2372 } else if (channel_mode == 2) {
2373 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2374 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2375 } else if (channel_mode == 3) {
2376 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2377 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2378 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2379 } else if (channel_mode == 4) {
2380 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2381 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2382 open->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2383 open->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2384 } else if (channel_mode == 5) {
2385 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2386 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2387 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2388 open->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2389 open->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2390 } else if (channel_mode == 6) {
2391 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2392 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2393 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2394 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2395 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2396 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2397 } else if (channel_mode == 7) {
2398 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2399 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2400 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2401 open->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
2402 open->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2403 open->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2404 open->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2405 } else if (channel_mode == 8) {
2406 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2407 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2408 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2409 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2410 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2411 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2412 open->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2413 open->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2414 } else {
2415 pr_err("%s: invalid num_chan %d\n", __func__,
2416 channel_mode);
2417 rc = -EINVAL;
2418 goto inval_ch_mod;
2419 }
2420 }
2421
2422non_mch_path:
2423inval_ch_mod:
2424 return rc;
2425}
2426
2427int adm_arrange_mch_ep2_map(struct adm_cmd_device_open_v6 *open_v6,
2428 int channel_mode)
2429{
2430 int rc = 0;
2431
2432 memset(open_v6->dev_channel_mapping_eid2, 0,
2433 PCM_FORMAT_MAX_NUM_CHANNEL);
2434
2435 if (channel_mode == 1) {
2436 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FC;
2437 } else if (channel_mode == 2) {
2438 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2439 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2440 } else if (channel_mode == 3) {
2441 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2442 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2443 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2444 } else if (channel_mode == 4) {
2445 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2446 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2447 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LS;
2448 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_RS;
2449 } else if (channel_mode == 5) {
2450 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2451 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2452 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2453 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_LS;
2454 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_RS;
2455 } else if (channel_mode == 6) {
2456 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2457 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2458 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
2459 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2460 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2461 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2462 } else if (channel_mode == 8) {
2463 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2464 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2465 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
2466 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2467 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2468 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2469 open_v6->dev_channel_mapping_eid2[6] = PCM_CHANNEL_LB;
2470 open_v6->dev_channel_mapping_eid2[7] = PCM_CHANNEL_RB;
2471 } else {
2472 pr_err("%s: invalid num_chan %d\n", __func__,
2473 channel_mode);
2474 rc = -EINVAL;
2475 }
2476
2477 return rc;
2478}
2479
Dieter Luecking50c55352018-09-28 14:29:17 +02002480static int adm_arrange_mch_map_v8(
2481 struct adm_device_endpoint_payload *ep_payload,
2482 int path,
2483 int channel_mode)
2484{
2485 int rc = 0, idx;
2486
2487 memset(ep_payload->dev_channel_mapping,
2488 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2489 switch (path) {
2490 case ADM_PATH_PLAYBACK:
2491 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2492 break;
2493 case ADM_PATH_LIVE_REC:
2494 case ADM_PATH_NONLIVE_REC:
2495 idx = ADM_MCH_MAP_IDX_REC;
2496 break;
2497 default:
2498 goto non_mch_path;
2499 };
2500
2501 if ((ep_payload->dev_num_channel > 2) &&
2502 multi_ch_maps[idx].set_channel_map) {
2503 memcpy(ep_payload->dev_channel_mapping,
2504 multi_ch_maps[idx].channel_mapping,
2505 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2506 } else {
2507 if (channel_mode == 1) {
2508 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2509 } else if (channel_mode == 2) {
2510 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2511 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2512 } else if (channel_mode == 3) {
2513 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2514 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2515 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2516 } else if (channel_mode == 4) {
2517 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2518 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2519 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2520 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2521 } else if (channel_mode == 5) {
2522 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2523 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2524 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2525 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2526 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2527 } else if (channel_mode == 6) {
2528 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2529 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2530 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2531 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2532 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2533 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2534 } else if (channel_mode == 7) {
2535 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2536 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2537 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2538 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
2539 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2540 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2541 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2542 } else if (channel_mode == 8) {
2543 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2544 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2545 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2546 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2547 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2548 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2549 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2550 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2551 } else if (channel_mode == 10) {
2552 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2553 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2554 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2555 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2556 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2557 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2558 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2559 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2560 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2561 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2562 } else if (channel_mode == 12) {
2563 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2564 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2565 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2566 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2567 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2568 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2569 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2570 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2571 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2572 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2573 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2574 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2575 } else if (channel_mode == 16) {
2576 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2577 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2578 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2579 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2580 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2581 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2582 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2583 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2584 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2585 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2586 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2587 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2588 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2589 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2590 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2591 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
2592 } else {
2593 pr_err("%s: invalid num_chan %d\n", __func__,
2594 channel_mode);
2595 rc = -EINVAL;
2596 goto inval_ch_mod;
2597 }
2598 }
2599
2600non_mch_path:
2601inval_ch_mod:
2602 return rc;
2603}
2604
2605static int adm_arrange_mch_ep2_map_v8(
2606 struct adm_device_endpoint_payload *ep_payload,
2607 int channel_mode)
2608{
2609 int rc = 0;
2610
2611 memset(ep_payload->dev_channel_mapping, 0,
2612 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2613
2614 if (channel_mode == 1) {
2615 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2616 } else if (channel_mode == 2) {
2617 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2618 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2619 } else if (channel_mode == 3) {
2620 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2621 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2622 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2623 } else if (channel_mode == 4) {
2624 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2625 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2626 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2627 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2628 } else if (channel_mode == 5) {
2629 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2630 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2631 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2632 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2633 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2634 } else if (channel_mode == 6) {
2635 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2636 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2637 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2638 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2639 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2640 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2641 } else if (channel_mode == 8) {
2642 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2643 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2644 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2645 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2646 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2647 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2648 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2649 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2650 } else if (channel_mode == 10) {
2651 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2652 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2653 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2654 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2655 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2656 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2657 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2658 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2659 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
2660 ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
2661 } else if (channel_mode == 12) {
2662 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2663 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2664 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2665 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2666 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2667 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2668 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2669 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2670 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2671 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2672 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2673 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2674 } else if (channel_mode == 16) {
2675 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2676 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2677 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2678 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2679 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2680 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2681 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2682 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2683 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
2684 ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
2685 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2686 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2687 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2688 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2689 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2690 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
2691 } else {
2692 pr_err("%s: invalid num_chan %d\n", __func__,
2693 channel_mode);
2694 rc = -EINVAL;
2695 }
2696
2697 return rc;
2698}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302699/**
2700 * adm_open -
2701 * command to send ADM open
2702 *
2703 * @port_id: port id number
2704 * @path: direction or ADM path type
2705 * @rate: sample rate of session
2706 * @channel_mode: number of channels set
2707 * @topology: topology active for this session
2708 * @perf_mode: performance mode like LL/ULL/..
2709 * @bit_width: bit width to set for copp
2710 * @app_type: App type used for this session
2711 * @acdb_id: ACDB ID of this device
Surendar Karkae7507512018-07-20 15:46:54 +05302712 * @session_type: type of session
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302713 *
2714 * Returns 0 on success or error on failure
2715 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302716int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
Surendar Karkae7507512018-07-20 15:46:54 +05302717 int perf_mode, uint16_t bit_width, int app_type, int acdb_id,
2718 int session_type)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302719{
2720 struct adm_cmd_device_open_v5 open;
2721 struct adm_cmd_device_open_v6 open_v6;
Dieter Luecking50c55352018-09-28 14:29:17 +02002722 struct adm_cmd_device_open_v8 open_v8;
2723 struct adm_device_endpoint_payload ep1_payload;
2724 struct adm_device_endpoint_payload ep2_payload;
2725 int ep1_payload_size = 0;
2726 int ep2_payload_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302727 int ret = 0;
Asish Bhattacharya34504582017-08-08 12:55:01 +05302728 int port_idx, flags;
2729 int copp_idx = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302730 int tmp_port = q6audio_get_port_id(port_id);
Dieter Luecking50c55352018-09-28 14:29:17 +02002731 void *adm_params = NULL;
2732 int param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302733
2734 pr_debug("%s:port %#x path:%d rate:%d mode:%d perf_mode:%d,topo_id %d\n",
2735 __func__, port_id, path, rate, channel_mode, perf_mode,
2736 topology);
2737
2738 port_id = q6audio_convert_virtual_to_portid(port_id);
2739 port_idx = adm_validate_and_get_port_index(port_id);
2740 if (port_idx < 0) {
2741 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2742 return -EINVAL;
2743 }
Dieter Luecking50c55352018-09-28 14:29:17 +02002744 if (channel_mode < 0 || channel_mode > 32) {
2745 pr_err("%s: Invalid channel number 0x%x\n",
2746 __func__, channel_mode);
2747 return -EINVAL;
2748 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302749
2750 if (this_adm.apr == NULL) {
2751 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
2752 0xFFFFFFFF, &this_adm);
2753 if (this_adm.apr == NULL) {
2754 pr_err("%s: Unable to register ADM\n", __func__);
2755 return -ENODEV;
2756 }
2757 rtac_set_adm_handle(this_adm.apr);
2758 }
2759
2760 if (perf_mode == ULL_POST_PROCESSING_PCM_MODE) {
2761 flags = ADM_ULL_POST_PROCESSING_DEVICE_SESSION;
2762 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
2763 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
2764 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
2765 topology = DEFAULT_COPP_TOPOLOGY;
2766 } else if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
2767 flags = ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
2768 topology = NULL_COPP_TOPOLOGY;
2769 rate = ULL_SUPPORTED_SAMPLE_RATE;
2770 bit_width = ULL_SUPPORTED_BITS_PER_SAMPLE;
2771 } else if (perf_mode == LOW_LATENCY_PCM_MODE) {
2772 flags = ADM_LOW_LATENCY_DEVICE_SESSION;
2773 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
2774 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
2775 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
2776 topology = DEFAULT_COPP_TOPOLOGY;
2777 } else {
2778 if ((path == ADM_PATH_COMPRESSED_RX) ||
2779 (path == ADM_PATH_COMPRESSED_TX))
2780 flags = 0;
2781 else
2782 flags = ADM_LEGACY_DEVICE_SESSION;
2783 }
2784
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05302785 if ((topology == VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY) ||
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302786 (topology == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY) ||
2787 (topology == VPM_TX_DM_RFECNS_COPP_TOPOLOGY))
2788 rate = 16000;
2789
kunleizc0cd19e2018-10-18 17:11:35 +08002790 if (topology == VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY)
2791 channel_mode = 1;
2792
Asish Bhattacharya34504582017-08-08 12:55:01 +05302793 /*
2794 * Routing driver reuses the same adm for streams with the same
2795 * app_type, sample_rate etc.
2796 * This isn't allowed for ULL streams as per the DSP interface
2797 */
2798 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE)
2799 copp_idx = adm_get_idx_if_copp_exists(port_idx, topology,
2800 perf_mode,
2801 rate, bit_width,
Surendar Karkae7507512018-07-20 15:46:54 +05302802 app_type, session_type);
Asish Bhattacharya34504582017-08-08 12:55:01 +05302803
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302804 if (copp_idx < 0) {
2805 copp_idx = adm_get_next_available_copp(port_idx);
2806 if (copp_idx >= MAX_COPPS_PER_PORT) {
2807 pr_err("%s: exceeded copp id %d\n",
2808 __func__, copp_idx);
2809 return -EINVAL;
2810 }
2811 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
2812 atomic_set(&this_adm.copp.topology[port_idx][copp_idx],
2813 topology);
2814 atomic_set(&this_adm.copp.mode[port_idx][copp_idx],
2815 perf_mode);
2816 atomic_set(&this_adm.copp.rate[port_idx][copp_idx],
2817 rate);
2818 atomic_set(&this_adm.copp.channels[port_idx][copp_idx],
2819 channel_mode);
2820 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx],
2821 bit_width);
2822 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx],
2823 app_type);
2824 atomic_set(&this_adm.copp.acdb_id[port_idx][copp_idx],
2825 acdb_id);
Surendar Karkae7507512018-07-20 15:46:54 +05302826 atomic_set(&this_adm.copp.session_type[port_idx][copp_idx],
2827 session_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302828 set_bit(ADM_STATUS_CALIBRATION_REQUIRED,
2829 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
2830 if ((path != ADM_PATH_COMPRESSED_RX) &&
2831 (path != ADM_PATH_COMPRESSED_TX))
2832 send_adm_custom_topology();
2833 }
2834
2835 if (this_adm.copp.adm_delay[port_idx][copp_idx] &&
2836 perf_mode == LEGACY_PCM_MODE) {
2837 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
2838 1);
2839 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
2840 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
2841 }
2842
2843 /* Create a COPP if port id are not enabled */
2844 if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) {
2845 pr_debug("%s: open ADM: port_idx: %d, copp_idx: %d\n", __func__,
2846 port_idx, copp_idx);
Dieter Luecking50c55352018-09-28 14:29:17 +02002847 if ((topology == SRS_TRUMEDIA_TOPOLOGY_ID) &&
2848 perf_mode == LEGACY_PCM_MODE) {
2849 int res;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302850
Dieter Luecking50c55352018-09-28 14:29:17 +02002851 atomic_set(&this_adm.mem_map_index, ADM_SRS_TRUMEDIA);
2852 msm_dts_srs_tm_ion_memmap(&this_adm.outband_memmap);
2853 res = adm_memory_map_regions(
2854 &this_adm.outband_memmap.paddr, 0,
2855 (uint32_t *)&this_adm.outband_memmap.size, 1);
2856 if (res < 0) {
2857 pr_err("%s: SRS adm_memory_map_regions failed! addr = 0x%pK, size = %d\n",
2858 __func__,
2859 (void *)this_adm.outband_memmap.paddr,
2860 (uint32_t)this_adm.outband_memmap.size);
2861 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302862 }
2863
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302864
Mangesh Kunchamwar9f295c72018-10-08 18:20:41 +05302865 if ((q6core_get_avcs_api_version_per_service(
Dieter Luecking50c55352018-09-28 14:29:17 +02002866 APRV2_IDS_SERVICE_ID_ADSP_ADM_V) >=
Mangesh Kunchamwar9f295c72018-10-08 18:20:41 +05302867 ADSP_ADM_API_VERSION_V3) &&
2868 q6core_use_Q6_32ch_support()) {
Dieter Luecking50c55352018-09-28 14:29:17 +02002869 memset(&open_v8, 0, sizeof(open_v8));
2870 memset(&ep1_payload, 0, sizeof(ep1_payload));
2871 memset(&ep2_payload, 0, sizeof(ep2_payload));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302872
Dieter Luecking50c55352018-09-28 14:29:17 +02002873 open_v8.hdr.hdr_field = APR_HDR_FIELD(
2874 APR_MSG_TYPE_SEQ_CMD,
2875 APR_HDR_LEN(APR_HDR_SIZE),
2876 APR_PKT_VER);
2877 open_v8.hdr.src_svc = APR_SVC_ADM;
2878 open_v8.hdr.src_domain = APR_DOMAIN_APPS;
2879 open_v8.hdr.src_port = tmp_port;
2880 open_v8.hdr.dest_svc = APR_SVC_ADM;
2881 open_v8.hdr.dest_domain = APR_DOMAIN_ADSP;
2882 open_v8.hdr.dest_port = tmp_port;
2883 open_v8.hdr.token = port_idx << 16 | copp_idx;
2884 open_v8.hdr.opcode = ADM_CMD_DEVICE_OPEN_V8;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302885
Dieter Luecking50c55352018-09-28 14:29:17 +02002886 if (this_adm.native_mode != 0) {
2887 open_v8.flags = flags |
2888 (this_adm.native_mode << 11);
2889 this_adm.native_mode = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302890 } else {
Dieter Luecking50c55352018-09-28 14:29:17 +02002891 open_v8.flags = flags;
2892 }
2893 open_v8.mode_of_operation = path;
2894 open_v8.endpoint_id_1 = tmp_port;
2895 open_v8.endpoint_id_2 = 0xFFFF;
2896 open_v8.endpoint_id_3 = 0xFFFF;
2897
Surendar Karkade79a062018-12-05 14:18:55 +05302898 if ((this_adm.ec_ref_rx != -1) &&
2899 (path != ADM_PATH_PLAYBACK)) {
2900 if (this_adm.num_ec_ref_rx_chans != 0) {
2901 open_v8.endpoint_id_2 =
2902 this_adm.ec_ref_rx;
2903 this_adm.ec_ref_rx = -1;
2904 } else {
2905 pr_err("%s: EC channels not set %d\n",
2906 __func__,
2907 this_adm.num_ec_ref_rx_chans);
2908 return -EINVAL;
2909 }
Dieter Luecking41620832018-11-14 15:11:47 +01002910 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302911
Dieter Luecking50c55352018-09-28 14:29:17 +02002912 open_v8.topology_id = topology;
2913 open_v8.reserved = 0;
2914
2915 /* variable endpoint payload */
2916 ep1_payload.dev_num_channel = channel_mode & 0x00FF;
2917 ep1_payload.bit_width = bit_width;
2918 ep1_payload.sample_rate = rate;
2919 ret = adm_arrange_mch_map_v8(&ep1_payload, path,
2920 channel_mode);
2921 if (ret)
2922 return ret;
2923
2924 pr_debug("%s: port_id=0x%x %x %x topology_id=0x%X flags %x ref_ch %x\n",
2925 __func__, open_v8.endpoint_id_1,
2926 open_v8.endpoint_id_2,
2927 open_v8.endpoint_id_3,
2928 open_v8.topology_id,
2929 open_v8.flags,
2930 this_adm.num_ec_ref_rx_chans);
2931
2932 ep1_payload_size = 8 +
2933 roundup(ep1_payload.dev_num_channel, 4);
2934 param_size = sizeof(struct adm_cmd_device_open_v8)
2935 + ep1_payload_size;
2936 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
2937
Dieter Luecking27c57722018-10-05 16:45:41 +02002938 if ((this_adm.num_ec_ref_rx_chans != 0)
2939 && (path != ADM_PATH_PLAYBACK)
Dieter Luecking50c55352018-09-28 14:29:17 +02002940 && (open_v8.endpoint_id_2 != 0xFFFF)) {
2941 ep2_payload.dev_num_channel =
2942 this_adm.num_ec_ref_rx_chans;
Dieter Luecking50c55352018-09-28 14:29:17 +02002943
2944 if (this_adm.ec_ref_rx_bit_width != 0) {
2945 ep2_payload.bit_width =
2946 this_adm.ec_ref_rx_bit_width;
2947 this_adm.ec_ref_rx_bit_width = 0;
2948 } else {
2949 ep2_payload.bit_width = bit_width;
2950 }
2951
2952 if (this_adm.ec_ref_rx_sampling_rate != 0) {
2953 ep2_payload.sample_rate =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302954 this_adm.ec_ref_rx_sampling_rate;
Dieter Luecking50c55352018-09-28 14:29:17 +02002955 this_adm.ec_ref_rx_sampling_rate = 0;
2956 } else {
2957 ep2_payload.sample_rate = rate;
2958 }
2959
2960 pr_debug("%s: adm open_v8 eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
2961 __func__,
2962 ep2_payload.dev_num_channel,
2963 ep2_payload.bit_width,
2964 ep2_payload.sample_rate);
2965
2966 ret = adm_arrange_mch_ep2_map_v8(&ep2_payload,
2967 ep2_payload.dev_num_channel);
2968
2969 if (ret)
2970 return ret;
2971 ep2_payload_size = 8 +
2972 roundup(ep2_payload.dev_num_channel, 4);
2973 param_size += ep2_payload_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302974 }
2975
Dieter Luecking27c57722018-10-05 16:45:41 +02002976 open_v8.hdr.pkt_size = param_size;
Dieter Luecking50c55352018-09-28 14:29:17 +02002977 adm_params = kzalloc(param_size, GFP_KERNEL);
2978 if (!adm_params)
2979 return -ENOMEM;
Dieter Luecking50c55352018-09-28 14:29:17 +02002980 memcpy(adm_params, &open_v8, sizeof(open_v8));
2981 memcpy(adm_params + sizeof(open_v8),
2982 (void *)&ep1_payload,
2983 ep1_payload_size);
Dieter Luecking27c57722018-10-05 16:45:41 +02002984
2985 if ((this_adm.num_ec_ref_rx_chans != 0)
2986 && (path != ADM_PATH_PLAYBACK)
2987 && (open_v8.endpoint_id_2 != 0xFFFF)) {
Dieter Luecking41620832018-11-14 15:11:47 +01002988 this_adm.num_ec_ref_rx_chans = 0;
Dieter Luecking27c57722018-10-05 16:45:41 +02002989 memcpy(adm_params + sizeof(open_v8)
2990 + ep1_payload_size,
2991 (void *)&ep2_payload,
2992 ep2_payload_size);
2993 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302994
Dieter Luecking50c55352018-09-28 14:29:17 +02002995 ret = apr_send_pkt(this_adm.apr,
2996 (uint32_t *)adm_params);
2997 if (ret < 0) {
2998 pr_err("%s: port_id: 0x%x for[0x%x] failed %d for open_v8\n",
2999 __func__, tmp_port, port_id, ret);
3000 return -EINVAL;
3001 }
3002 kfree(adm_params);
3003 } else {
3004
3005 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3006 APR_HDR_LEN(APR_HDR_SIZE),
3007 APR_PKT_VER);
3008 open.hdr.pkt_size = sizeof(open);
3009 open.hdr.src_svc = APR_SVC_ADM;
3010 open.hdr.src_domain = APR_DOMAIN_APPS;
3011 open.hdr.src_port = tmp_port;
3012 open.hdr.dest_svc = APR_SVC_ADM;
3013 open.hdr.dest_domain = APR_DOMAIN_ADSP;
3014 open.hdr.dest_port = tmp_port;
3015 open.hdr.token = port_idx << 16 | copp_idx;
3016 open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
3017 open.flags = flags;
3018 open.mode_of_operation = path;
3019 open.endpoint_id_1 = tmp_port;
3020 open.endpoint_id_2 = 0xFFFF;
3021
Surendar Karkae7507512018-07-20 15:46:54 +05303022 if (this_adm.ec_ref_rx && (path != 1) &&
3023 (afe_get_port_type(tmp_port) == MSM_AFE_PORT_TYPE_TX)) {
Dieter Luecking50c55352018-09-28 14:29:17 +02003024 open.endpoint_id_2 = this_adm.ec_ref_rx;
3025 this_adm.ec_ref_rx = -1;
3026 }
3027
3028 open.topology_id = topology;
3029
3030 open.dev_num_channel = channel_mode & 0x00FF;
3031 open.bit_width = bit_width;
3032 WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
3033 (rate != ULL_SUPPORTED_SAMPLE_RATE));
3034 open.sample_rate = rate;
3035
3036 ret = adm_arrange_mch_map(&open, path, channel_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303037
3038 if (ret)
3039 return ret;
3040
Dieter Luecking50c55352018-09-28 14:29:17 +02003041 pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
3042 __func__, open.endpoint_id_1, open.sample_rate,
3043 open.topology_id);
3044
3045 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3046
3047 if ((this_adm.num_ec_ref_rx_chans != 0) &&
3048 (path != 1) && (open.endpoint_id_2 != 0xFFFF)) {
3049 memset(&open_v6, 0,
3050 sizeof(struct adm_cmd_device_open_v6));
3051 memcpy(&open_v6, &open,
3052 sizeof(struct adm_cmd_device_open_v5));
3053 open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
3054 open_v6.hdr.pkt_size = sizeof(open_v6);
3055 open_v6.dev_num_channel_eid2 =
3056 this_adm.num_ec_ref_rx_chans;
3057 this_adm.num_ec_ref_rx_chans = 0;
3058
3059 if (this_adm.ec_ref_rx_bit_width != 0) {
3060 open_v6.bit_width_eid2 =
3061 this_adm.ec_ref_rx_bit_width;
3062 this_adm.ec_ref_rx_bit_width = 0;
3063 } else {
3064 open_v6.bit_width_eid2 = bit_width;
3065 }
3066
3067 if (this_adm.ec_ref_rx_sampling_rate != 0) {
3068 open_v6.sample_rate_eid2 =
3069 this_adm.ec_ref_rx_sampling_rate;
3070 this_adm.ec_ref_rx_sampling_rate = 0;
3071 } else {
3072 open_v6.sample_rate_eid2 = rate;
3073 }
3074
3075 pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
3076 __func__, open_v6.dev_num_channel_eid2,
3077 open_v6.bit_width_eid2,
3078 open_v6.sample_rate_eid2);
3079
3080 ret = adm_arrange_mch_ep2_map(&open_v6,
3081 open_v6.dev_num_channel_eid2);
3082
3083 if (ret)
3084 return ret;
3085
3086 ret = apr_send_pkt(this_adm.apr,
3087 (uint32_t *)&open_v6);
3088 } else {
3089 ret = apr_send_pkt(this_adm.apr,
3090 (uint32_t *)&open);
3091 }
3092 if (ret < 0) {
3093 pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
3094 __func__, tmp_port, port_id, ret);
3095 return -EINVAL;
3096 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303097 }
Dieter Luecking50c55352018-09-28 14:29:17 +02003098
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303099 /* Wait for the callback with copp id */
3100 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3101 atomic_read(&this_adm.copp.stat
3102 [port_idx][copp_idx]) >= 0,
3103 msecs_to_jiffies(TIMEOUT_MS));
3104 if (!ret) {
3105 pr_err("%s: ADM open timedout for port_id: 0x%x for [0x%x]\n",
3106 __func__, tmp_port, port_id);
3107 return -EINVAL;
3108 } else if (atomic_read(&this_adm.copp.stat
3109 [port_idx][copp_idx]) > 0) {
3110 pr_err("%s: DSP returned error[%s]\n",
3111 __func__, adsp_err_get_err_str(
3112 atomic_read(&this_adm.copp.stat
3113 [port_idx][copp_idx])));
3114 return adsp_err_get_lnx_err_code(
3115 atomic_read(&this_adm.copp.stat
3116 [port_idx][copp_idx]));
3117 }
3118 }
3119 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
3120 return copp_idx;
3121}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303122EXPORT_SYMBOL(adm_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303123
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303124/**
3125 * adm_copp_mfc_cfg -
3126 * command to send ADM MFC config
3127 *
3128 * @port_id: Port ID number
3129 * @copp_idx: copp index assigned
3130 * @dst_sample_rate: sink sample rate
3131 *
3132 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303133void adm_copp_mfc_cfg(int port_id, int copp_idx, int dst_sample_rate)
3134{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003135 struct audproc_mfc_param_media_fmt mfc_cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303136 struct adm_cmd_device_open_v5 open;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003137 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303138 int port_idx;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303139 int rc = 0;
3140 int i = 0;
3141
3142 port_id = q6audio_convert_virtual_to_portid(port_id);
3143 port_idx = adm_validate_and_get_port_index(port_id);
3144
3145 if (port_idx < 0) {
3146 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
3147 goto fail_cmd;
3148 }
3149
3150 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
3151 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
3152 goto fail_cmd;
3153 }
3154
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003155 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
3156 memset(&open, 0, sizeof(open));
3157 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303158
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003159 param_hdr.module_id = AUDPROC_MODULE_ID_MFC;
3160 param_hdr.instance_id = INSTANCE_ID_0;
3161 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
3162 param_hdr.param_size = sizeof(mfc_cfg);
3163
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303164 mfc_cfg.sampling_rate = dst_sample_rate;
3165 mfc_cfg.bits_per_sample =
3166 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
3167 open.dev_num_channel = mfc_cfg.num_channels =
3168 atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
3169
3170 rc = adm_arrange_mch_map(&open, ADM_PATH_PLAYBACK,
3171 mfc_cfg.num_channels);
3172 if (rc < 0) {
3173 pr_err("%s: unable to get channal map\n", __func__);
3174 goto fail_cmd;
3175 }
3176
3177 for (i = 0; i < mfc_cfg.num_channels; i++)
3178 mfc_cfg.channel_type[i] =
3179 (uint16_t) open.dev_channel_mapping[i];
3180
3181 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3182
3183 pr_debug("%s: mfc config: port_idx %d copp_idx %d copp SR %d copp BW %d copp chan %d o/p SR %d\n",
3184 __func__, port_idx, copp_idx,
3185 atomic_read(&this_adm.copp.rate[port_idx][copp_idx]),
3186 mfc_cfg.bits_per_sample, mfc_cfg.num_channels,
3187 mfc_cfg.sampling_rate);
3188
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003189 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
3190 (uint8_t *) &mfc_cfg);
3191 if (rc)
3192 pr_err("%s: Failed to set media format configuration data, err %d\n",
3193 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303194
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303195fail_cmd:
3196 return;
3197}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303198EXPORT_SYMBOL(adm_copp_mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303199
3200static void route_set_opcode_matrix_id(
3201 struct adm_cmd_matrix_map_routings_v5 **route_addr,
3202 int path, uint32_t passthr_mode)
3203{
3204 struct adm_cmd_matrix_map_routings_v5 *route = *route_addr;
3205
3206 switch (path) {
3207 case ADM_PATH_PLAYBACK:
3208 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
3209 route->matrix_id = ADM_MATRIX_ID_AUDIO_RX;
3210 break;
3211 case ADM_PATH_LIVE_REC:
3212 if (passthr_mode == LISTEN) {
3213 route->hdr.opcode =
3214 ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3215 route->matrix_id = ADM_MATRIX_ID_LISTEN_TX;
3216 break;
3217 }
3218 /* fall through to set matrix id for non-listen case */
3219 case ADM_PATH_NONLIVE_REC:
3220 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
3221 route->matrix_id = ADM_MATRIX_ID_AUDIO_TX;
3222 break;
3223 case ADM_PATH_COMPRESSED_RX:
3224 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3225 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_RX;
3226 break;
3227 case ADM_PATH_COMPRESSED_TX:
3228 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3229 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_TX;
3230 break;
3231 default:
3232 pr_err("%s: Wrong path set[%d]\n", __func__, path);
3233 break;
3234 }
3235 pr_debug("%s: opcode 0x%x, matrix id %d\n",
3236 __func__, route->hdr.opcode, route->matrix_id);
3237}
3238
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303239/**
3240 * adm_matrix_map -
3241 * command to send ADM matrix map for ADM copp list
3242 *
3243 * @path: direction or ADM path type
3244 * @payload_map: have info of session id and associated copp_idx/num_copps
3245 * @perf_mode: performance mode like LL/ULL/..
3246 * @passthr_mode: flag to indicate passthrough mode
3247 *
3248 * Returns 0 on success or error on failure
3249 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303250int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode,
3251 uint32_t passthr_mode)
3252{
3253 struct adm_cmd_matrix_map_routings_v5 *route;
3254 struct adm_session_map_node_v5 *node;
3255 uint16_t *copps_list;
3256 int cmd_size = 0;
3257 int ret = 0, i = 0;
3258 void *payload = NULL;
3259 void *matrix_map = NULL;
3260 int port_idx, copp_idx;
3261
3262 /* Assumes port_ids have already been validated during adm_open */
3263 cmd_size = (sizeof(struct adm_cmd_matrix_map_routings_v5) +
3264 sizeof(struct adm_session_map_node_v5) +
3265 (sizeof(uint32_t) * payload_map.num_copps));
3266 matrix_map = kzalloc(cmd_size, GFP_KERNEL);
3267 if (matrix_map == NULL) {
3268 pr_err("%s: Mem alloc failed\n", __func__);
3269 ret = -EINVAL;
3270 return ret;
3271 }
3272 route = (struct adm_cmd_matrix_map_routings_v5 *)matrix_map;
3273
3274 route->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3275 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3276 route->hdr.pkt_size = cmd_size;
3277 route->hdr.src_svc = 0;
3278 route->hdr.src_domain = APR_DOMAIN_APPS;
3279 route->hdr.src_port = 0; /* Ignored */;
3280 route->hdr.dest_svc = APR_SVC_ADM;
3281 route->hdr.dest_domain = APR_DOMAIN_ADSP;
3282 route->hdr.dest_port = 0; /* Ignored */;
3283 route->hdr.token = 0;
3284 route->num_sessions = 1;
3285 route_set_opcode_matrix_id(&route, path, passthr_mode);
3286
3287 payload = ((u8 *)matrix_map +
3288 sizeof(struct adm_cmd_matrix_map_routings_v5));
3289 node = (struct adm_session_map_node_v5 *)payload;
3290
3291 node->session_id = payload_map.session_id;
3292 node->num_copps = payload_map.num_copps;
3293 payload = (u8 *)node + sizeof(struct adm_session_map_node_v5);
3294 copps_list = (uint16_t *)payload;
3295 for (i = 0; i < payload_map.num_copps; i++) {
3296 port_idx =
3297 adm_validate_and_get_port_index(payload_map.port_id[i]);
3298 if (port_idx < 0) {
3299 pr_err("%s: Invalid port_id 0x%x\n", __func__,
3300 payload_map.port_id[i]);
3301 ret = -EINVAL;
3302 goto fail_cmd;
3303 }
3304 copp_idx = payload_map.copp_idx[i];
3305 copps_list[i] = atomic_read(&this_adm.copp.id[port_idx]
3306 [copp_idx]);
3307 }
3308 atomic_set(&this_adm.matrix_map_stat, -1);
3309
3310 ret = apr_send_pkt(this_adm.apr, (uint32_t *)matrix_map);
3311 if (ret < 0) {
3312 pr_err("%s: routing for syream %d failed ret %d\n",
3313 __func__, payload_map.session_id, ret);
3314 ret = -EINVAL;
3315 goto fail_cmd;
3316 }
3317 ret = wait_event_timeout(this_adm.matrix_map_wait,
3318 atomic_read(&this_adm.matrix_map_stat) >= 0,
3319 msecs_to_jiffies(TIMEOUT_MS));
3320 if (!ret) {
3321 pr_err("%s: routing for syream %d failed\n", __func__,
3322 payload_map.session_id);
3323 ret = -EINVAL;
3324 goto fail_cmd;
3325 } else if (atomic_read(&this_adm.matrix_map_stat) > 0) {
3326 pr_err("%s: DSP returned error[%s]\n", __func__,
3327 adsp_err_get_err_str(atomic_read(
3328 &this_adm.matrix_map_stat)));
3329 ret = adsp_err_get_lnx_err_code(
3330 atomic_read(&this_adm.matrix_map_stat));
3331 goto fail_cmd;
3332 }
3333
3334 if ((perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) &&
3335 (path != ADM_PATH_COMPRESSED_RX)) {
3336 for (i = 0; i < payload_map.num_copps; i++) {
3337 port_idx = afe_get_port_index(payload_map.port_id[i]);
3338 copp_idx = payload_map.copp_idx[i];
3339 if (port_idx < 0 || copp_idx < 0 ||
3340 (copp_idx > MAX_COPPS_PER_PORT - 1)) {
3341 pr_err("%s: Invalid idx port_idx %d copp_idx %d\n",
3342 __func__, port_idx, copp_idx);
3343 continue;
3344 }
3345 rtac_add_adm_device(payload_map.port_id[i],
3346 atomic_read(&this_adm.copp.id
3347 [port_idx][copp_idx]),
3348 get_cal_path(path),
3349 payload_map.session_id,
3350 payload_map.app_type[i],
3351 payload_map.acdb_dev_id[i]);
3352
3353 if (!test_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3354 (void *)&this_adm.copp.adm_status[port_idx]
3355 [copp_idx])) {
3356 pr_debug("%s: adm copp[0x%x][%d] already sent",
3357 __func__, port_idx, copp_idx);
3358 continue;
3359 }
3360 send_adm_cal(payload_map.port_id[i], copp_idx,
3361 get_cal_path(path), perf_mode,
3362 payload_map.app_type[i],
3363 payload_map.acdb_dev_id[i],
Aditya Bavanari5106b562018-01-08 13:16:32 +05303364 payload_map.sample_rate[i],
3365 passthr_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303366 /* ADM COPP calibration is already sent */
3367 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3368 (void *)&this_adm.copp.
3369 adm_status[port_idx][copp_idx]);
3370 pr_debug("%s: copp_id: %d\n", __func__,
3371 atomic_read(&this_adm.copp.id[port_idx]
3372 [copp_idx]));
3373 }
3374 }
3375
3376fail_cmd:
3377 kfree(matrix_map);
3378 return ret;
3379}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303380EXPORT_SYMBOL(adm_matrix_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303381
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303382/**
3383 * adm_ec_ref_rx_id -
3384 * Update EC ref port ID
3385 *
3386 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303387void adm_ec_ref_rx_id(int port_id)
3388{
3389 this_adm.ec_ref_rx = port_id;
3390 pr_debug("%s: ec_ref_rx:%d\n", __func__, this_adm.ec_ref_rx);
3391}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303392EXPORT_SYMBOL(adm_ec_ref_rx_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303393
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303394/**
3395 * adm_num_ec_ref_rx_chans -
3396 * Update EC ref number of channels
3397 *
3398 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303399void adm_num_ec_ref_rx_chans(int num_chans)
3400{
3401 this_adm.num_ec_ref_rx_chans = num_chans;
3402 pr_debug("%s: num_ec_ref_rx_chans:%d\n",
3403 __func__, this_adm.num_ec_ref_rx_chans);
3404}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303405EXPORT_SYMBOL(adm_num_ec_ref_rx_chans);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303406
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303407/**
3408 * adm_ec_ref_rx_bit_width -
3409 * Update EC ref bit_width
3410 *
3411 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303412void adm_ec_ref_rx_bit_width(int bit_width)
3413{
3414 this_adm.ec_ref_rx_bit_width = bit_width;
3415 pr_debug("%s: ec_ref_rx_bit_width:%d\n",
3416 __func__, this_adm.ec_ref_rx_bit_width);
3417}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303418EXPORT_SYMBOL(adm_ec_ref_rx_bit_width);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303419
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303420/**
3421 * adm_ec_ref_rx_sampling_rate -
3422 * Update EC ref sample rate
3423 *
3424 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303425void adm_ec_ref_rx_sampling_rate(int sampling_rate)
3426{
3427 this_adm.ec_ref_rx_sampling_rate = sampling_rate;
3428 pr_debug("%s: ec_ref_rx_sampling_rate:%d\n",
3429 __func__, this_adm.ec_ref_rx_sampling_rate);
3430}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303431EXPORT_SYMBOL(adm_ec_ref_rx_sampling_rate);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303432
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303433/**
Dieter Luecking50c55352018-09-28 14:29:17 +02003434 * adm_set_native_mode -
3435 * Set adm channel native mode.
3436 * If enabled matrix mixer will be
3437 * running in native mode for channel
3438 * configuration for this device session.
3439 *
3440 */
3441void adm_set_native_mode(int mode)
3442{
3443 this_adm.native_mode = mode;
3444 pr_debug("%s: enable native_mode :%d\n",
3445 __func__, this_adm.native_mode);
3446}
3447EXPORT_SYMBOL(adm_set_native_mode);
3448
3449/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303450 * adm_close -
3451 * command to close ADM copp
3452 *
3453 * @port_id: Port ID number
3454 * @perf_mode: performance mode like LL/ULL/..
3455 * @copp_idx: copp index assigned
3456 *
3457 * Returns 0 on success or error on failure
3458 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303459int adm_close(int port_id, int perf_mode, int copp_idx)
3460{
3461 struct apr_hdr close;
3462
3463 int ret = 0, port_idx;
3464 int copp_id = RESET_COPP_ID;
3465
3466 pr_debug("%s: port_id=0x%x perf_mode: %d copp_idx: %d\n", __func__,
3467 port_id, perf_mode, copp_idx);
3468
3469 port_id = q6audio_convert_virtual_to_portid(port_id);
3470 port_idx = adm_validate_and_get_port_index(port_id);
3471 if (port_idx < 0) {
3472 pr_err("%s: Invalid port_id 0x%x\n",
3473 __func__, port_id);
3474 return -EINVAL;
3475 }
3476
3477 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
3478 pr_err("%s: Invalid copp idx: %d\n", __func__, copp_idx);
3479 return -EINVAL;
3480 }
3481
3482 if (this_adm.copp.adm_delay[port_idx][copp_idx] && perf_mode
3483 == LEGACY_PCM_MODE) {
3484 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
3485 1);
3486 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
3487 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
3488 }
3489
3490 atomic_dec(&this_adm.copp.cnt[port_idx][copp_idx]);
3491 if (!(atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]))) {
3492 copp_id = adm_get_copp_id(port_idx, copp_idx);
3493 pr_debug("%s: Closing ADM port_idx:%d copp_idx:%d copp_id:0x%x\n",
3494 __func__, port_idx, copp_idx, copp_id);
3495 if ((!perf_mode) && (this_adm.outband_memmap.paddr != 0) &&
3496 (atomic_read(&this_adm.copp.topology[port_idx][copp_idx]) ==
3497 SRS_TRUMEDIA_TOPOLOGY_ID)) {
3498 atomic_set(&this_adm.mem_map_index,
3499 ADM_SRS_TRUMEDIA);
3500 ret = adm_memory_unmap_regions();
3501 if (ret < 0) {
3502 pr_err("%s: adm mem unmmap err %d",
3503 __func__, ret);
3504 } else {
3505 atomic_set(&this_adm.mem_map_handles
3506 [ADM_SRS_TRUMEDIA], 0);
3507 }
3508 }
3509
3510
3511 if ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) &&
3512 this_adm.sourceTrackingData.memmap.paddr) {
3513 atomic_set(&this_adm.mem_map_index,
3514 ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
3515 ret = adm_memory_unmap_regions();
3516 if (ret < 0) {
3517 pr_err("%s: adm mem unmmap err %d",
3518 __func__, ret);
3519 }
3520 msm_audio_ion_free(
Banajit Goswami08bb7362017-11-03 22:48:23 -07003521 this_adm.sourceTrackingData.dma_buf);
3522 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303523 this_adm.sourceTrackingData.memmap.size = 0;
3524 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
3525 this_adm.sourceTrackingData.memmap.paddr = 0;
3526 this_adm.sourceTrackingData.apr_cmd_status = -1;
3527 atomic_set(&this_adm.mem_map_handles[
3528 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
3529 }
3530
3531 close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3532 APR_HDR_LEN(APR_HDR_SIZE),
3533 APR_PKT_VER);
3534 close.pkt_size = sizeof(close);
3535 close.src_svc = APR_SVC_ADM;
3536 close.src_domain = APR_DOMAIN_APPS;
3537 close.src_port = port_id;
3538 close.dest_svc = APR_SVC_ADM;
3539 close.dest_domain = APR_DOMAIN_ADSP;
3540 close.dest_port = copp_id;
3541 close.token = port_idx << 16 | copp_idx;
3542 close.opcode = ADM_CMD_DEVICE_CLOSE_V5;
3543
3544 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
3545 RESET_COPP_ID);
3546 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
3547 atomic_set(&this_adm.copp.topology[port_idx][copp_idx], 0);
3548 atomic_set(&this_adm.copp.mode[port_idx][copp_idx], 0);
3549 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3550 atomic_set(&this_adm.copp.rate[port_idx][copp_idx], 0);
3551 atomic_set(&this_adm.copp.channels[port_idx][copp_idx], 0);
3552 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx], 0);
3553 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx], 0);
Surendar Karkae7507512018-07-20 15:46:54 +05303554 atomic_set(&this_adm.copp.session_type[port_idx][copp_idx], 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303555
3556 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3557 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
3558
3559 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
3560 if (ret < 0) {
3561 pr_err("%s: ADM close failed %d\n", __func__, ret);
3562 return -EINVAL;
3563 }
3564
3565 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3566 atomic_read(&this_adm.copp.stat
3567 [port_idx][copp_idx]) >= 0,
3568 msecs_to_jiffies(TIMEOUT_MS));
3569 if (!ret) {
3570 pr_err("%s: ADM cmd Route timedout for port 0x%x\n",
3571 __func__, port_id);
3572 return -EINVAL;
3573 } else if (atomic_read(&this_adm.copp.stat
3574 [port_idx][copp_idx]) > 0) {
3575 pr_err("%s: DSP returned error[%s]\n",
3576 __func__, adsp_err_get_err_str(
3577 atomic_read(&this_adm.copp.stat
3578 [port_idx][copp_idx])));
3579 return adsp_err_get_lnx_err_code(
3580 atomic_read(&this_adm.copp.stat
3581 [port_idx][copp_idx]));
3582 }
3583 }
3584
3585 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
3586 pr_debug("%s: remove adm device from rtac\n", __func__);
3587 rtac_remove_adm_device(port_id, copp_id);
3588 }
3589 return 0;
3590}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303591EXPORT_SYMBOL(adm_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303592
3593int send_rtac_audvol_cal(void)
3594{
3595 int ret = 0;
3596 int ret2 = 0;
3597 int i = 0;
3598 int copp_idx, port_idx, acdb_id, app_id, path;
3599 struct cal_block_data *cal_block = NULL;
3600 struct audio_cal_info_audvol *audvol_cal_info = NULL;
3601 struct rtac_adm rtac_adm_data;
3602
3603 mutex_lock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
3604
3605 cal_block = cal_utils_get_only_cal_block(
3606 this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07003607 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303608 pr_err("%s: can't find cal block!\n", __func__);
3609 goto unlock;
3610 }
3611
3612 audvol_cal_info = cal_block->cal_info;
3613 if (audvol_cal_info == NULL) {
3614 pr_err("%s: audvol_cal_info is NULL!\n", __func__);
3615 goto unlock;
3616 }
3617
3618 get_rtac_adm_data(&rtac_adm_data);
3619 for (; i < rtac_adm_data.num_of_dev; i++) {
3620
3621 acdb_id = rtac_adm_data.device[i].acdb_dev_id;
3622 if (acdb_id == 0)
3623 acdb_id = audvol_cal_info->acdb_id;
3624
3625 app_id = rtac_adm_data.device[i].app_type;
3626 if (app_id == 0)
3627 app_id = audvol_cal_info->app_type;
3628
3629 path = afe_get_port_type(rtac_adm_data.device[i].afe_port);
3630 if ((acdb_id == audvol_cal_info->acdb_id) &&
3631 (app_id == audvol_cal_info->app_type) &&
3632 (path == audvol_cal_info->path)) {
3633
3634 if (adm_get_indexes_from_copp_id(rtac_adm_data.
3635 device[i].copp, &copp_idx, &port_idx) != 0) {
3636 pr_debug("%s: Copp Id %d is not active\n",
3637 __func__,
3638 rtac_adm_data.device[i].copp);
3639 continue;
3640 }
3641
3642 ret2 = adm_remap_and_send_cal_block(ADM_RTAC_AUDVOL_CAL,
3643 rtac_adm_data.device[i].afe_port,
3644 copp_idx, cal_block,
3645 atomic_read(&this_adm.copp.
3646 mode[port_idx][copp_idx]),
3647 audvol_cal_info->app_type,
3648 audvol_cal_info->acdb_id,
3649 atomic_read(&this_adm.copp.
3650 rate[port_idx][copp_idx]));
3651 if (ret2 < 0) {
3652 pr_debug("%s: remap and send failed for copp Id %d, acdb id %d, app type %d, path %d\n",
3653 __func__, rtac_adm_data.device[i].copp,
3654 audvol_cal_info->acdb_id,
3655 audvol_cal_info->app_type,
3656 audvol_cal_info->path);
3657 ret = ret2;
3658 }
3659 }
3660 }
3661unlock:
3662 mutex_unlock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
3663 return ret;
3664}
3665
3666int adm_map_rtac_block(struct rtac_cal_block_data *cal_block)
3667{
3668 int result = 0;
3669
3670 pr_debug("%s:\n", __func__);
3671
3672 if (cal_block == NULL) {
3673 pr_err("%s: cal_block is NULL!\n",
3674 __func__);
3675 result = -EINVAL;
3676 goto done;
3677 }
3678
3679 if (cal_block->cal_data.paddr == 0) {
3680 pr_debug("%s: No address to map!\n",
3681 __func__);
3682 result = -EINVAL;
3683 goto done;
3684 }
3685
3686 if (cal_block->map_data.map_size == 0) {
3687 pr_debug("%s: map size is 0!\n",
3688 __func__);
3689 result = -EINVAL;
3690 goto done;
3691 }
3692
3693 /* valid port ID needed for callback use primary I2S */
3694 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
3695 result = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
3696 &cal_block->map_data.map_size, 1);
3697 if (result < 0) {
3698 pr_err("%s: RTAC mmap did not work! size = %d result %d\n",
3699 __func__,
3700 cal_block->map_data.map_size, result);
3701 pr_debug("%s: RTAC mmap did not work! addr = 0x%pK, size = %d\n",
3702 __func__,
3703 &cal_block->cal_data.paddr,
3704 cal_block->map_data.map_size);
3705 goto done;
3706 }
3707
3708 cal_block->map_data.map_handle = atomic_read(
3709 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]);
3710done:
3711 return result;
3712}
3713
3714int adm_unmap_rtac_block(uint32_t *mem_map_handle)
3715{
3716 int result = 0;
3717
3718 pr_debug("%s:\n", __func__);
3719
3720 if (mem_map_handle == NULL) {
3721 pr_debug("%s: Map handle is NULL, nothing to unmap\n",
3722 __func__);
3723 goto done;
3724 }
3725
3726 if (*mem_map_handle == 0) {
3727 pr_debug("%s: Map handle is 0, nothing to unmap\n",
3728 __func__);
3729 goto done;
3730 }
3731
3732 if (*mem_map_handle != atomic_read(
3733 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL])) {
3734 pr_err("%s: Map handles do not match! Unmapping RTAC, RTAC map 0x%x, ADM map 0x%x\n",
3735 __func__, *mem_map_handle, atomic_read(
3736 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]));
3737
3738 /* if mismatch use handle passed in to unmap */
3739 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL],
3740 *mem_map_handle);
3741 }
3742
3743 /* valid port ID needed for callback use primary I2S */
3744 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
3745 result = adm_memory_unmap_regions();
3746 if (result < 0) {
3747 pr_debug("%s: adm_memory_unmap_regions failed, error %d\n",
3748 __func__, result);
3749 } else {
3750 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL], 0);
3751 *mem_map_handle = 0;
3752 }
3753done:
3754 return result;
3755}
3756
3757static int get_cal_type_index(int32_t cal_type)
3758{
3759 int ret = -EINVAL;
3760
3761 switch (cal_type) {
3762 case ADM_AUDPROC_CAL_TYPE:
3763 ret = ADM_AUDPROC_CAL;
3764 break;
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05303765 case ADM_LSM_AUDPROC_CAL_TYPE:
3766 ret = ADM_LSM_AUDPROC_CAL;
3767 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303768 case ADM_AUDVOL_CAL_TYPE:
3769 ret = ADM_AUDVOL_CAL;
3770 break;
3771 case ADM_CUST_TOPOLOGY_CAL_TYPE:
3772 ret = ADM_CUSTOM_TOP_CAL;
3773 break;
3774 case ADM_RTAC_INFO_CAL_TYPE:
3775 ret = ADM_RTAC_INFO_CAL;
3776 break;
3777 case ADM_RTAC_APR_CAL_TYPE:
3778 ret = ADM_RTAC_APR_CAL;
3779 break;
3780 case ADM_RTAC_AUDVOL_CAL_TYPE:
3781 ret = ADM_RTAC_AUDVOL_CAL;
3782 break;
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07003783 case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
3784 ret = ADM_LSM_AUDPROC_PERSISTENT_CAL;
3785 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303786 default:
3787 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
3788 }
3789 return ret;
3790}
3791
3792static int adm_alloc_cal(int32_t cal_type, size_t data_size, void *data)
3793{
3794 int ret = 0;
3795 int cal_index;
3796
3797 pr_debug("%s:\n", __func__);
3798
3799 cal_index = get_cal_type_index(cal_type);
3800 if (cal_index < 0) {
3801 pr_err("%s: could not get cal index %d!\n",
3802 __func__, cal_index);
3803 ret = -EINVAL;
3804 goto done;
3805 }
3806
3807 ret = cal_utils_alloc_cal(data_size, data,
3808 this_adm.cal_data[cal_index], 0, NULL);
3809 if (ret < 0) {
3810 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
3811 __func__, ret, cal_type);
3812 ret = -EINVAL;
3813 goto done;
3814 }
3815done:
3816 return ret;
3817}
3818
3819static int adm_dealloc_cal(int32_t cal_type, size_t data_size, void *data)
3820{
3821 int ret = 0;
3822 int cal_index;
3823
3824 pr_debug("%s:\n", __func__);
3825
3826 cal_index = get_cal_type_index(cal_type);
3827 if (cal_index < 0) {
3828 pr_err("%s: could not get cal index %d!\n",
3829 __func__, cal_index);
3830 ret = -EINVAL;
3831 goto done;
3832 }
3833
3834 ret = cal_utils_dealloc_cal(data_size, data,
3835 this_adm.cal_data[cal_index]);
3836 if (ret < 0) {
3837 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
3838 __func__, ret, cal_type);
3839 ret = -EINVAL;
3840 goto done;
3841 }
3842done:
3843 return ret;
3844}
3845
3846static int adm_set_cal(int32_t cal_type, size_t data_size, void *data)
3847{
3848 int ret = 0;
3849 int cal_index;
3850
3851 pr_debug("%s:\n", __func__);
3852
3853 cal_index = get_cal_type_index(cal_type);
3854 if (cal_index < 0) {
3855 pr_err("%s: could not get cal index %d!\n",
3856 __func__, cal_index);
3857 ret = -EINVAL;
3858 goto done;
3859 }
3860
3861 ret = cal_utils_set_cal(data_size, data,
3862 this_adm.cal_data[cal_index], 0, NULL);
3863 if (ret < 0) {
3864 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
3865 __func__, ret, cal_type);
3866 ret = -EINVAL;
3867 goto done;
3868 }
3869
3870 if (cal_index == ADM_CUSTOM_TOP_CAL) {
3871 mutex_lock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
3872 this_adm.set_custom_topology = 1;
3873 mutex_unlock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
3874 } else if (cal_index == ADM_RTAC_AUDVOL_CAL) {
3875 send_rtac_audvol_cal();
3876 }
3877done:
3878 return ret;
3879}
3880
3881static int adm_map_cal_data(int32_t cal_type,
3882 struct cal_block_data *cal_block)
3883{
3884 int ret = 0;
3885 int cal_index;
3886
3887 pr_debug("%s:\n", __func__);
3888
3889 cal_index = get_cal_type_index(cal_type);
3890 if (cal_index < 0) {
3891 pr_err("%s: could not get cal index %d!\n",
3892 __func__, cal_index);
3893 ret = -EINVAL;
3894 goto done;
3895 }
3896
3897 atomic_set(&this_adm.mem_map_index, cal_index);
3898 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
3899 (uint32_t *)&cal_block->map_data.map_size, 1);
3900 if (ret < 0) {
3901 pr_err("%s: map did not work! cal_type %i ret %d\n",
3902 __func__, cal_index, ret);
3903 ret = -ENODEV;
3904 goto done;
3905 }
3906 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
3907 mem_map_handles[cal_index]);
3908done:
3909 return ret;
3910}
3911
3912static int adm_unmap_cal_data(int32_t cal_type,
3913 struct cal_block_data *cal_block)
3914{
3915 int ret = 0;
3916 int cal_index;
3917
3918 pr_debug("%s:\n", __func__);
3919
3920 cal_index = get_cal_type_index(cal_type);
3921 if (cal_index < 0) {
3922 pr_err("%s: could not get cal index %d!\n",
3923 __func__, cal_index);
3924 ret = -EINVAL;
3925 goto done;
3926 }
3927
3928 if (cal_block == NULL) {
3929 pr_err("%s: Cal block is NULL!\n",
3930 __func__);
3931 goto done;
3932 }
3933
3934 if (cal_block->map_data.q6map_handle == 0) {
3935 pr_err("%s: Map handle is NULL, nothing to unmap\n",
3936 __func__);
3937 goto done;
3938 }
3939
3940 atomic_set(&this_adm.mem_map_handles[cal_index],
3941 cal_block->map_data.q6map_handle);
3942 atomic_set(&this_adm.mem_map_index, cal_index);
3943 ret = adm_memory_unmap_regions();
3944 if (ret < 0) {
3945 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
3946 __func__, cal_index, ret);
3947 ret = -ENODEV;
3948 goto done;
3949 }
3950 cal_block->map_data.q6map_handle = 0;
3951done:
3952 return ret;
3953}
3954
3955static void adm_delete_cal_data(void)
3956{
3957 pr_debug("%s:\n", __func__);
3958
3959 cal_utils_destroy_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data);
3960}
3961
3962static int adm_init_cal_data(void)
3963{
3964 int ret = 0;
3965 struct cal_type_info cal_type_info[] = {
3966 {{ADM_CUST_TOPOLOGY_CAL_TYPE,
3967 {adm_alloc_cal, adm_dealloc_cal, NULL,
3968 adm_set_cal, NULL, NULL} },
3969 {adm_map_cal_data, adm_unmap_cal_data,
3970 cal_utils_match_buf_num} },
3971
3972 {{ADM_AUDPROC_CAL_TYPE,
3973 {adm_alloc_cal, adm_dealloc_cal, NULL,
3974 adm_set_cal, NULL, NULL} },
3975 {adm_map_cal_data, adm_unmap_cal_data,
3976 cal_utils_match_buf_num} },
3977
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05303978 {{ADM_LSM_AUDPROC_CAL_TYPE,
3979 {adm_alloc_cal, adm_dealloc_cal, NULL,
3980 adm_set_cal, NULL, NULL} },
3981 {adm_map_cal_data, adm_unmap_cal_data,
3982 cal_utils_match_buf_num} },
3983
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303984 {{ADM_AUDVOL_CAL_TYPE,
3985 {adm_alloc_cal, adm_dealloc_cal, NULL,
3986 adm_set_cal, NULL, NULL} },
3987 {adm_map_cal_data, adm_unmap_cal_data,
3988 cal_utils_match_buf_num} },
3989
3990 {{ADM_RTAC_INFO_CAL_TYPE,
3991 {NULL, NULL, NULL, NULL, NULL, NULL} },
3992 {NULL, NULL, cal_utils_match_buf_num} },
3993
3994 {{ADM_RTAC_APR_CAL_TYPE,
3995 {NULL, NULL, NULL, NULL, NULL, NULL} },
3996 {NULL, NULL, cal_utils_match_buf_num} },
3997
3998 {{SRS_TRUMEDIA_CAL_TYPE,
3999 {NULL, NULL, NULL, NULL, NULL, NULL} },
4000 {NULL, NULL, cal_utils_match_buf_num} },
4001
4002 {{ADM_RTAC_AUDVOL_CAL_TYPE,
4003 {adm_alloc_cal, adm_dealloc_cal, NULL,
4004 adm_set_cal, NULL, NULL} },
4005 {adm_map_cal_data, adm_unmap_cal_data,
4006 cal_utils_match_buf_num} },
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004007
4008 {{ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE,
4009 {adm_alloc_cal, adm_dealloc_cal, NULL,
4010 adm_set_cal, NULL, NULL} },
4011 {adm_map_cal_data, adm_unmap_cal_data,
4012 cal_utils_match_buf_num} },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304013 };
4014 pr_debug("%s:\n", __func__);
4015
4016 ret = cal_utils_create_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data,
4017 cal_type_info);
4018 if (ret < 0) {
4019 pr_err("%s: could not create cal type! ret %d\n",
4020 __func__, ret);
4021 ret = -EINVAL;
4022 goto err;
4023 }
4024
4025 return ret;
4026err:
4027 adm_delete_cal_data();
4028 return ret;
4029}
4030
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304031/**
4032 * adm_set_volume -
4033 * command to set volume on ADM copp
4034 *
4035 * @port_id: Port ID number
4036 * @copp_idx: copp index assigned
4037 * @volume: gain value to set
4038 *
4039 * Returns 0 on success or error on failure
4040 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304041int adm_set_volume(int port_id, int copp_idx, int volume)
4042{
4043 struct audproc_volume_ctrl_master_gain audproc_vol;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004044 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304045 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304046
4047 pr_debug("%s: port_id %d, volume %d\n", __func__, port_id, volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304048
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004049 memset(&audproc_vol, 0, sizeof(audproc_vol));
4050 memset(&param_hdr, 0, sizeof(param_hdr));
4051 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
4052 param_hdr.instance_id = INSTANCE_ID_0;
4053 param_hdr.param_id = AUDPROC_PARAM_ID_VOL_CTRL_MASTER_GAIN;
4054 param_hdr.param_size = sizeof(audproc_vol);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304055
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304056 audproc_vol.master_gain = volume;
4057
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004058 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4059 (uint8_t *) &audproc_vol);
4060 if (rc)
4061 pr_err("%s: Failed to set volume, err %d\n", __func__, rc);
4062
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304063 return rc;
4064}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304065EXPORT_SYMBOL(adm_set_volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304066
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304067/**
4068 * adm_set_softvolume -
4069 * command to set softvolume
4070 *
4071 * @port_id: Port ID number
4072 * @copp_idx: copp index assigned
4073 * @softvol_param: Params to set for softvolume
4074 *
4075 * Returns 0 on success or error on failure
4076 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304077int adm_set_softvolume(int port_id, int copp_idx,
4078 struct audproc_softvolume_params *softvol_param)
4079{
4080 struct audproc_soft_step_volume_params audproc_softvol;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004081 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304082 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304083
4084 pr_debug("%s: period %d step %d curve %d\n", __func__,
4085 softvol_param->period, softvol_param->step,
4086 softvol_param->rampingcurve);
4087
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004088 memset(&audproc_softvol, 0, sizeof(audproc_softvol));
4089 memset(&param_hdr, 0, sizeof(param_hdr));
4090 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
4091 param_hdr.instance_id = INSTANCE_ID_0;
4092 param_hdr.param_id = AUDPROC_PARAM_ID_SOFT_VOL_STEPPING_PARAMETERS;
4093 param_hdr.param_size = sizeof(audproc_softvol);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304094
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304095 audproc_softvol.period = softvol_param->period;
4096 audproc_softvol.step = softvol_param->step;
4097 audproc_softvol.ramping_curve = softvol_param->rampingcurve;
4098
4099 pr_debug("%s: period %d, step %d, curve %d\n", __func__,
4100 audproc_softvol.period, audproc_softvol.step,
4101 audproc_softvol.ramping_curve);
4102
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004103 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4104 (uint8_t *) &audproc_softvol);
4105 if (rc)
4106 pr_err("%s: Failed to set soft volume, err %d\n", __func__, rc);
4107
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304108 return rc;
4109}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304110EXPORT_SYMBOL(adm_set_softvolume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304111
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304112/**
4113 * adm_set_mic_gain -
4114 * command to set MIC gain
4115 *
4116 * @port_id: Port ID number
4117 * @copp_idx: copp index assigned
4118 * @volume: gain value to set
4119 *
4120 * Returns 0 on success or error on failure
4121 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304122int adm_set_mic_gain(int port_id, int copp_idx, int volume)
4123{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004124 struct admx_mic_gain mic_gain_params;
4125 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304126 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304127
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004128 pr_debug("%s: Setting mic gain to %d at port_id 0x%x\n", __func__,
4129 volume, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304130
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004131 memset(&mic_gain_params, 0, sizeof(mic_gain_params));
4132 memset(&param_hdr, 0, sizeof(param_hdr));
4133 param_hdr.module_id = ADM_MODULE_IDX_MIC_GAIN_CTRL;
4134 param_hdr.instance_id = INSTANCE_ID_0;
4135 param_hdr.param_id = ADM_PARAM_IDX_MIC_GAIN;
4136 param_hdr.param_size = sizeof(mic_gain_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304137
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004138 mic_gain_params.tx_mic_gain = volume;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304139
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004140 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4141 (uint8_t *) &mic_gain_params);
4142 if (rc)
4143 pr_err("%s: Failed to set mic gain, err %d\n", __func__, rc);
4144
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304145 return rc;
4146}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304147EXPORT_SYMBOL(adm_set_mic_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304148
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304149/**
4150 * adm_send_set_multichannel_ec_primary_mic_ch -
4151 * command to set multi-ch EC primary mic
4152 *
4153 * @port_id: Port ID number
4154 * @copp_idx: copp index assigned
4155 * @primary_mic_ch: channel number of primary mic
4156 *
4157 * Returns 0 on success or error on failure
4158 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304159int adm_send_set_multichannel_ec_primary_mic_ch(int port_id, int copp_idx,
4160 int primary_mic_ch)
4161{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004162 struct admx_sec_primary_mic_ch sec_primary_ch_params;
4163 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304164 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304165
4166 pr_debug("%s port_id 0x%x, copp_idx 0x%x, primary_mic_ch %d\n",
4167 __func__, port_id, copp_idx, primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304168
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004169 memset(&sec_primary_ch_params, 0, sizeof(sec_primary_ch_params));
4170 memset(&param_hdr, 0, sizeof(param_hdr));
4171 param_hdr.module_id = AUDPROC_MODULE_ID_VOICE_TX_SECNS;
4172 param_hdr.instance_id = INSTANCE_ID_0;
4173 param_hdr.param_id = AUDPROC_PARAM_IDX_SEC_PRIMARY_MIC_CH;
4174 param_hdr.param_size = sizeof(sec_primary_ch_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304175
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004176 sec_primary_ch_params.version = 0;
4177 sec_primary_ch_params.sec_primary_mic_ch = primary_mic_ch;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304178
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004179 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4180 (uint8_t *) &sec_primary_ch_params);
4181 if (rc)
4182 pr_err("%s: Failed to set primary mic chanel, err %d\n",
4183 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304184
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304185 return rc;
4186}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304187EXPORT_SYMBOL(adm_send_set_multichannel_ec_primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304188
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304189/**
4190 * adm_param_enable -
4191 * command to send params to ADM for given module
4192 *
4193 * @port_id: Port ID number
4194 * @copp_idx: copp index assigned
4195 * @module_id: ADM module
4196 * @enable: flag to enable or disable module
4197 *
4198 * Returns 0 on success or error on failure
4199 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304200int adm_param_enable(int port_id, int copp_idx, int module_id, int enable)
4201{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004202 struct module_instance_info mod_inst_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304203
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004204 memset(&mod_inst_info, 0, sizeof(mod_inst_info));
4205 mod_inst_info.module_id = module_id;
4206 mod_inst_info.instance_id = INSTANCE_ID_0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304207
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004208 return adm_param_enable_v2(port_id, copp_idx, mod_inst_info, enable);
4209}
Vidyakumar Athota98464a22018-03-15 20:39:37 -07004210EXPORT_SYMBOL(adm_param_enable);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004211
4212/**
4213 * adm_param_enable_v2 -
4214 * command to send params to ADM for given module
4215 *
4216 * @port_id: Port ID number
4217 * @copp_idx: copp index assigned
4218 * @mod_inst_info: module and instance ID info
4219 * @enable: flag to enable or disable module
4220 *
4221 * Returns 0 on success or error on failure
4222 */
4223int adm_param_enable_v2(int port_id, int copp_idx,
4224 struct module_instance_info mod_inst_info, int enable)
4225{
4226 uint32_t enable_param;
4227 struct param_hdr_v3 param_hdr;
4228 int rc = 0;
4229
4230 if (enable < 0 || enable > 1) {
4231 pr_err("%s: Invalid value for enable %d\n", __func__, enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304232 return -EINVAL;
4233 }
4234
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004235 pr_debug("%s port_id %d, module_id 0x%x, instance_id 0x%x, enable %d\n",
4236 __func__, port_id, mod_inst_info.module_id,
4237 mod_inst_info.instance_id, enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304238
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004239 memset(&param_hdr, 0, sizeof(param_hdr));
4240 param_hdr.module_id = mod_inst_info.module_id;
4241 param_hdr.instance_id = mod_inst_info.instance_id;
4242 param_hdr.param_id = AUDPROC_PARAM_ID_ENABLE;
4243 param_hdr.param_size = sizeof(enable_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304244
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004245 enable_param = enable;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304246
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004247 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4248 (uint8_t *) &enable_param);
4249 if (rc)
4250 pr_err("%s: Failed to set enable of module(%d) instance(%d) to %d, err %d\n",
4251 __func__, mod_inst_info.module_id,
4252 mod_inst_info.instance_id, enable, rc);
4253
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304254 return rc;
4255
4256}
Vidyakumar Athota98464a22018-03-15 20:39:37 -07004257EXPORT_SYMBOL(adm_param_enable_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304258
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304259/**
4260 * adm_send_calibration -
4261 * send ADM calibration to DSP
4262 *
4263 * @port_id: Port ID number
4264 * @copp_idx: copp index assigned
4265 * @path: direction or ADM path type
4266 * @perf_mode: performance mode like LL/ULL/..
4267 * @cal_type: calibration type to use
4268 * @params: pointer with cal data
4269 * @size: cal size
4270 *
4271 * Returns 0 on success or error on failure
4272 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304273int adm_send_calibration(int port_id, int copp_idx, int path, int perf_mode,
4274 int cal_type, char *params, int size)
4275{
4276
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004277 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304278
4279 pr_debug("%s:port_id %d, path %d, perf_mode %d, cal_type %d, size %d\n",
4280 __func__, port_id, path, perf_mode, cal_type, size);
4281
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304282 /* Maps audio_dev_ctrl path definition to ACDB definition */
4283 if (get_cal_path(path) != RX_DEVICE) {
4284 pr_err("%s: acdb_path %d\n", __func__, path);
4285 rc = -EINVAL;
4286 goto end;
4287 }
4288
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004289 rc = adm_set_pp_params(port_id, copp_idx, NULL, (u8 *) params, size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304290
4291end:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304292 return rc;
4293}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304294EXPORT_SYMBOL(adm_send_calibration);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304295
4296/*
4297 * adm_update_wait_parameters must be called with routing driver locks.
4298 * adm_reset_wait_parameters must be called with routing driver locks.
4299 * set and reset parmeters are separated to make sure it is always called
4300 * under routing driver lock.
4301 * adm_wait_timeout is to block until timeout or interrupted. Timeout is
4302 * not a an error.
4303 */
4304int adm_set_wait_parameters(int port_id, int copp_idx)
4305{
4306
4307 int ret = 0, port_idx;
4308
4309 pr_debug("%s: port_id 0x%x, copp_idx %d\n", __func__, port_id,
4310 copp_idx);
4311 port_id = afe_convert_virtual_to_portid(port_id);
4312 port_idx = adm_validate_and_get_port_index(port_id);
4313 if (port_idx < 0) {
4314 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4315 ret = -EINVAL;
4316 goto end;
4317 }
4318
4319 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4320 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4321 return -EINVAL;
4322 }
4323
4324 this_adm.copp.adm_delay[port_idx][copp_idx] = 1;
4325 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 0);
4326
4327end:
4328 return ret;
4329
4330}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304331EXPORT_SYMBOL(adm_set_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304332
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304333/**
4334 * adm_reset_wait_parameters -
4335 * reset wait parameters or ADM delay value
4336 *
4337 * @port_id: Port ID number
4338 * @copp_idx: copp index assigned
4339 *
4340 * Returns 0 on success or error on failure
4341 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304342int adm_reset_wait_parameters(int port_id, int copp_idx)
4343{
4344 int ret = 0, port_idx;
4345
4346 pr_debug("%s: port_id 0x%x copp_idx %d\n", __func__, port_id,
4347 copp_idx);
4348 port_id = afe_convert_virtual_to_portid(port_id);
4349 port_idx = adm_validate_and_get_port_index(port_id);
4350 if (port_idx < 0) {
4351 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4352 ret = -EINVAL;
4353 goto end;
4354 }
4355
4356 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4357 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4358 return -EINVAL;
4359 }
4360
4361 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 1);
4362 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
4363
4364end:
4365 return ret;
4366}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304367EXPORT_SYMBOL(adm_reset_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304368
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304369/**
4370 * adm_wait_timeout -
4371 * ADM wait command after command send to DSP
4372 *
4373 * @port_id: Port ID number
4374 * @copp_idx: copp index assigned
4375 * @wait_time: value in ms for command timeout
4376 *
4377 * Returns 0 on success or error on failure
4378 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304379int adm_wait_timeout(int port_id, int copp_idx, int wait_time)
4380{
4381 int ret = 0, port_idx;
4382
4383 pr_debug("%s: port_id 0x%x, copp_idx %d, wait_time %d\n", __func__,
4384 port_id, copp_idx, wait_time);
4385 port_id = afe_convert_virtual_to_portid(port_id);
4386 port_idx = adm_validate_and_get_port_index(port_id);
4387 if (port_idx < 0) {
4388 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4389 ret = -EINVAL;
4390 goto end;
4391 }
4392
4393 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4394 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4395 return -EINVAL;
4396 }
4397
4398 ret = wait_event_timeout(
4399 this_adm.copp.adm_delay_wait[port_idx][copp_idx],
4400 atomic_read(&this_adm.copp.adm_delay_stat[port_idx][copp_idx]),
4401 msecs_to_jiffies(wait_time));
4402 pr_debug("%s: return %d\n", __func__, ret);
4403 if (ret != 0)
4404 ret = -EINTR;
4405end:
4406 pr_debug("%s: return %d--\n", __func__, ret);
4407 return ret;
4408}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304409EXPORT_SYMBOL(adm_wait_timeout);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304410
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304411/**
4412 * adm_store_cal_data -
4413 * Retrieve calibration data for ADM copp device
4414 *
4415 * @port_id: Port ID number
4416 * @copp_idx: copp index assigned
4417 * @path: direction or copp type
4418 * @perf_mode: performance mode like LL/ULL/..
4419 * @cal_index: calibration index to use
4420 * @params: pointer to store cal data
4421 * @size: pointer to fill with cal size
4422 *
4423 * Returns 0 on success or error on failure
4424 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304425int adm_store_cal_data(int port_id, int copp_idx, int path, int perf_mode,
4426 int cal_index, char *params, int *size)
4427{
4428 int rc = 0;
4429 struct cal_block_data *cal_block = NULL;
4430 int app_type, acdb_id, port_idx, sample_rate;
4431
4432 if (this_adm.cal_data[cal_index] == NULL) {
4433 pr_debug("%s: cal_index %d not allocated!\n",
4434 __func__, cal_index);
4435 goto end;
4436 }
4437
4438 if (get_cal_path(path) != RX_DEVICE) {
4439 pr_debug("%s: Invalid path to store calibration %d\n",
4440 __func__, path);
4441 rc = -EINVAL;
4442 goto end;
4443 }
4444
4445 port_id = afe_convert_virtual_to_portid(port_id);
4446 port_idx = adm_validate_and_get_port_index(port_id);
4447 if (port_idx < 0) {
4448 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
4449 rc = -EINVAL;
4450 goto end;
4451 }
4452
4453 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4454 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4455 return -EINVAL;
4456 }
4457
4458 acdb_id = atomic_read(&this_adm.copp.acdb_id[port_idx][copp_idx]);
4459 app_type = atomic_read(&this_adm.copp.app_type[port_idx][copp_idx]);
4460 sample_rate = atomic_read(&this_adm.copp.rate[port_idx][copp_idx]);
4461
4462 mutex_lock(&this_adm.cal_data[cal_index]->lock);
4463 cal_block = adm_find_cal(cal_index, get_cal_path(path), app_type,
4464 acdb_id, sample_rate);
4465 if (cal_block == NULL)
4466 goto unlock;
4467
4468 if (cal_block->cal_data.size <= 0) {
4469 pr_debug("%s: No ADM cal send for port_id = 0x%x!\n",
4470 __func__, port_id);
4471 rc = -EINVAL;
4472 goto unlock;
4473 }
4474
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304475 if (cal_index == ADM_AUDPROC_CAL || cal_index == ADM_LSM_AUDPROC_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304476 if (cal_block->cal_data.size > AUD_PROC_BLOCK_SIZE) {
4477 pr_err("%s:audproc:invalid size exp/actual[%zd, %d]\n",
4478 __func__, cal_block->cal_data.size, *size);
4479 rc = -ENOMEM;
4480 goto unlock;
4481 }
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004482 } else if (cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
4483 if (cal_block->cal_data.size > AUD_PROC_PERSIST_BLOCK_SIZE) {
4484 pr_err("%s:persist invalid size exp/actual[%zd, %d]\n",
4485 __func__, cal_block->cal_data.size, *size);
4486 rc = -ENOMEM;
4487 goto unlock;
4488 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304489 } else if (cal_index == ADM_AUDVOL_CAL) {
4490 if (cal_block->cal_data.size > AUD_VOL_BLOCK_SIZE) {
4491 pr_err("%s:aud_vol:invalid size exp/actual[%zd, %d]\n",
4492 __func__, cal_block->cal_data.size, *size);
4493 rc = -ENOMEM;
4494 goto unlock;
4495 }
4496 } else {
4497 pr_debug("%s: Not valid calibration for dolby topolgy\n",
4498 __func__);
4499 rc = -EINVAL;
4500 goto unlock;
4501 }
4502 memcpy(params, cal_block->cal_data.kvaddr, cal_block->cal_data.size);
4503 *size = cal_block->cal_data.size;
4504
4505 pr_debug("%s:port_id %d, copp_idx %d, path %d",
4506 __func__, port_id, copp_idx, path);
4507 pr_debug("perf_mode %d, cal_type %d, size %d\n",
4508 perf_mode, cal_index, *size);
4509
4510unlock:
4511 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
4512end:
4513 return rc;
4514}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304515EXPORT_SYMBOL(adm_store_cal_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304516
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304517/**
4518 * adm_send_compressed_device_mute -
4519 * command to send mute for compressed device
4520 *
4521 * @port_id: Port ID number
4522 * @copp_idx: copp index assigned
4523 * @mute_on: flag to indicate mute or unmute
4524 *
4525 * Returns 0 on success or error on failure
4526 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304527int adm_send_compressed_device_mute(int port_id, int copp_idx, bool mute_on)
4528{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004529 u32 mute_param = mute_on ? 1 : 0;
4530 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304531 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304532
4533 pr_debug("%s port_id: 0x%x, copp_idx %d, mute_on: %d\n",
4534 __func__, port_id, copp_idx, mute_on);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304535
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004536 memset(&param_hdr, 0, sizeof(param_hdr));
4537 param_hdr.module_id = AUDPROC_MODULE_ID_COMPRESSED_MUTE;
4538 param_hdr.instance_id = INSTANCE_ID_0;
4539 param_hdr.param_id = AUDPROC_PARAM_ID_COMPRESSED_MUTE;
4540 param_hdr.param_size = sizeof(mute_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304541
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004542 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4543 (uint8_t *) &mute_param);
4544 if (ret)
4545 pr_err("%s: Failed to set mute, err %d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304546
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304547 return ret;
4548}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304549EXPORT_SYMBOL(adm_send_compressed_device_mute);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304550
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304551/**
4552 * adm_send_compressed_device_latency -
4553 * command to send latency for compressed device
4554 *
4555 * @port_id: Port ID number
4556 * @copp_idx: copp index assigned
4557 * @latency: latency value to pass
4558 *
4559 * Returns 0 on success or error on failure
4560 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304561int adm_send_compressed_device_latency(int port_id, int copp_idx, int latency)
4562{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004563 u32 latency_param;
4564 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304565 int ret = 0;
4566
4567 pr_debug("%s port_id: 0x%x, copp_idx %d latency: %d\n", __func__,
4568 port_id, copp_idx, latency);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004569
4570 if (latency < 0) {
4571 pr_err("%s: Invalid value for latency %d", __func__, latency);
4572 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304573 }
4574
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004575 memset(&param_hdr, 0, sizeof(param_hdr));
4576 param_hdr.module_id = AUDPROC_MODULE_ID_COMPRESSED_LATENCY;
4577 param_hdr.instance_id = INSTANCE_ID_0;
4578 param_hdr.param_id = AUDPROC_PARAM_ID_COMPRESSED_LATENCY;
4579 param_hdr.param_size = sizeof(latency_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304580
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004581 latency_param = latency;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304582
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004583 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4584 (uint8_t *) &latency_param);
4585 if (ret)
4586 pr_err("%s: Failed to set latency, err %d\n", __func__, ret);
4587
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304588 return ret;
4589}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304590EXPORT_SYMBOL(adm_send_compressed_device_latency);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304591
4592/**
4593 * adm_swap_speaker_channels
4594 *
4595 * Receives port_id, copp_idx, sample rate, spk_swap and
4596 * send MFC command to swap speaker channel.
4597 * Return zero on success. On failure returns nonzero.
4598 *
4599 * port_id - Passed value, port_id for which channels swap is wanted
4600 * copp_idx - Passed value, copp_idx for which channels swap is wanted
4601 * sample_rate - Passed value, sample rate used by app type config
4602 * spk_swap - Passed value, spk_swap for check if swap flag is set
4603 */
4604int adm_swap_speaker_channels(int port_id, int copp_idx,
4605 int sample_rate, bool spk_swap)
4606{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004607 struct audproc_mfc_param_media_fmt mfc_cfg;
4608 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304609 uint16_t num_channels;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004610 int port_idx = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304611 int ret = 0;
4612
4613 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
4614 __func__, port_id, copp_idx);
4615 port_id = q6audio_convert_virtual_to_portid(port_id);
4616 port_idx = adm_validate_and_get_port_index(port_id);
4617 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
4618 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004619 return -EINVAL;
4620 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4621 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
4622 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304623 }
4624
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004625 num_channels = atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304626 if (num_channels != 2) {
4627 pr_debug("%s: Invalid number of channels: %d\n",
4628 __func__, num_channels);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004629 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304630 }
4631
4632 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004633 memset(&param_hdr, 0, sizeof(param_hdr));
4634
4635 param_hdr.module_id = AUDPROC_MODULE_ID_MFC;
4636 param_hdr.instance_id = INSTANCE_ID_0;
4637 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
4638 param_hdr.param_size = sizeof(mfc_cfg);
4639
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304640 mfc_cfg.sampling_rate = sample_rate;
4641 mfc_cfg.bits_per_sample =
4642 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
4643 mfc_cfg.num_channels = num_channels;
4644
4645 /* Currently applying speaker swap for only 2 channel use case */
4646 if (spk_swap) {
4647 mfc_cfg.channel_type[0] =
4648 (uint16_t) PCM_CHANNEL_FR;
4649 mfc_cfg.channel_type[1] =
4650 (uint16_t) PCM_CHANNEL_FL;
4651 } else {
4652 mfc_cfg.channel_type[0] =
4653 (uint16_t) PCM_CHANNEL_FL;
4654 mfc_cfg.channel_type[1] =
4655 (uint16_t) PCM_CHANNEL_FR;
4656 }
4657
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004658 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4659 (u8 *) &mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304660 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004661 pr_err("%s: Failed to set swap speaker channels on port[0x%x] failed %d\n",
4662 __func__, port_id, ret);
4663 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304664 }
4665
4666 pr_debug("%s: mfc_cfg Set params returned success", __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004667 return 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304668}
4669EXPORT_SYMBOL(adm_swap_speaker_channels);
4670
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304671/**
4672 * adm_set_sound_focus -
4673 * Update sound focus info
4674 *
4675 * @port_id: Port ID number
4676 * @copp_idx: copp index assigned
4677 * @soundFocusData: sound focus data to pass
4678 *
4679 * Returns 0 on success or error on failure
4680 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304681int adm_set_sound_focus(int port_id, int copp_idx,
4682 struct sound_focus_param soundFocusData)
4683{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004684 struct adm_param_fluence_soundfocus_t soundfocus_params;
4685 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304686 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304687 int i;
4688
4689 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
4690 __func__, port_id, copp_idx);
4691
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004692 memset(&param_hdr, 0, sizeof(param_hdr));
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07004693 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004694 param_hdr.instance_id = INSTANCE_ID_0;
4695 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
4696 param_hdr.param_size = sizeof(soundfocus_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304697
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004698 memset(&(soundfocus_params), 0xFF, sizeof(soundfocus_params));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304699 for (i = 0; i < MAX_SECTORS; i++) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004700 soundfocus_params.start_angles[i] =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304701 soundFocusData.start_angle[i];
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004702 soundfocus_params.enables[i] = soundFocusData.enable[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304703 pr_debug("%s: start_angle[%d] = %d\n",
4704 __func__, i, soundFocusData.start_angle[i]);
4705 pr_debug("%s: enable[%d] = %d\n",
4706 __func__, i, soundFocusData.enable[i]);
4707 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004708 soundfocus_params.gain_step = soundFocusData.gain_step;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304709 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData.gain_step);
4710
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004711 soundfocus_params.reserved = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304712
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004713 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4714 (uint8_t *) &soundfocus_params);
4715 if (ret)
4716 pr_err("%s: Failed to set sound focus params, err %d\n",
4717 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304718
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304719 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
4720
4721 return ret;
4722}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304723EXPORT_SYMBOL(adm_set_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304724
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304725/**
4726 * adm_get_sound_focus -
4727 * Retrieve sound focus info
4728 *
4729 * @port_id: Port ID number
4730 * @copp_idx: copp index assigned
4731 * @soundFocusData: pointer for sound focus data to be updated with
4732 *
4733 * Returns 0 on success or error on failure
4734 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304735int adm_get_sound_focus(int port_id, int copp_idx,
4736 struct sound_focus_param *soundFocusData)
4737{
4738 int ret = 0, i;
4739 char *params_value;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004740 uint32_t max_param_size = 0;
4741 struct adm_param_fluence_soundfocus_t *soundfocus_params = NULL;
4742 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304743
4744 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
4745 __func__, port_id, copp_idx);
4746
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004747 max_param_size = sizeof(struct adm_param_fluence_soundfocus_t) +
4748 sizeof(union param_hdrs);
4749 params_value = kzalloc(max_param_size, GFP_KERNEL);
4750 if (!params_value)
4751 return -ENOMEM;
4752
4753 memset(&param_hdr, 0, sizeof(param_hdr));
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07004754 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004755 param_hdr.instance_id = INSTANCE_ID_0;
4756 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
4757 param_hdr.param_size = max_param_size;
4758 ret = adm_get_pp_params(port_id, copp_idx,
4759 ADM_CLIENT_ID_SOURCE_TRACKING, NULL, &param_hdr,
4760 params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304761 if (ret) {
4762 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304763 ret = -EINVAL;
4764 goto done;
4765 }
4766
4767 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
4768 pr_err("%s - get params returned error [%s]\n",
4769 __func__, adsp_err_get_err_str(
4770 this_adm.sourceTrackingData.apr_cmd_status));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304771 ret = adsp_err_get_lnx_err_code(
4772 this_adm.sourceTrackingData.apr_cmd_status);
4773 goto done;
4774 }
4775
4776 soundfocus_params = (struct adm_param_fluence_soundfocus_t *)
4777 params_value;
4778 for (i = 0; i < MAX_SECTORS; i++) {
4779 soundFocusData->start_angle[i] =
4780 soundfocus_params->start_angles[i];
4781 soundFocusData->enable[i] = soundfocus_params->enables[i];
4782 pr_debug("%s: start_angle[%d] = %d\n",
4783 __func__, i, soundFocusData->start_angle[i]);
4784 pr_debug("%s: enable[%d] = %d\n",
4785 __func__, i, soundFocusData->enable[i]);
4786 }
4787 soundFocusData->gain_step = soundfocus_params->gain_step;
4788 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData->gain_step);
4789
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304790done:
4791 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
4792
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004793 kfree(params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304794 return ret;
4795}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304796EXPORT_SYMBOL(adm_get_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304797
4798static int adm_source_tracking_alloc_map_memory(void)
4799{
4800 int ret;
4801
4802 pr_debug("%s: Enter\n", __func__);
4803
Banajit Goswami08bb7362017-11-03 22:48:23 -07004804 ret = msm_audio_ion_alloc(&this_adm.sourceTrackingData.dma_buf,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304805 AUD_PROC_BLOCK_SIZE,
4806 &this_adm.sourceTrackingData.memmap.paddr,
4807 &this_adm.sourceTrackingData.memmap.size,
4808 &this_adm.sourceTrackingData.memmap.kvaddr);
4809 if (ret) {
4810 pr_err("%s: failed to allocate memory\n", __func__);
4811
4812 ret = -EINVAL;
4813 goto done;
4814 }
4815
4816 atomic_set(&this_adm.mem_map_index, ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
4817 ret = adm_memory_map_regions(&this_adm.sourceTrackingData.memmap.paddr,
4818 0,
4819 (uint32_t *)&this_adm.sourceTrackingData.memmap.size,
4820 1);
4821 if (ret < 0) {
4822 pr_err("%s: failed to map memory, paddr = 0x%pK, size = %d\n",
4823 __func__,
4824 (void *)this_adm.sourceTrackingData.memmap.paddr,
4825 (uint32_t)this_adm.sourceTrackingData.memmap.size);
4826
Banajit Goswami08bb7362017-11-03 22:48:23 -07004827 msm_audio_ion_free(this_adm.sourceTrackingData.dma_buf);
4828 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304829 this_adm.sourceTrackingData.memmap.size = 0;
4830 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
4831 this_adm.sourceTrackingData.memmap.paddr = 0;
4832 this_adm.sourceTrackingData.apr_cmd_status = -1;
4833 atomic_set(&this_adm.mem_map_handles
4834 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
4835
4836 ret = -EINVAL;
4837 goto done;
4838 }
4839 ret = 0;
4840 pr_debug("%s: paddr = 0x%pK, size = %d, mem_map_handle = 0x%x\n",
4841 __func__, (void *)this_adm.sourceTrackingData.memmap.paddr,
4842 (uint32_t)this_adm.sourceTrackingData.memmap.size,
4843 atomic_read(&this_adm.mem_map_handles
4844 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING]));
4845
4846done:
4847 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
4848
4849 return ret;
4850}
4851
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304852/**
4853 * adm_get_source_tracking -
4854 * Retrieve source tracking info
4855 *
4856 * @port_id: Port ID number
4857 * @copp_idx: copp index assigned
4858 * @sourceTrackingData: pointer for source track data to be updated with
4859 *
4860 * Returns 0 on success or error on failure
4861 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304862int adm_get_source_tracking(int port_id, int copp_idx,
4863 struct source_tracking_param *sourceTrackingData)
4864{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004865 struct adm_param_fluence_sourcetracking_t *source_tracking_params =
4866 NULL;
4867 struct mem_mapping_hdr mem_hdr;
4868 struct param_hdr_v3 param_hdr;
4869 int i = 0;
4870 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304871
4872 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
4873 __func__, port_id, copp_idx);
4874
4875 if (!this_adm.sourceTrackingData.memmap.paddr) {
4876 /* Allocate and map shared memory for out of band usage */
4877 ret = adm_source_tracking_alloc_map_memory();
4878 if (ret != 0) {
4879 ret = -EINVAL;
4880 goto done;
4881 }
4882 }
4883
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004884 memset(&mem_hdr, 0, sizeof(mem_hdr));
4885 memset(&param_hdr, 0, sizeof(param_hdr));
4886 mem_hdr.data_payload_addr_lsw =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304887 lower_32_bits(this_adm.sourceTrackingData.memmap.paddr);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004888 mem_hdr.data_payload_addr_msw = msm_audio_populate_upper_32_bits(
4889 this_adm.sourceTrackingData.memmap.paddr);
4890 mem_hdr.mem_map_handle = atomic_read(
4891 &this_adm.mem_map_handles[ADM_MEM_MAP_INDEX_SOURCE_TRACKING]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304892
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07004893 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004894 param_hdr.instance_id = INSTANCE_ID_0;
4895 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOURCETRACKING;
4896 /*
4897 * This size should be the max size of the calibration data + header.
4898 * Use the union size to ensure max size is used.
4899 */
4900 param_hdr.param_size =
4901 sizeof(struct adm_param_fluence_sourcetracking_t) +
4902 sizeof(union param_hdrs);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304903
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004904 /*
4905 * Retrieving parameters out of band, so no need to provide a buffer for
4906 * the returned parameter data as it will be at the memory location
4907 * provided.
4908 */
4909 ret = adm_get_pp_params(port_id, copp_idx,
4910 ADM_CLIENT_ID_SOURCE_TRACKING, &mem_hdr,
4911 &param_hdr, NULL);
4912 if (ret) {
4913 pr_err("%s: Failed to get params, error %d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304914 goto done;
4915 }
4916
4917 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
4918 pr_err("%s - get params returned error [%s]\n",
4919 __func__, adsp_err_get_err_str(
4920 this_adm.sourceTrackingData.apr_cmd_status));
4921
4922 ret = adsp_err_get_lnx_err_code(
4923 this_adm.sourceTrackingData.apr_cmd_status);
4924 goto done;
4925 }
4926
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004927 /* How do we know what the param data was retrieved with for hdr size */
4928 source_tracking_params =
4929 (struct adm_param_fluence_sourcetracking_t
4930 *) (this_adm.sourceTrackingData.memmap.kvaddr +
4931 sizeof(struct param_hdr_v1));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304932 for (i = 0; i < MAX_SECTORS; i++) {
4933 sourceTrackingData->vad[i] = source_tracking_params->vad[i];
4934 pr_debug("%s: vad[%d] = %d\n",
4935 __func__, i, sourceTrackingData->vad[i]);
4936 }
4937 sourceTrackingData->doa_speech = source_tracking_params->doa_speech;
4938 pr_debug("%s: doa_speech = %d\n",
4939 __func__, sourceTrackingData->doa_speech);
4940
4941 for (i = 0; i < MAX_NOISE_SOURCE_INDICATORS; i++) {
4942 sourceTrackingData->doa_noise[i] =
4943 source_tracking_params->doa_noise[i];
4944 pr_debug("%s: doa_noise[%d] = %d\n",
4945 __func__, i, sourceTrackingData->doa_noise[i]);
4946 }
4947 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
4948 sourceTrackingData->polar_activity[i] =
4949 source_tracking_params->polar_activity[i];
4950 pr_debug("%s: polar_activity[%d] = %d\n",
4951 __func__, i, sourceTrackingData->polar_activity[i]);
4952 }
4953
4954 ret = 0;
4955
4956done:
4957 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
4958
4959 return ret;
4960}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304961EXPORT_SYMBOL(adm_get_source_tracking);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304962
Chaithanya Krishna Bacharaju8c6a1842018-11-16 15:02:39 +05304963/**
4964 * adm_get_doa_tracking_mon -
4965 * Retrieve doa tracking monitor info
4966 *
4967 * @port_id: Port ID number
4968 * @copp_idx: copp index assigned
4969 * @doa_tracking_data: pointer for doa data to be updated with
4970 *
4971 * Returns 0 on success or error on failure
4972 */
4973int adm_get_doa_tracking_mon(int port_id, int copp_idx,
4974 struct doa_tracking_mon_param *doa_tracking_data)
4975{
4976 int ret = 0, i;
4977 char *params_value;
4978 uint32_t max_param_size = 0;
4979 struct adm_param_doa_tracking_mon_t *doa_tracking_params = NULL;
4980 struct param_hdr_v3 param_hdr;
4981
4982 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
4983 __func__, port_id, copp_idx);
4984
4985 if (doa_tracking_data == NULL) {
4986 pr_err("%s: Received NULL pointer for doa tracking data\n",
4987 __func__);
4988 return -EINVAL;
4989 }
4990
4991 max_param_size = sizeof(struct adm_param_doa_tracking_mon_t) +
4992 sizeof(union param_hdrs);
4993 params_value = kzalloc(max_param_size, GFP_KERNEL);
4994 if (!params_value)
4995 return -ENOMEM;
4996
4997 memset(&param_hdr, 0, sizeof(param_hdr));
4998 param_hdr.module_id = AUDPROC_MODULE_ID_FFECNS;
4999 param_hdr.instance_id = INSTANCE_ID_0;
5000 param_hdr.param_id = AUDPROC_PARAM_ID_FFV_DOA_TRACKING_MONITOR;
5001 param_hdr.param_size = max_param_size;
5002 ret = adm_get_pp_params(port_id, copp_idx,
5003 ADM_CLIENT_ID_DEFAULT, NULL, &param_hdr,
5004 params_value);
5005 if (ret) {
5006 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
5007 goto done;
5008 }
5009
5010 doa_tracking_params =
5011 (struct adm_param_doa_tracking_mon_t *)params_value;
5012 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
5013 doa_tracking_data->target_angle_L16[i] =
5014 doa_tracking_params->target_angle_L16[i];
5015 pr_debug("%s: target angle[%d] = %d\n",
5016 __func__, i, doa_tracking_data->target_angle_L16[i]);
5017 }
5018
5019 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
5020 doa_tracking_data->interf_angle_L16[i] =
5021 doa_tracking_params->interf_angle_L16[i];
5022 pr_debug("%s: interference angle[%d] = %d\n",
5023 __func__, i, doa_tracking_data->interf_angle_L16[i]);
5024 }
5025
5026 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
5027 doa_tracking_data->polar_activity[i] =
5028 doa_tracking_params->polar_activity[i];
5029 }
5030
5031done:
5032 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5033 kfree(params_value);
5034 return ret;
5035}
5036EXPORT_SYMBOL(adm_get_doa_tracking_mon);
5037
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305038int __init adm_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305039{
5040 int i = 0, j;
5041
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305042 this_adm.ec_ref_rx = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305043 init_waitqueue_head(&this_adm.matrix_map_wait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305044 init_waitqueue_head(&this_adm.adm_wait);
5045
5046 for (i = 0; i < AFE_MAX_PORTS; i++) {
5047 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
5048 atomic_set(&this_adm.copp.id[i][j], RESET_COPP_ID);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305049 init_waitqueue_head(&this_adm.copp.wait[i][j]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305050 init_waitqueue_head(
5051 &this_adm.copp.adm_delay_wait[i][j]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305052 }
5053 }
5054
5055 if (adm_init_cal_data())
5056 pr_err("%s: could not init cal data!\n", __func__);
5057
Banajit Goswami08bb7362017-11-03 22:48:23 -07005058 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305059 this_adm.sourceTrackingData.memmap.size = 0;
5060 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5061 this_adm.sourceTrackingData.memmap.paddr = 0;
5062 this_adm.sourceTrackingData.apr_cmd_status = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305063
5064 return 0;
5065}
5066
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05305067void adm_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305068{
Laxminath Kasam30ad7512017-11-28 12:40:22 +05305069 if (this_adm.apr)
5070 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305071 adm_delete_cal_data();
5072}