blob: 708cc0fdbca3fc036123623d4268ad22d287b67a [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/*
Ramu Gottipatife399492020-01-09 10:57:33 +05303 * Copyright (c) 2012-2020, 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
Chaithanya Krishna Bacharaju6bd40882019-07-16 11:07:14 +053045#define SESSION_TYPE_RX 0
46
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053047/* ENUM for adm_status */
48enum adm_cal_status {
49 ADM_STATUS_CALIBRATION_REQUIRED = 0,
50 ADM_STATUS_MAX,
51};
52
53struct adm_copp {
54
55 atomic_t id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
56 atomic_t cnt[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
57 atomic_t topology[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
58 atomic_t mode[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
59 atomic_t stat[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
60 atomic_t rate[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
61 atomic_t bit_width[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
62 atomic_t channels[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
63 atomic_t app_type[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
64 atomic_t acdb_id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
Surendar Karkae7507512018-07-20 15:46:54 +053065 atomic_t session_type[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053066 wait_queue_head_t wait[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
67 wait_queue_head_t adm_delay_wait[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
68 atomic_t adm_delay_stat[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
69 uint32_t adm_delay[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
70 unsigned long adm_status[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
71};
72
73struct source_tracking_data {
Banajit Goswami08bb7362017-11-03 22:48:23 -070074 struct dma_buf *dma_buf;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053075 struct param_outband memmap;
76 int apr_cmd_status;
77};
78
79struct adm_ctl {
80 void *apr;
81
82 struct adm_copp copp;
83
84 atomic_t matrix_map_stat;
85 wait_queue_head_t matrix_map_wait;
86
87 atomic_t adm_stat;
88 wait_queue_head_t adm_wait;
89
90 struct cal_type_data *cal_data[ADM_MAX_CAL_TYPES];
91
92 atomic_t mem_map_handles[ADM_MEM_MAP_INDEX_MAX];
93 atomic_t mem_map_index;
94
95 struct param_outband outband_memmap;
96 struct source_tracking_data sourceTrackingData;
97
Soumya Managoli97f90ea2020-04-28 09:16:55 +053098 struct mutex adm_apr_lock;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053099 int set_custom_topology;
100 int ec_ref_rx;
101 int num_ec_ref_rx_chans;
102 int ec_ref_rx_bit_width;
103 int ec_ref_rx_sampling_rate;
Dhananjay Kumar43034392019-01-16 21:57:58 +0530104 int num_ec_ref_rx_chans_downmixed;
105 uint16_t ec_ref_chmixer_weights[PCM_FORMAT_MAX_NUM_CHANNEL_V8]
106 [PCM_FORMAT_MAX_NUM_CHANNEL_V8];
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +0800107 int ffecns_port_id;
Dieter Luecking50c55352018-09-28 14:29:17 +0200108 int native_mode;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530109};
110
111static struct adm_ctl this_adm;
112
113struct adm_multi_ch_map {
114 bool set_channel_map;
Dieter Luecking50c55352018-09-28 14:29:17 +0200115 char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530116};
117
118#define ADM_MCH_MAP_IDX_PLAYBACK 0
119#define ADM_MCH_MAP_IDX_REC 1
120static struct adm_multi_ch_map multi_ch_maps[2] = {
Dieter Luecking50c55352018-09-28 14:29:17 +0200121 { 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 },
127 { false,
128 {0, 0, 0, 0, 0, 0, 0, 0,
129 0, 0, 0, 0, 0, 0, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 0, 0, 0, 0, 0, 0}
132 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530133};
134
Rohit kumar2054b692019-02-01 18:01:12 +0530135static struct adm_multi_ch_map port_channel_map[AFE_MAX_PORTS];
136
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530137static int adm_get_parameters[MAX_COPPS_PER_PORT * ADM_GET_PARAMETER_LENGTH];
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800138static int adm_module_topo_list[MAX_COPPS_PER_PORT *
139 ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH];
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530140static struct mutex dts_srs_lock;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530141
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530142void msm_dts_srs_acquire_lock(void)
143{
144 mutex_lock(&dts_srs_lock);
145}
146
147void msm_dts_srs_release_lock(void)
148{
149 mutex_unlock(&dts_srs_lock);
150}
151
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530152static int adm_arrange_mch_map_v8(
153 struct adm_device_endpoint_payload *ep_payload,
154 int path,
Rohit kumar2054b692019-02-01 18:01:12 +0530155 int channel_mode,
156 int port_idx);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530157
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530158/**
159 * adm_validate_and_get_port_index -
160 * validate given port id
161 *
162 * @port_id: Port ID number
163 *
164 * Returns valid index on success or error on failure
165 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530166int adm_validate_and_get_port_index(int port_id)
167{
168 int index;
169 int ret;
170
171 ret = q6audio_validate_port(port_id);
172 if (ret < 0) {
173 pr_err("%s: port validation failed id 0x%x ret %d\n",
174 __func__, port_id, ret);
175 return -EINVAL;
176 }
177
178 index = afe_get_port_index(port_id);
179 if (index < 0 || index >= AFE_MAX_PORTS) {
180 pr_err("%s: Invalid port idx %d port_id 0x%x\n",
181 __func__, index,
182 port_id);
183 return -EINVAL;
184 }
185 pr_debug("%s: port_idx- %d\n", __func__, index);
186 return index;
187}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530188EXPORT_SYMBOL(adm_validate_and_get_port_index);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530189
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530190/**
191 * adm_get_default_copp_idx -
192 * retrieve default copp_idx for given port
193 *
194 * @port_id: Port ID number
195 *
196 * Returns valid value on success or error on failure
197 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530198int adm_get_default_copp_idx(int port_id)
199{
200 int port_idx = adm_validate_and_get_port_index(port_id), idx;
201
202 if (port_idx < 0) {
203 pr_err("%s: Invalid port id: 0x%x", __func__, port_id);
204 return -EINVAL;
205 }
206 pr_debug("%s: port_idx:%d\n", __func__, port_idx);
207 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
208 if (atomic_read(&this_adm.copp.id[port_idx][idx]) !=
209 RESET_COPP_ID)
210 return idx;
211 }
212 return -EINVAL;
213}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530214EXPORT_SYMBOL(adm_get_default_copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530215
216int adm_get_topology_for_port_from_copp_id(int port_id, int copp_id)
217{
218 int port_idx = adm_validate_and_get_port_index(port_id), idx;
219
220 if (port_idx < 0) {
221 pr_err("%s: Invalid port id: 0x%x", __func__, port_id);
222 return 0;
223 }
224 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
225 if (atomic_read(&this_adm.copp.id[port_idx][idx]) == copp_id)
226 return atomic_read(&this_adm.copp.topology[port_idx]
227 [idx]);
228 pr_err("%s: Invalid copp_id %d port_id 0x%x\n",
229 __func__, copp_id, port_id);
230 return 0;
231}
232
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530233/**
234 * adm_get_topology_for_port_copp_idx -
235 * retrieve topology of given port/copp_idx
236 *
237 * @port_id: Port ID number
238 * @copp_idx: copp index of ADM copp
239 *
240 * Returns valid value on success or 0 on failure
241 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530242int adm_get_topology_for_port_copp_idx(int port_id, int copp_idx)
243{
244 int port_idx = adm_validate_and_get_port_index(port_id);
245
246 if (port_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
247 pr_err("%s: Invalid port: 0x%x copp id: 0x%x",
248 __func__, port_id, copp_idx);
249 return 0;
250 }
251 return atomic_read(&this_adm.copp.topology[port_idx][copp_idx]);
252}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530253EXPORT_SYMBOL(adm_get_topology_for_port_copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530254
255int adm_get_indexes_from_copp_id(int copp_id, int *copp_idx, int *port_idx)
256{
257 int p_idx, c_idx;
258
259 for (p_idx = 0; p_idx < AFE_MAX_PORTS; p_idx++) {
260 for (c_idx = 0; c_idx < MAX_COPPS_PER_PORT; c_idx++) {
261 if (atomic_read(&this_adm.copp.id[p_idx][c_idx])
262 == copp_id) {
263 if (copp_idx != NULL)
264 *copp_idx = c_idx;
265 if (port_idx != NULL)
266 *port_idx = p_idx;
267 return 0;
268 }
269 }
270 }
271 return -EINVAL;
272}
273
274static int adm_get_copp_id(int port_idx, int copp_idx)
275{
276 pr_debug("%s: port_idx:%d copp_idx:%d\n", __func__, port_idx, copp_idx);
277
278 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
279 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
280 return -EINVAL;
281 }
282 return atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
283}
284
285static int adm_get_idx_if_copp_exists(int port_idx, int topology, int mode,
Surendar Karkae7507512018-07-20 15:46:54 +0530286 int rate, int bit_width, int app_type,
287 int session_type)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530288{
289 int idx;
290
291 pr_debug("%s: port_idx-%d, topology-0x%x, mode-%d, rate-%d, bit_width-%d\n",
292 __func__, port_idx, topology, mode, rate, bit_width);
293
294 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
295 if ((topology ==
296 atomic_read(&this_adm.copp.topology[port_idx][idx])) &&
297 (mode == atomic_read(&this_adm.copp.mode[port_idx][idx])) &&
298 (rate == atomic_read(&this_adm.copp.rate[port_idx][idx])) &&
299 (bit_width ==
300 atomic_read(&this_adm.copp.bit_width[port_idx][idx])) &&
Surendar Karkae7507512018-07-20 15:46:54 +0530301 (session_type ==
302 atomic_read(
303 &this_adm.copp.session_type[port_idx][idx])) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530304 (app_type ==
305 atomic_read(&this_adm.copp.app_type[port_idx][idx])))
306 return idx;
307 return -EINVAL;
308}
309
310static int adm_get_next_available_copp(int port_idx)
311{
312 int idx;
313
314 pr_debug("%s:\n", __func__);
315 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
316 pr_debug("%s: copp_id:0x%x port_idx:%d idx:%d\n", __func__,
317 atomic_read(&this_adm.copp.id[port_idx][idx]),
318 port_idx, idx);
319 if (atomic_read(&this_adm.copp.id[port_idx][idx]) ==
320 RESET_COPP_ID)
321 break;
322 }
323 return idx;
324}
325
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530326/**
327 * srs_trumedia_open -
328 * command to set SRS trumedia open
329 *
330 * @port_id: Port ID number
331 * @copp_idx: copp index of ADM copp
332 * @srs_tech_id: SRS tech index
333 * @srs_params: params pointer
334 *
335 * Returns 0 on success or error on failure
336 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530337int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id,
338 void *srs_params)
339{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800340 struct param_hdr_v3 param_hdr;
341 struct mem_mapping_hdr mem_hdr;
342 u32 total_param_size = 0;
343 bool outband = false;
344 int port_idx;
345 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530346
347 pr_debug("SRS - %s", __func__);
348
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800349 memset(&param_hdr, 0, sizeof(param_hdr));
350 memset(&mem_hdr, 0, sizeof(mem_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530351 port_id = afe_convert_virtual_to_portid(port_id);
352 port_idx = adm_validate_and_get_port_index(port_id);
353 if (port_idx < 0) {
354 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
355 return -EINVAL;
356 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800357
358 param_hdr.module_id = SRS_TRUMEDIA_MODULE_ID;
359 param_hdr.instance_id = INSTANCE_ID_0;
360
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530361 switch (srs_tech_id) {
362 case SRS_ID_GLOBAL: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800363 param_hdr.param_id = SRS_TRUMEDIA_PARAMS;
364 param_hdr.param_size =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530365 sizeof(struct srs_trumedia_params_GLOBAL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530366 break;
367 }
368 case SRS_ID_WOWHD: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800369 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_WOWHD;
370 param_hdr.param_size = sizeof(struct srs_trumedia_params_WOWHD);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530371 break;
372 }
373 case SRS_ID_CSHP: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800374 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_CSHP;
375 param_hdr.param_size = sizeof(struct srs_trumedia_params_CSHP);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530376 break;
377 }
378 case SRS_ID_HPF: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800379 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_HPF;
380 param_hdr.param_size = sizeof(struct srs_trumedia_params_HPF);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530381 break;
382 }
383 case SRS_ID_AEQ: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800384 u8 *update_params_ptr = (u8 *) this_adm.outband_memmap.kvaddr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530385
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800386 outband = true;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530387
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530388 if (update_params_ptr == NULL) {
389 pr_err("ADM_SRS_TRUMEDIA - %s: null memmap for AEQ params\n",
390 __func__);
391 ret = -EINVAL;
392 goto fail_cmd;
393 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530394
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800395 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_AEQ;
396 param_hdr.param_size = sizeof(struct srs_trumedia_params_AEQ);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530397
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800398 ret = q6common_pack_pp_params(update_params_ptr, &param_hdr,
399 srs_params, &total_param_size);
400 if (ret) {
401 pr_err("%s: Failed to pack param header and data, error %d\n",
402 __func__, ret);
403 goto fail_cmd;
404 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530405 break;
406 }
407 case SRS_ID_HL: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800408 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_HL;
409 param_hdr.param_size = sizeof(struct srs_trumedia_params_HL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530410 break;
411 }
412 case SRS_ID_GEQ: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800413 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_GEQ;
414 param_hdr.param_size = sizeof(struct srs_trumedia_params_GEQ);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530415 break;
416 }
417 default:
418 goto fail_cmd;
419 }
420
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530421 if (outband && this_adm.outband_memmap.paddr) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800422 mem_hdr.data_payload_addr_lsw =
423 lower_32_bits(this_adm.outband_memmap.paddr);
424 mem_hdr.data_payload_addr_msw =
425 msm_audio_populate_upper_32_bits(
426 this_adm.outband_memmap.paddr);
427 mem_hdr.mem_map_handle = atomic_read(
428 &this_adm.mem_map_handles[ADM_SRS_TRUMEDIA]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530429
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800430 ret = adm_set_pp_params(port_id, copp_idx, &mem_hdr, NULL,
431 total_param_size);
432 } else {
433 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx,
434 param_hdr,
435 (u8 *) srs_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530436 }
437
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800438 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530439 pr_err("SRS - %s: ADM enable for port %d failed\n", __func__,
440 port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530441
442fail_cmd:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530443 return ret;
444}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530445EXPORT_SYMBOL(srs_trumedia_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530446
447static int adm_populate_channel_weight(u16 *ptr,
448 struct msm_pcm_channel_mixer *ch_mixer,
449 int channel_index)
450{
451 u16 i, j, start_index = 0;
452
453 if (channel_index > ch_mixer->output_channel) {
454 pr_err("%s: channel index %d is larger than output_channel %d\n",
455 __func__, channel_index, ch_mixer->output_channel);
456 return -EINVAL;
457 }
458
459 for (i = 0; i < ch_mixer->output_channel; i++) {
460 pr_debug("%s: weight for output %d:", __func__, i);
461 for (j = 0; j < ADM_MAX_CHANNELS; j++)
462 pr_debug(" %d",
463 ch_mixer->channel_weight[i][j]);
464 pr_debug("\n");
465 }
466
467 for (i = 0; i < channel_index; ++i)
468 start_index += ch_mixer->input_channels[i];
469
470 for (i = 0; i < ch_mixer->output_channel; ++i) {
471 for (j = start_index;
472 j < start_index +
473 ch_mixer->input_channels[channel_index]; j++) {
474 *ptr = ch_mixer->channel_weight[i][j];
475 pr_debug("%s: ptr[%d][%d] = %d\n",
476 __func__, i, j, *ptr);
477 ptr++;
478 }
479 }
480
481 return 0;
482}
483
484/*
485 * adm_programable_channel_mixer
486 *
487 * Receives port_id, copp_idx, session_id, session_type, ch_mixer
488 * and channel_index to send ADM command to mix COPP data.
489 *
490 * port_id - Passed value, port_id for which backend is wanted
491 * copp_idx - Passed value, copp_idx for which COPP is wanted
492 * session_id - Passed value, session_id for which session is needed
493 * session_type - Passed value, session_type for RX or TX
494 * ch_mixer - Passed value, ch_mixer for which channel mixer config is needed
495 * channel_index - Passed value, channel_index for which channel is needed
496 */
497int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
498 int session_type,
499 struct msm_pcm_channel_mixer *ch_mixer,
500 int channel_index)
501{
502 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700503 struct param_hdr_v1 data_v5;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530504 int ret = 0, port_idx, sz = 0, param_size = 0;
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530505 struct adm_device_endpoint_payload ep_params = {0, 0, 0, {0}};
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530506 u16 *adm_pspd_params;
507 u16 *ptr;
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530508 int index = 0, i = 0, path_type = ADM_PATH_PLAYBACK;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530509
510 pr_debug("%s: port_id = %d\n", __func__, port_id);
511 port_id = afe_convert_virtual_to_portid(port_id);
512 port_idx = adm_validate_and_get_port_index(port_id);
513 if (port_idx < 0) {
514 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
515 return -EINVAL;
516 }
Ramu Gottipatife399492020-01-09 10:57:33 +0530517
518 /*
519 * check if PSPD is already configured
520 * if it is configured already, return 0 without applying PSPD.
521 */
522 if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) > 1) {
523 pr_debug("%s: copp.cnt:%#x\n", __func__,
524 atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]));
525 return 0;
526 }
527
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530528 /*
529 * First 8 bytes are 4 bytes as rule number, 2 bytes as output
530 * channel and 2 bytes as input channel.
531 * 2 * ch_mixer->output_channel means output channel mapping.
532 * 2 * ch_mixer->input_channels[channel_index]) means input
533 * channel mapping.
534 * 2 * ch_mixer->input_channels[channel_index] *
535 * ch_mixer->output_channel) means the channel mixer weighting
536 * coefficients.
537 * param_size needs to be a multiple of 4 bytes.
538 */
539
540 param_size = 2 * (4 + ch_mixer->output_channel +
541 ch_mixer->input_channels[channel_index] +
542 ch_mixer->input_channels[channel_index] *
543 ch_mixer->output_channel);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530544 param_size = roundup(param_size, 4);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530545
546 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800547 sizeof(struct default_chmixer_param_id_coeff) +
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700548 sizeof(struct param_hdr_v1) + param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530549 pr_debug("%s: sz = %d\n", __func__, sz);
550 adm_params = kzalloc(sz, GFP_KERNEL);
551 if (!adm_params)
552 return -ENOMEM;
553
554 adm_params->payload_addr_lsw = 0;
555 adm_params->payload_addr_msw = 0;
556 adm_params->mem_map_handle = 0;
557 adm_params->direction = session_type;
558 adm_params->sessionid = session_id;
559 pr_debug("%s: copp_id = %d, session id %d\n", __func__,
560 atomic_read(&this_adm.copp.id[port_idx][copp_idx]),
561 session_id);
562 adm_params->deviceid = atomic_read(
563 &this_adm.copp.id[port_idx][copp_idx]);
564 adm_params->reserved = 0;
565
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800566 /*
567 * This module is internal to ADSP and cannot be configured with
568 * an instance id
569 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530570 data_v5.module_id = MTMX_MODULE_ID_DEFAULT_CHMIXER;
571 data_v5.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
572 data_v5.reserved = 0;
573 data_v5.param_size = param_size;
574 adm_params->payload_size =
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800575 sizeof(struct default_chmixer_param_id_coeff) +
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700576 sizeof(struct param_hdr_v1) + data_v5.param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530577 adm_pspd_params = (u16 *)((u8 *)adm_params +
578 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5));
579 memcpy(adm_pspd_params, &data_v5, sizeof(data_v5));
580
581 adm_pspd_params = (u16 *)((u8 *)adm_params +
582 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)
583 + sizeof(data_v5));
584
585 adm_pspd_params[0] = ch_mixer->rule;
586 adm_pspd_params[2] = ch_mixer->output_channel;
587 adm_pspd_params[3] = ch_mixer->input_channels[channel_index];
588 index = 4;
589
Chaithanya Krishna Bacharaju6bd40882019-07-16 11:07:14 +0530590 path_type = (session_type == SESSION_TYPE_RX) ?
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530591 ADM_PATH_PLAYBACK : ADM_PATH_LIVE_REC;
592
593 if (ch_mixer->override_out_ch_map) {
594 memcpy(&adm_pspd_params[index], &ch_mixer->out_ch_map,
595 ch_mixer->output_channel * sizeof(uint16_t));
596 index += ch_mixer->output_channel;
597 } else {
598 ep_params.dev_num_channel = ch_mixer->output_channel;
Rohit kumar2054b692019-02-01 18:01:12 +0530599 adm_arrange_mch_map_v8(&ep_params, path_type,
600 ep_params.dev_num_channel, port_idx);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530601 for (i = 0; i < ch_mixer->output_channel; i++)
602 adm_pspd_params[index++] = ep_params.dev_channel_mapping[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530603 }
604
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530605 if (ch_mixer->override_in_ch_map) {
606 memcpy(&adm_pspd_params[index], &ch_mixer->in_ch_map,
607 ch_mixer->input_channel * sizeof(uint16_t));
608 index += ch_mixer->input_channel;
609 } else {
610 ep_params.dev_num_channel = ch_mixer->input_channels[channel_index];
Rohit kumar2054b692019-02-01 18:01:12 +0530611 adm_arrange_mch_map_v8(&ep_params, path_type,
612 ep_params.dev_num_channel, port_idx);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530613 for (i = 0; i < ch_mixer->input_channels[channel_index]; i++)
614 adm_pspd_params[index++] = ep_params.dev_channel_mapping[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530615 }
616
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530617 ret = adm_populate_channel_weight(&adm_pspd_params[index],
618 ch_mixer, channel_index);
Meng Wangd9fa69c2018-01-23 12:42:52 +0800619 if (ret) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530620 pr_err("%s: fail to get channel weight with error %d\n",
621 __func__, ret);
622 goto fail_cmd;
623 }
624
625 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
626 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
627 adm_params->hdr.src_svc = APR_SVC_ADM;
628 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
629 adm_params->hdr.src_port = port_id;
630 adm_params->hdr.dest_svc = APR_SVC_ADM;
631 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
632 adm_params->hdr.dest_port =
633 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
634 adm_params->hdr.token = port_idx << 16 | copp_idx;
635 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
636 adm_params->hdr.pkt_size = sz;
637 adm_params->payload_addr_lsw = 0;
638 adm_params->payload_addr_msw = 0;
639 adm_params->mem_map_handle = 0;
640 adm_params->reserved = 0;
641
642 ptr = (u16 *)adm_params;
643 for (index = 0; index < (sz / 2); index++)
644 pr_debug("%s: adm_params[%d] = 0x%x\n",
645 __func__, index, (unsigned int)ptr[index]);
646
647 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], 0);
648 ret = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
649 if (ret < 0) {
650 pr_err("%s: Set params failed port %d rc %d\n", __func__,
651 port_id, ret);
652 ret = -EINVAL;
653 goto fail_cmd;
654 }
655
656 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
657 atomic_read(
658 &this_adm.copp.stat[port_idx][copp_idx]) >= 0,
659 msecs_to_jiffies(TIMEOUT_MS));
660 if (!ret) {
661 pr_err("%s: set params timed out port = %d\n",
662 __func__, port_id);
663 ret = -ETIMEDOUT;
664 goto fail_cmd;
665 }
666 ret = 0;
667fail_cmd:
668 kfree(adm_params);
669
670 return ret;
671}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530672EXPORT_SYMBOL(adm_programable_channel_mixer);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530673
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530674/**
675 * adm_set_stereo_to_custom_stereo -
676 * command to update custom stereo
677 *
678 * @port_id: Port ID number
679 * @copp_idx: copp index of ADM copp
680 * @session_id: session id to be updated
681 * @params: params pointer
682 * @param_length: length of params
683 *
684 * Returns 0 on success or error on failure
685 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530686int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx,
687 unsigned int session_id, char *params,
688 uint32_t params_length)
689{
690 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
691 int sz, rc = 0, port_idx;
692
693 pr_debug("%s:\n", __func__);
694 port_id = afe_convert_virtual_to_portid(port_id);
695 port_idx = adm_validate_and_get_port_index(port_id);
696 if (port_idx < 0) {
697 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
698 return -EINVAL;
699 }
700
701 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
702 params_length;
703 adm_params = kzalloc(sz, GFP_KERNEL);
704 if (!adm_params) {
705 pr_err("%s, adm params memory alloc failed\n", __func__);
706 return -ENOMEM;
707 }
708
709 memcpy(((u8 *)adm_params +
710 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)),
711 params, params_length);
712 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
713 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
714 adm_params->hdr.pkt_size = sz;
715 adm_params->hdr.src_svc = APR_SVC_ADM;
716 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
717 adm_params->hdr.src_port = port_id;
718 adm_params->hdr.dest_svc = APR_SVC_ADM;
719 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
720 adm_params->hdr.dest_port = 0; /* Ignored */;
721 adm_params->hdr.token = port_idx << 16 | copp_idx;
722 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
723 adm_params->payload_addr_lsw = 0;
724 adm_params->payload_addr_msw = 0;
725 adm_params->mem_map_handle = 0;
726 adm_params->payload_size = params_length;
727 /* direction RX as 0 */
728 adm_params->direction = ADM_MATRIX_ID_AUDIO_RX;
729 /* session id for this cmd to be applied on */
730 adm_params->sessionid = session_id;
731 adm_params->deviceid =
732 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
733 adm_params->reserved = 0;
734 pr_debug("%s: deviceid %d, session_id %d, src_port %d, dest_port %d\n",
735 __func__, adm_params->deviceid, adm_params->sessionid,
736 adm_params->hdr.src_port, adm_params->hdr.dest_port);
737 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
738 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
739 if (rc < 0) {
740 pr_err("%s: Set params failed port = 0x%x rc %d\n",
741 __func__, port_id, rc);
742 rc = -EINVAL;
743 goto set_stereo_to_custom_stereo_return;
744 }
745 /* Wait for the callback */
746 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
747 atomic_read(&this_adm.copp.stat
748 [port_idx][copp_idx]) >= 0,
749 msecs_to_jiffies(TIMEOUT_MS));
750 if (!rc) {
751 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
752 port_id);
753 rc = -EINVAL;
754 goto set_stereo_to_custom_stereo_return;
755 } else if (atomic_read(&this_adm.copp.stat
756 [port_idx][copp_idx]) > 0) {
757 pr_err("%s: DSP returned error[%s]\n", __func__,
758 adsp_err_get_err_str(atomic_read(
759 &this_adm.copp.stat
760 [port_idx][copp_idx])));
761 rc = adsp_err_get_lnx_err_code(
762 atomic_read(&this_adm.copp.stat
763 [port_idx][copp_idx]));
764 goto set_stereo_to_custom_stereo_return;
765 }
766 rc = 0;
767set_stereo_to_custom_stereo_return:
768 kfree(adm_params);
769 return rc;
770}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530771EXPORT_SYMBOL(adm_set_stereo_to_custom_stereo);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530772
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800773/*
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -0700774 * adm_set_custom_chmix_cfg:
775 * Set the custom channel mixer configuration for ADM
776 *
777 * @port_id: Backend port id
778 * @copp_idx: ADM copp index
779 * @session_id: ID of the requesting session
780 * @params: Expected packaged params for channel mixer
781 * @params_length: Length of the params to be set
782 * @direction: RX or TX direction
783 * @stream_type: Audio or Listen stream type
784 */
785int adm_set_custom_chmix_cfg(int port_id, int copp_idx,
786 unsigned int session_id, char *params,
787 uint32_t params_length, int direction,
788 int stream_type)
789{
790 struct adm_cmd_set_pspd_mtmx_strtr_params_v6 *adm_params = NULL;
791 int sz, rc = 0, port_idx;
792
793 port_id = afe_convert_virtual_to_portid(port_id);
794 port_idx = adm_validate_and_get_port_index(port_id);
795 if (port_idx < 0) {
796 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
797 return -EINVAL;
798 }
799
800 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v6) +
801 params_length;
802 adm_params = kzalloc(sz, GFP_KERNEL);
803 if (!adm_params) {
804 pr_err("%s, adm params memory alloc failed\n", __func__);
805 return -ENOMEM;
806 }
807
808 memcpy(((u8 *)adm_params +
809 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v6)),
810 params, params_length);
811 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
812 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
813 adm_params->hdr.pkt_size = sz;
814 adm_params->hdr.src_svc = APR_SVC_ADM;
815 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
816 adm_params->hdr.src_port = port_id;
817 adm_params->hdr.dest_svc = APR_SVC_ADM;
818 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
819 adm_params->hdr.dest_port = 0; /* Ignored */;
820 adm_params->hdr.token = port_idx << 16 | copp_idx;
821 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6;
822 adm_params->payload_addr_lsw = 0;
823 adm_params->payload_addr_msw = 0;
824 adm_params->mem_map_handle = 0;
825 adm_params->payload_size = params_length;
826 adm_params->direction = direction;
827 /* session id for this cmd to be applied on */
828 adm_params->sessionid = session_id;
829 adm_params->deviceid =
830 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
831 /* connecting stream type i.e. lsm or asm */
832 adm_params->stream_type = stream_type;
833 pr_debug("%s: deviceid %d, session_id %d, src_port %d, dest_port %d\n",
834 __func__, adm_params->deviceid, adm_params->sessionid,
835 adm_params->hdr.src_port, adm_params->hdr.dest_port);
836 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
837 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
838 if (rc < 0) {
839 pr_err("%s: Set params failed port = 0x%x rc %d\n",
840 __func__, port_id, rc);
841 rc = -EINVAL;
842 goto exit;
843 }
844 /* Wait for the callback */
845 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
846 atomic_read(&this_adm.copp.stat
847 [port_idx][copp_idx]),
848 msecs_to_jiffies(TIMEOUT_MS));
849 if (!rc) {
850 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
851 port_id);
852 rc = -EINVAL;
853 goto exit;
854 } else if (atomic_read(&this_adm.copp.stat
855 [port_idx][copp_idx]) > 0) {
856 pr_err("%s: DSP returned error[%s]\n", __func__,
857 adsp_err_get_err_str(atomic_read(
858 &this_adm.copp.stat
859 [port_idx][copp_idx])));
860 rc = adsp_err_get_lnx_err_code(
861 atomic_read(&this_adm.copp.stat
862 [port_idx][copp_idx]));
863 goto exit;
864 }
865
866 rc = 0;
867exit:
868 kfree(adm_params);
869 return rc;
870}
871EXPORT_SYMBOL(adm_set_custom_chmix_cfg);
872
873/*
Soumya Managoli97f90ea2020-04-28 09:16:55 +0530874 * adm_apr_send_pkt : returns 0 on success, negative otherwise.
875 */
876int adm_apr_send_pkt(void *data, wait_queue_head_t *wait,
877 int port_idx, int copp_idx)
878{
879 int ret = 0;
880 atomic_t *copp_stat = NULL;
881 wait = &this_adm.copp.wait[port_idx][copp_idx];
882
883 if (!wait)
884 return -EINVAL;
885
886 mutex_lock(&this_adm.adm_apr_lock);
887 pr_debug("%s: port idx %d copp idx %d\n", __func__,
888 port_idx, copp_idx);
889 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
890 atomic_set(copp_stat, -1);
891
892 if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) {
893 pr_err("%s: port[0x%x] coppid[0x%x] is not active, ERROR\n",
894 __func__, port_idx, copp_idx);
895 mutex_unlock(&this_adm.adm_apr_lock);
896 return -EINVAL;
897 }
898
899 ret = apr_send_pkt(this_adm.apr, data);
900 if (ret > 0) {
901 ret = wait_event_timeout(*wait,
902 atomic_read(copp_stat) >= 0,
903 msecs_to_jiffies(TIMEOUT_MS));
904 if (atomic_read(copp_stat) > 0) {
905 pr_err("%s: DSP returned error[%s]\n", __func__,
906 adsp_err_get_err_str(atomic_read(copp_stat)));
907 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
908 } else if (!ret) {
909 pr_err_ratelimited("%s: request timedout\n",
910 __func__);
911 ret = -ETIMEDOUT;
912 } else {
913 ret = 0;
914 }
915 } else if (ret == 0) {
916 pr_err("%s: packet not transmitted\n", __func__);
917 /* apr_send_pkt can return 0 when nothing is transmitted */
918 ret = -EINVAL;
919 }
920
921 mutex_unlock(&this_adm.adm_apr_lock);
922 return ret;
923}
924
925/*
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800926 * With pre-packed data, only the opcode differes from V5 and V6.
927 * Use q6common_pack_pp_params to pack the data correctly.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530928 */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800929int adm_set_pp_params(int port_id, int copp_idx,
930 struct mem_mapping_hdr *mem_hdr, u8 *param_data,
931 u32 param_size)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530932{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800933 struct adm_cmd_set_pp_params *adm_set_params = NULL;
934 int size = 0;
935 int port_idx = 0;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800936 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530937
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530938 port_id = afe_convert_virtual_to_portid(port_id);
939 port_idx = adm_validate_and_get_port_index(port_id);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800940 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
941 pr_err("%s: Invalid port_idx 0x%x\n", __func__, port_idx);
942 return -EINVAL;
943 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
944 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530945 return -EINVAL;
946 }
947
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800948 /* Only add params_size in inband case */
949 size = sizeof(struct adm_cmd_set_pp_params);
950 if (param_data != NULL)
951 size += param_size;
952 adm_set_params = kzalloc(size, GFP_KERNEL);
953 if (!adm_set_params)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530954 return -ENOMEM;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800955
956 adm_set_params->apr_hdr.hdr_field =
957 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
958 APR_PKT_VER);
959 adm_set_params->apr_hdr.pkt_size = size;
960 adm_set_params->apr_hdr.src_svc = APR_SVC_ADM;
961 adm_set_params->apr_hdr.src_domain = APR_DOMAIN_APPS;
962 adm_set_params->apr_hdr.src_port = port_id;
963 adm_set_params->apr_hdr.dest_svc = APR_SVC_ADM;
964 adm_set_params->apr_hdr.dest_domain = APR_DOMAIN_ADSP;
965 adm_set_params->apr_hdr.dest_port =
966 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
967 adm_set_params->apr_hdr.token = port_idx << 16 | copp_idx;
968
969 if (q6common_is_instance_id_supported())
970 adm_set_params->apr_hdr.opcode = ADM_CMD_SET_PP_PARAMS_V6;
971 else
972 adm_set_params->apr_hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
973
974 adm_set_params->payload_size = param_size;
975
976 if (mem_hdr != NULL) {
977 /* Out of Band Case */
978 adm_set_params->mem_hdr = *mem_hdr;
979 } else if (param_data != NULL) {
980 /*
981 * In band case. Parameter data must be pre-packed with its
982 * header before calling this function. Use
983 * q6common_pack_pp_params to pack parameter data and header
984 * correctly.
985 */
986 memcpy(&adm_set_params->param_data, param_data, param_size);
987 } else {
988 pr_err("%s: Received NULL pointers for both memory header and param data\n",
989 __func__);
990 ret = -EINVAL;
991 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530992 }
Soumya Managoli97f90ea2020-04-28 09:16:55 +0530993 ret = adm_apr_send_pkt((uint32_t *) adm_set_params,
994 &this_adm.copp.wait[port_idx][copp_idx],
995 port_idx, copp_idx);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800996done:
997 kfree(adm_set_params);
998 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530999}
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001000EXPORT_SYMBOL(adm_set_pp_params);
1001
1002int adm_pack_and_set_one_pp_param(int port_id, int copp_idx,
1003 struct param_hdr_v3 param_hdr, u8 *param_data)
1004{
1005 u8 *packed_data = NULL;
1006 u32 total_size = 0;
1007 int ret = 0;
1008
1009 total_size = sizeof(union param_hdrs) + param_hdr.param_size;
1010 packed_data = kzalloc(total_size, GFP_KERNEL);
1011 if (!packed_data)
1012 return -ENOMEM;
1013
1014 ret = q6common_pack_pp_params(packed_data, &param_hdr, param_data,
1015 &total_size);
1016 if (ret) {
1017 pr_err("%s: Failed to pack parameter data, error %d\n",
1018 __func__, ret);
1019 goto done;
1020 }
1021
1022 ret = adm_set_pp_params(port_id, copp_idx, NULL, packed_data,
1023 total_size);
1024 if (ret)
1025 pr_err("%s: Failed to set parameter data, error %d\n", __func__,
1026 ret);
1027done:
1028 kfree(packed_data);
1029 return ret;
1030}
1031EXPORT_SYMBOL(adm_pack_and_set_one_pp_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301032
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001033/*
1034 * Only one parameter can be requested at a time. Therefore, packing and sending
1035 * the request can be handled locally.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301036 */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001037int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id,
1038 struct mem_mapping_hdr *mem_hdr,
1039 struct param_hdr_v3 *param_hdr, u8 *returned_param_data)
1040{
1041 struct adm_cmd_get_pp_params adm_get_params;
1042 int total_size = 0;
1043 int get_param_array_sz = ARRAY_SIZE(adm_get_parameters);
1044 int returned_param_size = 0;
1045 int returned_param_size_in_bytes = 0;
1046 int port_idx = 0;
1047 int idx = 0;
1048 atomic_t *copp_stat = NULL;
1049 int ret = 0;
1050
1051 if (param_hdr == NULL) {
1052 pr_err("%s: Received NULL pointer for parameter header\n",
1053 __func__);
1054 return -EINVAL;
1055 }
1056
1057 port_id = afe_convert_virtual_to_portid(port_id);
1058 port_idx = adm_validate_and_get_port_index(port_id);
1059 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1060 pr_err("%s: Invalid port_idx 0x%x\n", __func__, port_idx);
1061 return -EINVAL;
1062 }
1063 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1064 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
1065 return -EINVAL;
1066 }
1067
1068 memset(&adm_get_params, 0, sizeof(adm_get_params));
1069
1070 if (mem_hdr != NULL)
1071 adm_get_params.mem_hdr = *mem_hdr;
1072
1073 q6common_pack_pp_params((u8 *) &adm_get_params.param_hdr, param_hdr,
1074 NULL, &total_size);
1075
1076 /* Pack APR header after filling body so total_size has correct value */
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001077 adm_get_params.apr_hdr.hdr_field =
1078 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1079 APR_PKT_VER);
1080 adm_get_params.apr_hdr.pkt_size = sizeof(adm_get_params);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001081 adm_get_params.apr_hdr.src_svc = APR_SVC_ADM;
1082 adm_get_params.apr_hdr.src_domain = APR_DOMAIN_APPS;
1083 adm_get_params.apr_hdr.src_port = port_id;
1084 adm_get_params.apr_hdr.dest_svc = APR_SVC_ADM;
1085 adm_get_params.apr_hdr.dest_domain = APR_DOMAIN_ADSP;
1086 adm_get_params.apr_hdr.dest_port =
1087 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1088 adm_get_params.apr_hdr.token =
1089 port_idx << 16 | client_id << 8 | copp_idx;
1090
1091 if (q6common_is_instance_id_supported())
1092 adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V6;
1093 else
1094 adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
1095
1096 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
1097 atomic_set(copp_stat, -1);
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001098
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001099 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_params);
Vidyakumar Athotae427c412018-06-16 00:02:46 -07001100 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001101 pr_err("%s: Get params APR send failed port = 0x%x ret %d\n",
1102 __func__, port_id, ret);
1103 ret = -EINVAL;
1104 goto done;
1105 }
1106 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1107 atomic_read(copp_stat) >= 0,
1108 msecs_to_jiffies(TIMEOUT_MS));
1109 if (!ret) {
1110 pr_err("%s: Get params timed out port = 0x%x\n", __func__,
1111 port_id);
1112 ret = -ETIMEDOUT;
1113 goto done;
1114 }
1115 if (atomic_read(copp_stat) > 0) {
1116 pr_err("%s: DSP returned error[%s]\n", __func__,
1117 adsp_err_get_err_str(atomic_read(copp_stat)));
1118 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
1119 goto done;
1120 }
1121
1122 ret = 0;
1123
1124 /* Copy data to caller if sent in band */
1125 if (!returned_param_data) {
1126 pr_debug("%s: Received NULL pointer for param destination, not copying payload\n",
1127 __func__);
1128 return 0;
1129 }
1130
1131 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
1132 returned_param_size = adm_get_parameters[idx];
1133 if (returned_param_size < 0 ||
1134 returned_param_size + idx + 1 > get_param_array_sz) {
1135 pr_err("%s: Invalid parameter size %d\n", __func__,
1136 returned_param_size);
1137 return -EINVAL;
1138 }
1139
1140 returned_param_size_in_bytes = returned_param_size * sizeof(uint32_t);
1141 if (param_hdr->param_size < returned_param_size_in_bytes) {
1142 pr_err("%s: Provided buffer is not big enough, provided buffer size(%d) size needed(%d)\n",
1143 __func__, param_hdr->param_size,
1144 returned_param_size_in_bytes);
1145 return -EINVAL;
1146 }
1147
1148 memcpy(returned_param_data, &adm_get_parameters[idx + 1],
1149 returned_param_size_in_bytes);
1150done:
1151 return ret;
1152}
1153EXPORT_SYMBOL(adm_get_pp_params);
1154
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001155int adm_get_pp_topo_module_list_v2(int port_id, int copp_idx,
1156 int32_t param_length,
1157 int32_t *returned_params)
1158{
1159 struct adm_cmd_get_pp_topo_module_list adm_get_module_list;
1160 bool iid_supported = q6common_is_instance_id_supported();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301161 int *topo_list;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001162 int num_modules = 0;
1163 int list_size = 0;
1164 int port_idx, idx;
1165 int i = 0;
1166 atomic_t *copp_stat = NULL;
1167 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301168
1169 pr_debug("%s : port_id %x", __func__, port_id);
1170 port_id = afe_convert_virtual_to_portid(port_id);
1171 port_idx = adm_validate_and_get_port_index(port_id);
1172 if (port_idx < 0) {
1173 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1174 return -EINVAL;
1175 }
1176
1177 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1178 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
1179 return -EINVAL;
1180 }
1181
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001182 memset(&adm_get_module_list, 0, sizeof(adm_get_module_list));
1183
1184 adm_get_module_list.apr_hdr.pkt_size = sizeof(adm_get_module_list);
1185 adm_get_module_list.apr_hdr.src_svc = APR_SVC_ADM;
1186 adm_get_module_list.apr_hdr.src_domain = APR_DOMAIN_APPS;
1187 adm_get_module_list.apr_hdr.src_port = port_id;
1188 adm_get_module_list.apr_hdr.dest_svc = APR_SVC_ADM;
1189 adm_get_module_list.apr_hdr.dest_domain = APR_DOMAIN_ADSP;
1190 adm_get_module_list.apr_hdr.dest_port =
1191 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1192 adm_get_module_list.apr_hdr.token = port_idx << 16 | copp_idx;
1193 /*
1194 * Out of band functionality is not currently utilized.
1195 * Assume in band.
1196 */
1197 if (iid_supported) {
1198 adm_get_module_list.apr_hdr.opcode =
1199 ADM_CMD_GET_PP_TOPO_MODULE_LIST_V2;
1200 adm_get_module_list.param_max_size = param_length;
1201 } else {
1202 adm_get_module_list.apr_hdr.opcode =
1203 ADM_CMD_GET_PP_TOPO_MODULE_LIST;
1204
1205 if (param_length > U16_MAX) {
1206 pr_err("%s: Invalid param length for V1 %d\n", __func__,
1207 param_length);
1208 return -EINVAL;
1209 }
1210 adm_get_module_list.param_max_size = param_length << 16;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301211 }
1212
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001213 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
1214 atomic_set(copp_stat, -1);
1215 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_module_list);
Vidyakumar Athotae427c412018-06-16 00:02:46 -07001216 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001217 pr_err("%s: APR send pkt failed for port_id: 0x%x failed ret %d\n",
1218 __func__, port_id, ret);
1219 ret = -EINVAL;
1220 goto done;
1221 }
1222 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1223 atomic_read(copp_stat) >= 0,
1224 msecs_to_jiffies(TIMEOUT_MS));
1225 if (!ret) {
1226 pr_err("%s: Timeout for port_id: 0x%x\n", __func__, port_id);
1227 ret = -ETIMEDOUT;
1228 goto done;
1229 }
1230 if (atomic_read(copp_stat) > 0) {
1231 pr_err("%s: DSP returned error[%s]\n", __func__,
1232 adsp_err_get_err_str(atomic_read(copp_stat)));
1233 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
1234 goto done;
1235 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301236
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001237 ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301238
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001239 if (returned_params) {
1240 /*
1241 * When processing ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST IID is
1242 * added since it is not present. Therefore, there is no need to
1243 * do anything different if IID is not supported here as it is
1244 * already taken care of.
1245 */
1246 idx = ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH * copp_idx;
1247 num_modules = adm_module_topo_list[idx];
1248 if (num_modules < 0 || num_modules > MAX_MODULES_IN_TOPO) {
1249 pr_err("%s: Invalid number of modules returned %d\n",
1250 __func__, num_modules);
1251 return -EINVAL;
1252 }
1253
1254 list_size = num_modules * sizeof(struct module_instance_info);
1255 if (param_length < list_size) {
1256 pr_err("%s: Provided buffer not big enough to hold module-instance list, provided size %d, needed size %d\n",
1257 __func__, param_length, list_size);
1258 return -EINVAL;
1259 }
1260
1261 topo_list = (int32_t *) (&adm_module_topo_list[idx]);
1262 memcpy(returned_params, topo_list, list_size);
1263 for (i = 1; i <= num_modules; i += 2) {
1264 pr_debug("module = 0x%x instance = 0x%x\n",
1265 returned_params[i], returned_params[i + 1]);
1266 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301267 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001268done:
1269 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301270}
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001271EXPORT_SYMBOL(adm_get_pp_topo_module_list_v2);
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301272
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301273static void adm_callback_debug_print(struct apr_client_data *data)
1274{
1275 uint32_t *payload;
1276
1277 payload = data->payload;
1278
1279 if (data->payload_size >= 8)
1280 pr_debug("%s: code = 0x%x PL#0[0x%x], PL#1[0x%x], size = %d\n",
1281 __func__, data->opcode, payload[0], payload[1],
1282 data->payload_size);
1283 else if (data->payload_size >= 4)
1284 pr_debug("%s: code = 0x%x PL#0[0x%x], size = %d\n",
1285 __func__, data->opcode, payload[0],
1286 data->payload_size);
1287 else
1288 pr_debug("%s: code = 0x%x, size = %d\n",
1289 __func__, data->opcode, data->payload_size);
1290}
1291
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301292/**
1293 * adm_set_multi_ch_map -
1294 * Update multi channel map info
1295 *
1296 * @channel_map: pointer with channel map info
1297 * @path: direction or ADM path type
1298 *
1299 * Returns 0 on success or error on failure
1300 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301301int adm_set_multi_ch_map(char *channel_map, int path)
1302{
1303 int idx;
1304
1305 if (path == ADM_PATH_PLAYBACK) {
1306 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1307 } else if (path == ADM_PATH_LIVE_REC) {
1308 idx = ADM_MCH_MAP_IDX_REC;
1309 } else {
1310 pr_err("%s: invalid attempt to set path %d\n", __func__, path);
1311 return -EINVAL;
1312 }
1313
1314 memcpy(multi_ch_maps[idx].channel_mapping, channel_map,
Dieter Luecking50c55352018-09-28 14:29:17 +02001315 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301316 multi_ch_maps[idx].set_channel_map = true;
1317
1318 return 0;
1319}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301320EXPORT_SYMBOL(adm_set_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301321
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301322/**
1323 * adm_get_multi_ch_map -
1324 * Retrieves multi channel map info
1325 *
1326 * @channel_map: pointer to be updated with channel map
1327 * @path: direction or ADM path type
1328 *
1329 * Returns 0 on success or error on failure
1330 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301331int adm_get_multi_ch_map(char *channel_map, int path)
1332{
1333 int idx;
1334
1335 if (path == ADM_PATH_PLAYBACK) {
1336 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1337 } else if (path == ADM_PATH_LIVE_REC) {
1338 idx = ADM_MCH_MAP_IDX_REC;
1339 } else {
1340 pr_err("%s: invalid attempt to get path %d\n", __func__, path);
1341 return -EINVAL;
1342 }
1343
1344 if (multi_ch_maps[idx].set_channel_map) {
1345 memcpy(channel_map, multi_ch_maps[idx].channel_mapping,
Dieter Luecking50c55352018-09-28 14:29:17 +02001346 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301347 }
1348
1349 return 0;
1350}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301351EXPORT_SYMBOL(adm_get_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301352
Rohit kumar2054b692019-02-01 18:01:12 +05301353/**
1354 * adm_set_port_multi_ch_map -
1355 * Update port specific channel map info
1356 *
1357 * @channel_map: pointer with channel map info
1358 * @port_id: port for which chmap is set
1359 */
1360void adm_set_port_multi_ch_map(char *channel_map, int port_id)
1361{
1362 int port_idx;
1363
1364 port_id = q6audio_convert_virtual_to_portid(port_id);
1365 port_idx = adm_validate_and_get_port_index(port_id);
1366
1367 if (port_idx < 0) {
1368 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1369 return;
1370 }
1371
1372 memcpy(port_channel_map[port_idx].channel_mapping, channel_map,
1373 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
1374 port_channel_map[port_idx].set_channel_map = true;
1375}
1376EXPORT_SYMBOL(adm_set_port_multi_ch_map);
1377
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001378static int adm_process_get_param_response(u32 opcode, u32 idx, u32 *payload,
1379 u32 payload_size)
1380{
1381 struct adm_cmd_rsp_get_pp_params_v5 *v5_rsp = NULL;
1382 struct adm_cmd_rsp_get_pp_params_v6 *v6_rsp = NULL;
1383 u32 *param_data = NULL;
1384 int data_size = 0;
1385 int struct_size = 0;
1386
1387 if (payload == NULL) {
1388 pr_err("%s: Payload is NULL\n", __func__);
1389 return -EINVAL;
1390 }
1391
1392 switch (opcode) {
1393 case ADM_CMDRSP_GET_PP_PARAMS_V5:
1394 struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v5);
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001395 if (payload_size < struct_size) {
1396 pr_err("%s: payload size %d < expected size %d\n",
1397 __func__, payload_size, struct_size);
1398 break;
1399 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001400 v5_rsp = (struct adm_cmd_rsp_get_pp_params_v5 *) payload;
1401 data_size = v5_rsp->param_hdr.param_size;
1402 param_data = v5_rsp->param_data;
1403 break;
1404 case ADM_CMDRSP_GET_PP_PARAMS_V6:
1405 struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v6);
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001406 if (payload_size < struct_size) {
1407 pr_err("%s: payload size %d < expected size %d\n",
1408 __func__, payload_size, struct_size);
1409 break;
1410 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001411 v6_rsp = (struct adm_cmd_rsp_get_pp_params_v6 *) payload;
1412 data_size = v6_rsp->param_hdr.param_size;
1413 param_data = v6_rsp->param_data;
1414 break;
1415 default:
1416 pr_err("%s: Invalid opcode %d\n", __func__, opcode);
1417 return -EINVAL;
1418 }
1419
1420 /*
1421 * Just store the returned parameter data, not the header. The calling
1422 * function is expected to know what it asked for. Therefore, there is
1423 * no difference between V5 and V6.
1424 */
1425 if ((payload_size >= struct_size + data_size) &&
1426 (ARRAY_SIZE(adm_get_parameters) > idx) &&
Karthikeyan Mani95be5b12018-11-09 14:57:32 -08001427 (ARRAY_SIZE(adm_get_parameters) > idx + 1 + data_size)) {
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001428 pr_debug("%s: Received parameter data in band\n",
1429 __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001430 /*
1431 * data_size is expressed in number of bytes, store in number of
1432 * ints
1433 */
1434 adm_get_parameters[idx] =
1435 data_size / sizeof(*adm_get_parameters);
1436 pr_debug("%s: GET_PP PARAM: received parameter length: 0x%x\n",
1437 __func__, adm_get_parameters[idx]);
1438 /* store params after param_size */
1439 memcpy(&adm_get_parameters[idx + 1], param_data, data_size);
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001440 } else if (payload_size == sizeof(uint32_t)) {
1441 adm_get_parameters[idx] = -1;
1442 pr_debug("%s: Out of band case, setting size to %d\n",
1443 __func__, adm_get_parameters[idx]);
1444 } else {
1445 pr_err("%s: Invalid parameter combination, payload_size %d, idx %d\n",
1446 __func__, payload_size, idx);
1447 return -EINVAL;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001448 }
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001449 return 0;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001450}
1451
1452static int adm_process_get_topo_list_response(u32 opcode, int copp_idx,
1453 u32 num_modules, u32 *payload,
1454 u32 payload_size)
1455{
1456 u32 *fill_list = NULL;
1457 int idx = 0;
1458 int i = 0;
1459 int j = 0;
1460
1461 if (payload == NULL) {
1462 pr_err("%s: Payload is NULL\n", __func__);
1463 return -EINVAL;
1464 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1465 pr_err("%s: Invalid COPP index %d\n", __func__, copp_idx);
1466 return -EINVAL;
1467 }
1468
1469 idx = ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH * copp_idx;
1470 fill_list = adm_module_topo_list + idx;
1471 *fill_list++ = num_modules;
1472 for (i = 0; i < num_modules; i++) {
1473 if (j > payload_size / sizeof(u32)) {
1474 pr_err("%s: Invalid number of modules specified %d\n",
1475 __func__, num_modules);
1476 return -EINVAL;
1477 }
1478
1479 /* store module ID */
1480 *fill_list++ = payload[j];
1481 j++;
1482
1483 switch (opcode) {
1484 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
1485 /* store instance ID */
1486 *fill_list++ = payload[j];
1487 j++;
1488 break;
1489 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
1490 /* Insert IID 0 when repacking */
1491 *fill_list++ = INSTANCE_ID_0;
1492 break;
1493 default:
1494 pr_err("%s: Invalid opcode %d\n", __func__, opcode);
1495 return -EINVAL;
1496 }
1497 }
1498
1499 return 0;
1500}
1501
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301502static void adm_reset_data(void)
1503{
1504 int i, j;
1505
1506 apr_reset(this_adm.apr);
1507 for (i = 0; i < AFE_MAX_PORTS; i++) {
1508 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
1509 atomic_set(&this_adm.copp.id[i][j],
1510 RESET_COPP_ID);
1511 atomic_set(&this_adm.copp.cnt[i][j], 0);
1512 atomic_set(
1513 &this_adm.copp.topology[i][j], 0);
1514 atomic_set(&this_adm.copp.mode[i][j],
1515 0);
1516 atomic_set(&this_adm.copp.stat[i][j],
1517 0);
1518 atomic_set(&this_adm.copp.rate[i][j],
1519 0);
1520 atomic_set(
1521 &this_adm.copp.channels[i][j],
1522 0);
1523 atomic_set(
1524 &this_adm.copp.bit_width[i][j], 0);
1525 atomic_set(
1526 &this_adm.copp.app_type[i][j], 0);
1527 atomic_set(
1528 &this_adm.copp.acdb_id[i][j], 0);
Surendar Karkae7507512018-07-20 15:46:54 +05301529 atomic_set(
1530 &this_adm.copp.session_type[i][j], 0);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301531 this_adm.copp.adm_status[i][j] =
1532 ADM_STATUS_CALIBRATION_REQUIRED;
1533 }
1534 }
1535 this_adm.apr = NULL;
1536 cal_utils_clear_cal_block_q6maps(ADM_MAX_CAL_TYPES,
1537 this_adm.cal_data);
1538 mutex_lock(&this_adm.cal_data
1539 [ADM_CUSTOM_TOP_CAL]->lock);
1540 this_adm.set_custom_topology = 1;
1541 mutex_unlock(&this_adm.cal_data[
1542 ADM_CUSTOM_TOP_CAL]->lock);
1543 rtac_clear_mapping(ADM_RTAC_CAL);
1544 /*
1545 * Free the ION memory and clear the map handles
1546 * for Source Tracking
1547 */
1548 if (this_adm.sourceTrackingData.memmap.paddr != 0) {
1549 msm_audio_ion_free(
1550 this_adm.sourceTrackingData.dma_buf);
1551 this_adm.sourceTrackingData.dma_buf = NULL;
1552 this_adm.sourceTrackingData.memmap.size = 0;
1553 this_adm.sourceTrackingData.memmap.kvaddr =
1554 NULL;
1555 this_adm.sourceTrackingData.memmap.paddr = 0;
1556 this_adm.sourceTrackingData.apr_cmd_status = -1;
1557 atomic_set(&this_adm.mem_map_handles[
1558 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
1559 }
1560}
1561
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301562static int32_t adm_callback(struct apr_client_data *data, void *priv)
1563{
1564 uint32_t *payload;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001565 int port_idx, copp_idx, idx, client_id;
1566 int num_modules;
1567 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301568
1569 if (data == NULL) {
1570 pr_err("%s: data parameter is null\n", __func__);
1571 return -EINVAL;
1572 }
1573
1574 payload = data->payload;
1575
1576 if (data->opcode == RESET_EVENTS) {
1577 pr_debug("%s: Reset event is received: %d %d apr[%pK]\n",
1578 __func__,
1579 data->reset_event, data->reset_proc, this_adm.apr);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301580 if (this_adm.apr)
1581 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301582 return 0;
1583 }
1584
1585 adm_callback_debug_print(data);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001586 if (data->payload_size >= sizeof(uint32_t)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301587 copp_idx = (data->token) & 0XFF;
1588 port_idx = ((data->token) >> 16) & 0xFF;
1589 client_id = ((data->token) >> 8) & 0xFF;
1590 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1591 pr_err("%s: Invalid port idx %d token %d\n",
1592 __func__, port_idx, data->token);
1593 return 0;
1594 }
1595 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1596 pr_err("%s: Invalid copp idx %d token %d\n",
1597 __func__, copp_idx, data->token);
1598 return 0;
1599 }
1600 if (client_id < 0 || client_id >= ADM_CLIENT_ID_MAX) {
1601 pr_err("%s: Invalid client id %d\n", __func__,
1602 client_id);
1603 return 0;
1604 }
1605 if (data->opcode == APR_BASIC_RSP_RESULT) {
1606 pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
1607 __func__, payload[0]);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001608
1609 if (!((client_id != ADM_CLIENT_ID_SOURCE_TRACKING) &&
1610 ((payload[0] == ADM_CMD_SET_PP_PARAMS_V5) ||
1611 (payload[0] == ADM_CMD_SET_PP_PARAMS_V6)))) {
1612 if (data->payload_size <
1613 (2 * sizeof(uint32_t))) {
1614 pr_err("%s: Invalid payload size %d\n",
1615 __func__, data->payload_size);
1616 return 0;
1617 }
1618 }
1619
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301620 if (payload[1] != 0) {
1621 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
1622 __func__, payload[0], payload[1]);
1623 }
1624 switch (payload[0]) {
1625 case ADM_CMD_SET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001626 case ADM_CMD_SET_PP_PARAMS_V6:
1627 pr_debug("%s: ADM_CMD_SET_PP_PARAMS\n",
1628 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301629 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1630 this_adm.sourceTrackingData.
1631 apr_cmd_status = payload[1];
1632 else if (rtac_make_adm_callback(payload,
Soumya Managoli97f90ea2020-04-28 09:16:55 +05301633 data->payload_size)) {
1634 pr_debug("%s: rtac cmd response\n",
1635 __func__);
1636 }
1637 atomic_set(&this_adm.copp.stat[port_idx]
1638 [copp_idx], payload[1]);
1639 wake_up(
1640 &this_adm.copp.wait[port_idx][copp_idx]);
1641 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301642 /*
1643 * if soft volume is called and already
1644 * interrupted break out of the sequence here
1645 */
1646 case ADM_CMD_DEVICE_OPEN_V5:
1647 case ADM_CMD_DEVICE_CLOSE_V5:
1648 case ADM_CMD_DEVICE_OPEN_V6:
Dieter Luecking50c55352018-09-28 14:29:17 +02001649 case ADM_CMD_DEVICE_OPEN_V8:
Soumya Managoli97f90ea2020-04-28 09:16:55 +05301650 pr_debug("%s: Basic callback received for 0x%x, wake up.\n",
1651 __func__, payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301652 atomic_set(&this_adm.copp.stat[port_idx]
1653 [copp_idx], payload[1]);
1654 wake_up(
1655 &this_adm.copp.wait[port_idx][copp_idx]);
1656 break;
1657 case ADM_CMD_ADD_TOPOLOGIES:
1658 pr_debug("%s: callback received, ADM_CMD_ADD_TOPOLOGIES.\n",
1659 __func__);
1660 atomic_set(&this_adm.adm_stat, payload[1]);
1661 wake_up(&this_adm.adm_wait);
1662 break;
1663 case ADM_CMD_MATRIX_MAP_ROUTINGS_V5:
1664 case ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5:
1665 pr_debug("%s: Basic callback received, wake up.\n",
1666 __func__);
1667 atomic_set(&this_adm.matrix_map_stat,
1668 payload[1]);
1669 wake_up(&this_adm.matrix_map_wait);
1670 break;
1671 case ADM_CMD_SHARED_MEM_UNMAP_REGIONS:
1672 pr_debug("%s: ADM_CMD_SHARED_MEM_UNMAP_REGIONS\n",
1673 __func__);
1674 atomic_set(&this_adm.adm_stat, payload[1]);
1675 wake_up(&this_adm.adm_wait);
1676 break;
1677 case ADM_CMD_SHARED_MEM_MAP_REGIONS:
1678 pr_debug("%s: ADM_CMD_SHARED_MEM_MAP_REGIONS\n",
1679 __func__);
1680 /* Should only come here if there is an APR */
1681 /* error or malformed APR packet. Otherwise */
1682 /* response will be returned as */
1683 if (payload[1] != 0) {
1684 pr_err("%s: ADM map error, resuming\n",
1685 __func__);
1686 atomic_set(&this_adm.adm_stat,
1687 payload[1]);
1688 wake_up(&this_adm.adm_wait);
1689 }
1690 break;
1691 case ADM_CMD_GET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001692 case ADM_CMD_GET_PP_PARAMS_V6:
1693 pr_debug("%s: ADM_CMD_GET_PP_PARAMS\n",
1694 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301695 /* Should only come here if there is an APR */
1696 /* error or malformed APR packet. Otherwise */
1697 /* response will be returned as */
1698 /* ADM_CMDRSP_GET_PP_PARAMS_V5 */
1699 if (client_id ==
1700 ADM_CLIENT_ID_SOURCE_TRACKING) {
1701 this_adm.sourceTrackingData.
1702 apr_cmd_status = payload[1];
1703 if (payload[1] != 0)
1704 pr_err("%s: ADM get param error = %d\n",
1705 __func__, payload[1]);
1706
1707 atomic_set(&this_adm.copp.stat
1708 [port_idx][copp_idx],
1709 payload[1]);
1710 wake_up(&this_adm.copp.wait
1711 [port_idx][copp_idx]);
1712 } else {
1713 if (payload[1] != 0) {
1714 pr_err("%s: ADM get param error = %d, resuming\n",
1715 __func__, payload[1]);
1716
1717 rtac_make_adm_callback(payload,
1718 data->payload_size);
1719 }
1720 }
1721 break;
1722 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5:
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -07001723 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6:
1724 pr_debug("%s:callback received PSPD MTMX, wake up\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301725 __func__);
1726 atomic_set(&this_adm.copp.stat[port_idx]
1727 [copp_idx], payload[1]);
1728 wake_up(
1729 &this_adm.copp.wait[port_idx][copp_idx]);
1730 break;
1731 case ADM_CMD_GET_PP_TOPO_MODULE_LIST:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001732 case ADM_CMD_GET_PP_TOPO_MODULE_LIST_V2:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301733 pr_debug("%s:ADM_CMD_GET_PP_TOPO_MODULE_LIST\n",
1734 __func__);
1735 if (payload[1] != 0)
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001736 pr_err("%s: ADM get topo list error = %d\n",
1737 __func__, payload[1]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301738 break;
1739 default:
1740 pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
1741 payload[0]);
1742 break;
1743 }
1744 return 0;
1745 }
1746
1747 switch (data->opcode) {
1748 case ADM_CMDRSP_DEVICE_OPEN_V5:
Dieter Luecking50c55352018-09-28 14:29:17 +02001749 case ADM_CMDRSP_DEVICE_OPEN_V6:
1750 case ADM_CMDRSP_DEVICE_OPEN_V8: {
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001751 struct adm_cmd_rsp_device_open_v5 *open = NULL;
1752 if (data->payload_size <
1753 sizeof(struct adm_cmd_rsp_device_open_v5)) {
1754 pr_err("%s: Invalid payload size %d\n", __func__,
1755 data->payload_size);
1756 return 0;
1757 }
1758 open = (struct adm_cmd_rsp_device_open_v5 *)data->payload;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301759 if (open->copp_id == INVALID_COPP_ID) {
1760 pr_err("%s: invalid coppid rxed %d\n",
1761 __func__, open->copp_id);
1762 atomic_set(&this_adm.copp.stat[port_idx]
1763 [copp_idx], ADSP_EBADPARAM);
1764 wake_up(
1765 &this_adm.copp.wait[port_idx][copp_idx]);
1766 break;
1767 }
1768 atomic_set(&this_adm.copp.stat
1769 [port_idx][copp_idx], payload[0]);
1770 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
1771 open->copp_id);
1772 pr_debug("%s: coppid rxed=%d\n", __func__,
1773 open->copp_id);
1774 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1775 }
1776 break;
1777 case ADM_CMDRSP_GET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001778 case ADM_CMDRSP_GET_PP_PARAMS_V6:
1779 pr_debug("%s: ADM_CMDRSP_GET_PP_PARAMS\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301780 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1781 this_adm.sourceTrackingData.apr_cmd_status =
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001782 payload[0];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301783 else if (rtac_make_adm_callback(payload,
Soumya Managoli97f90ea2020-04-28 09:16:55 +05301784 data->payload_size)) {
1785 pr_debug("%s: rtac cmd response\n", __func__);
1786 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1787 payload[0]);
1788 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301789 break;
Soumya Managoli97f90ea2020-04-28 09:16:55 +05301790 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301791
1792 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001793 if (payload[0] == 0 && data->payload_size > 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001794 ret = adm_process_get_param_response(
1795 data->opcode, idx, payload,
1796 data->payload_size);
1797 if (ret)
1798 pr_err("%s: Failed to process get param response, error %d\n",
1799 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301800 } else {
1801 adm_get_parameters[idx] = -1;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001802 pr_err("%s: ADM_CMDRSP_GET_PP_PARAMS returned error 0x%x\n",
1803 __func__, payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301804 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001805 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1806 payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301807 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1808 break;
1809 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001810 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301811 pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n",
1812 __func__);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001813 if (data->payload_size >= (2 * sizeof(uint32_t))) {
1814 num_modules = payload[1];
1815 pr_debug("%s: Num modules %d\n", __func__,
1816 num_modules);
1817 if (payload[0]) {
1818 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
1819 __func__, payload[0]);
1820 } else if (num_modules > MAX_MODULES_IN_TOPO) {
1821 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n",
1822 __func__, num_modules);
1823 } else {
1824 ret = adm_process_get_topo_list_response(
1825 data->opcode, copp_idx,
1826 num_modules, payload,
1827 data->payload_size);
1828 if (ret)
1829 pr_err("%s: Failed to process get topo modules list response, error %d\n",
1830 __func__, ret);
1831 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301832 } else {
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001833 pr_err("%s: Invalid payload size %d\n",
1834 __func__, data->payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301835 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001836 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1837 payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301838 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1839 break;
1840 case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
1841 pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
1842 __func__);
1843 atomic_set(&this_adm.mem_map_handles[
1844 atomic_read(&this_adm.mem_map_index)],
1845 *payload);
1846 atomic_set(&this_adm.adm_stat, 0);
1847 wake_up(&this_adm.adm_wait);
1848 break;
1849 default:
1850 pr_err("%s: Unknown cmd:0x%x\n", __func__,
1851 data->opcode);
1852 break;
1853 }
1854 }
1855 return 0;
1856}
1857
1858static int adm_memory_map_regions(phys_addr_t *buf_add, uint32_t mempool_id,
1859 uint32_t *bufsz, uint32_t bufcnt)
1860{
1861 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
1862 struct avs_shared_map_region_payload *mregions = NULL;
1863 void *mmap_region_cmd = NULL;
1864 void *payload = NULL;
1865 int ret = 0;
1866 int i = 0;
1867 int cmd_size = 0;
1868
1869 pr_debug("%s:\n", __func__);
1870 if (this_adm.apr == NULL) {
1871 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
1872 0xFFFFFFFF, &this_adm);
1873 if (this_adm.apr == NULL) {
1874 pr_err("%s: Unable to register ADM\n", __func__);
1875 ret = -ENODEV;
1876 return ret;
1877 }
1878 rtac_set_adm_handle(this_adm.apr);
1879 }
1880
1881 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
1882 + sizeof(struct avs_shared_map_region_payload)
1883 * bufcnt;
1884
1885 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1886 if (!mmap_region_cmd)
1887 return -ENOMEM;
1888
1889 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)mmap_region_cmd;
1890 mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1891 APR_HDR_LEN(APR_HDR_SIZE),
1892 APR_PKT_VER);
1893 mmap_regions->hdr.pkt_size = cmd_size;
1894 mmap_regions->hdr.src_port = 0;
1895
1896 mmap_regions->hdr.dest_port = 0;
1897 mmap_regions->hdr.token = 0;
1898 mmap_regions->hdr.opcode = ADM_CMD_SHARED_MEM_MAP_REGIONS;
1899 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL & 0x00ff;
1900 mmap_regions->num_regions = bufcnt & 0x00ff;
1901 mmap_regions->property_flag = 0x00;
1902
1903 pr_debug("%s: map_regions->num_regions = %d\n", __func__,
1904 mmap_regions->num_regions);
1905 payload = ((u8 *) mmap_region_cmd +
1906 sizeof(struct avs_cmd_shared_mem_map_regions));
1907 mregions = (struct avs_shared_map_region_payload *)payload;
1908
1909 for (i = 0; i < bufcnt; i++) {
1910 mregions->shm_addr_lsw = lower_32_bits(buf_add[i]);
1911 mregions->shm_addr_msw =
1912 msm_audio_populate_upper_32_bits(buf_add[i]);
1913 mregions->mem_size_bytes = bufsz[i];
1914 ++mregions;
1915 }
1916
1917 atomic_set(&this_adm.adm_stat, -1);
1918 ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
1919 if (ret < 0) {
1920 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1921 mmap_regions->hdr.opcode, ret);
1922 ret = -EINVAL;
1923 goto fail_cmd;
1924 }
1925
1926 ret = wait_event_timeout(this_adm.adm_wait,
1927 atomic_read(&this_adm.adm_stat) >= 0,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001928 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301929 if (!ret) {
1930 pr_err("%s: timeout. waited for memory_map\n", __func__);
1931 ret = -EINVAL;
1932 goto fail_cmd;
1933 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1934 pr_err("%s: DSP returned error[%s]\n",
1935 __func__, adsp_err_get_err_str(
1936 atomic_read(&this_adm.adm_stat)));
1937 ret = adsp_err_get_lnx_err_code(
1938 atomic_read(&this_adm.adm_stat));
1939 goto fail_cmd;
1940 }
1941fail_cmd:
1942 kfree(mmap_region_cmd);
1943 return ret;
1944}
1945
1946static int adm_memory_unmap_regions(void)
1947{
1948 struct avs_cmd_shared_mem_unmap_regions unmap_regions;
1949 int ret = 0;
1950
1951 pr_debug("%s:\n", __func__);
1952 if (this_adm.apr == NULL) {
1953 pr_err("%s: APR handle NULL\n", __func__);
1954 return -EINVAL;
1955 }
1956
1957 unmap_regions.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1958 APR_HDR_LEN(APR_HDR_SIZE),
1959 APR_PKT_VER);
1960 unmap_regions.hdr.pkt_size = sizeof(unmap_regions);
1961 unmap_regions.hdr.src_port = 0;
1962 unmap_regions.hdr.dest_port = 0;
1963 unmap_regions.hdr.token = 0;
1964 unmap_regions.hdr.opcode = ADM_CMD_SHARED_MEM_UNMAP_REGIONS;
1965 unmap_regions.mem_map_handle = atomic_read(&this_adm.
1966 mem_map_handles[atomic_read(&this_adm.mem_map_index)]);
1967 atomic_set(&this_adm.adm_stat, -1);
1968 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &unmap_regions);
1969 if (ret < 0) {
1970 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1971 unmap_regions.hdr.opcode, ret);
1972 ret = -EINVAL;
1973 goto fail_cmd;
1974 }
1975
1976 ret = wait_event_timeout(this_adm.adm_wait,
1977 atomic_read(&this_adm.adm_stat) >= 0,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001978 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301979 if (!ret) {
1980 pr_err("%s: timeout. waited for memory_unmap\n",
1981 __func__);
1982 ret = -EINVAL;
1983 goto fail_cmd;
1984 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1985 pr_err("%s: DSP returned error[%s]\n",
1986 __func__, adsp_err_get_err_str(
1987 atomic_read(&this_adm.adm_stat)));
1988 ret = adsp_err_get_lnx_err_code(
1989 atomic_read(&this_adm.adm_stat));
1990 goto fail_cmd;
1991 } else {
1992 pr_debug("%s: Unmap handle 0x%x succeeded\n", __func__,
1993 unmap_regions.mem_map_handle);
1994 }
1995fail_cmd:
1996 return ret;
1997}
1998
1999static int remap_cal_data(struct cal_block_data *cal_block, int cal_index)
2000{
2001 int ret = 0;
2002
Banajit Goswami08bb7362017-11-03 22:48:23 -07002003 if (cal_block->map_data.dma_buf == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302004 pr_err("%s: No ION allocation for cal index %d!\n",
2005 __func__, cal_index);
2006 ret = -EINVAL;
2007 goto done;
2008 }
2009
2010 if ((cal_block->map_data.map_size > 0) &&
2011 (cal_block->map_data.q6map_handle == 0)) {
2012 atomic_set(&this_adm.mem_map_index, cal_index);
2013 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
2014 (uint32_t *)&cal_block->map_data.map_size, 1);
2015 if (ret < 0) {
2016 pr_err("%s: ADM mmap did not work! size = %zd ret %d\n",
2017 __func__,
2018 cal_block->map_data.map_size, ret);
2019 pr_debug("%s: ADM mmap did not work! addr = 0x%pK, size = %zd ret %d\n",
2020 __func__,
2021 &cal_block->cal_data.paddr,
2022 cal_block->map_data.map_size, ret);
2023 goto done;
2024 }
2025 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
2026 mem_map_handles[cal_index]);
2027 }
2028done:
2029 return ret;
2030}
2031
2032static void send_adm_custom_topology(void)
2033{
2034 struct cal_block_data *cal_block = NULL;
2035 struct cmd_set_topologies adm_top;
2036 int cal_index = ADM_CUSTOM_TOP_CAL;
2037 int result;
2038
2039 if (this_adm.cal_data[cal_index] == NULL)
2040 goto done;
2041
2042 mutex_lock(&this_adm.cal_data[cal_index]->lock);
2043 if (!this_adm.set_custom_topology)
2044 goto unlock;
2045 this_adm.set_custom_topology = 0;
2046
2047 cal_block = cal_utils_get_only_cal_block(this_adm.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002048 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302049 goto unlock;
2050
2051 pr_debug("%s: Sending cal_index %d\n", __func__, cal_index);
2052
2053 result = remap_cal_data(cal_block, cal_index);
2054 if (result) {
2055 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2056 __func__, cal_index);
2057 goto unlock;
2058 }
2059 atomic_set(&this_adm.mem_map_index, cal_index);
2060 atomic_set(&this_adm.mem_map_handles[cal_index],
2061 cal_block->map_data.q6map_handle);
2062
2063 if (cal_block->cal_data.size == 0) {
2064 pr_debug("%s: No ADM cal to send\n", __func__);
2065 goto unlock;
2066 }
2067
2068 adm_top.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2069 APR_HDR_LEN(20), APR_PKT_VER);
2070 adm_top.hdr.pkt_size = sizeof(adm_top);
2071 adm_top.hdr.src_svc = APR_SVC_ADM;
2072 adm_top.hdr.src_domain = APR_DOMAIN_APPS;
2073 adm_top.hdr.src_port = 0;
2074 adm_top.hdr.dest_svc = APR_SVC_ADM;
2075 adm_top.hdr.dest_domain = APR_DOMAIN_ADSP;
2076 adm_top.hdr.dest_port = 0;
2077 adm_top.hdr.token = 0;
2078 adm_top.hdr.opcode = ADM_CMD_ADD_TOPOLOGIES;
2079 adm_top.payload_addr_lsw = lower_32_bits(cal_block->cal_data.paddr);
2080 adm_top.payload_addr_msw = msm_audio_populate_upper_32_bits(
2081 cal_block->cal_data.paddr);
2082 adm_top.mem_map_handle = cal_block->map_data.q6map_handle;
2083 adm_top.payload_size = cal_block->cal_data.size;
2084
2085 atomic_set(&this_adm.adm_stat, -1);
2086 pr_debug("%s: Sending ADM_CMD_ADD_TOPOLOGIES payload = 0x%pK, size = %d\n",
2087 __func__, &cal_block->cal_data.paddr,
2088 adm_top.payload_size);
2089 result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_top);
2090 if (result < 0) {
2091 pr_err("%s: Set topologies failed payload size = %zd result %d\n",
2092 __func__, cal_block->cal_data.size, result);
2093 goto unlock;
2094 }
2095 /* Wait for the callback */
2096 result = wait_event_timeout(this_adm.adm_wait,
2097 atomic_read(&this_adm.adm_stat) >= 0,
2098 msecs_to_jiffies(TIMEOUT_MS));
2099 if (!result) {
2100 pr_err("%s: Set topologies timed out payload size = %zd\n",
2101 __func__, cal_block->cal_data.size);
2102 goto unlock;
2103 } else if (atomic_read(&this_adm.adm_stat) > 0) {
2104 pr_err("%s: DSP returned error[%s]\n",
2105 __func__, adsp_err_get_err_str(
2106 atomic_read(&this_adm.adm_stat)));
2107 result = adsp_err_get_lnx_err_code(
2108 atomic_read(&this_adm.adm_stat));
2109 goto unlock;
2110 }
2111unlock:
2112 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2113done:
2114 return;
2115}
2116
2117static int send_adm_cal_block(int port_id, int copp_idx,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002118 struct cal_block_data *cal_block, int perf_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302119{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002120 struct mem_mapping_hdr mem_hdr;
2121 int payload_size = 0;
2122 int port_idx = 0;
2123 int topology = 0;
2124 int result = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302125
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002126 pr_debug("%s: Port id 0x%x,\n", __func__, port_id);
2127
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302128 if (!cal_block) {
2129 pr_debug("%s: No ADM cal to send for port_id = 0x%x!\n",
2130 __func__, port_id);
2131 result = -EINVAL;
2132 goto done;
2133 }
2134 if (cal_block->cal_data.size <= 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002135 pr_debug("%s: No ADM cal sent for port_id = 0x%x!\n", __func__,
2136 port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302137 result = -EINVAL;
2138 goto done;
2139 }
2140
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002141 memset(&mem_hdr, 0, sizeof(mem_hdr));
2142 port_id = afe_convert_virtual_to_portid(port_id);
2143 port_idx = adm_validate_and_get_port_index(port_id);
2144 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
2145 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2146 return -EINVAL;
2147 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
2148 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
2149 return -EINVAL;
2150 }
2151
2152 topology = atomic_read(&this_adm.copp.topology[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302153 if (perf_mode == LEGACY_PCM_MODE &&
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002154 topology == DS2_ADM_COPP_TOPOLOGY_ID) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302155 pr_err("%s: perf_mode %d, topology 0x%x\n", __func__, perf_mode,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002156 topology);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302157 goto done;
2158 }
2159
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002160 mem_hdr.data_payload_addr_lsw =
2161 lower_32_bits(cal_block->cal_data.paddr);
2162 mem_hdr.data_payload_addr_msw =
2163 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
2164 mem_hdr.mem_map_handle = cal_block->map_data.q6map_handle;
2165 payload_size = cal_block->cal_data.size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302166
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002167 adm_set_pp_params(port_id, copp_idx, &mem_hdr, NULL, payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302168
2169done:
2170 return result;
2171}
2172
2173static struct cal_block_data *adm_find_cal_by_path(int cal_index, int path)
2174{
2175 struct list_head *ptr, *next;
2176 struct cal_block_data *cal_block = NULL;
2177 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2178 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2179
2180 pr_debug("%s:\n", __func__);
2181
2182 list_for_each_safe(ptr, next,
2183 &this_adm.cal_data[cal_index]->cal_blocks) {
2184
2185 cal_block = list_entry(ptr,
2186 struct cal_block_data, list);
2187
Vikram Panduranga770b8382017-09-27 12:17:36 -07002188 if (cal_utils_is_cal_stale(cal_block))
2189 continue;
2190
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302191 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002192 cal_index == ADM_LSM_AUDPROC_CAL ||
Ramlal Karra471fe912020-04-13 13:47:07 +05302193 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL ||
2194 cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302195 audproc_cal_info = cal_block->cal_info;
2196 if ((audproc_cal_info->path == path) &&
2197 (cal_block->cal_data.size > 0))
2198 return cal_block;
2199 } else if (cal_index == ADM_AUDVOL_CAL) {
2200 audvol_cal_info = cal_block->cal_info;
2201 if ((audvol_cal_info->path == path) &&
2202 (cal_block->cal_data.size > 0))
2203 return cal_block;
2204 }
2205 }
2206 pr_debug("%s: Can't find ADM cal for cal_index %d, path %d\n",
2207 __func__, cal_index, path);
2208 return NULL;
2209}
2210
2211static struct cal_block_data *adm_find_cal_by_app_type(int cal_index, int path,
2212 int app_type)
2213{
2214 struct list_head *ptr, *next;
2215 struct cal_block_data *cal_block = NULL;
2216 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2217 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2218
2219 pr_debug("%s\n", __func__);
2220
2221 list_for_each_safe(ptr, next,
2222 &this_adm.cal_data[cal_index]->cal_blocks) {
2223
2224 cal_block = list_entry(ptr,
2225 struct cal_block_data, list);
2226
Vikram Panduranga770b8382017-09-27 12:17:36 -07002227 if (cal_utils_is_cal_stale(cal_block))
2228 continue;
2229
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302230 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002231 cal_index == ADM_LSM_AUDPROC_CAL ||
Ramlal Karra471fe912020-04-13 13:47:07 +05302232 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL ||
2233 cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302234 audproc_cal_info = cal_block->cal_info;
2235 if ((audproc_cal_info->path == path) &&
2236 (audproc_cal_info->app_type == app_type) &&
2237 (cal_block->cal_data.size > 0))
2238 return cal_block;
2239 } else if (cal_index == ADM_AUDVOL_CAL) {
2240 audvol_cal_info = cal_block->cal_info;
2241 if ((audvol_cal_info->path == path) &&
2242 (audvol_cal_info->app_type == app_type) &&
2243 (cal_block->cal_data.size > 0))
2244 return cal_block;
2245 }
2246 }
2247 pr_debug("%s: Can't find ADM cali for cal_index %d, path %d, app %d, defaulting to search by path\n",
2248 __func__, cal_index, path, app_type);
2249 return adm_find_cal_by_path(cal_index, path);
2250}
2251
2252
2253static struct cal_block_data *adm_find_cal(int cal_index, int path,
2254 int app_type, int acdb_id,
2255 int sample_rate)
2256{
2257 struct list_head *ptr, *next;
2258 struct cal_block_data *cal_block = NULL;
2259 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2260 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2261
2262 pr_debug("%s:\n", __func__);
2263
2264 list_for_each_safe(ptr, next,
2265 &this_adm.cal_data[cal_index]->cal_blocks) {
2266
2267 cal_block = list_entry(ptr,
2268 struct cal_block_data, list);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002269 if (cal_utils_is_cal_stale(cal_block))
2270 continue;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302271
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302272 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002273 cal_index == ADM_LSM_AUDPROC_CAL ||
Ramlal Karra471fe912020-04-13 13:47:07 +05302274 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL||
2275 cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302276 audproc_cal_info = cal_block->cal_info;
2277 if ((audproc_cal_info->path == path) &&
2278 (audproc_cal_info->app_type == app_type) &&
2279 (audproc_cal_info->acdb_id == acdb_id) &&
2280 (audproc_cal_info->sample_rate == sample_rate) &&
2281 (cal_block->cal_data.size > 0))
2282 return cal_block;
2283 } else if (cal_index == ADM_AUDVOL_CAL) {
2284 audvol_cal_info = cal_block->cal_info;
2285 if ((audvol_cal_info->path == path) &&
2286 (audvol_cal_info->app_type == app_type) &&
2287 (audvol_cal_info->acdb_id == acdb_id) &&
2288 (cal_block->cal_data.size > 0))
2289 return cal_block;
2290 }
2291 }
2292 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",
2293 __func__, cal_index, path, app_type, acdb_id, sample_rate);
2294 return adm_find_cal_by_app_type(cal_index, path, app_type);
2295}
2296
2297static int adm_remap_and_send_cal_block(int cal_index, int port_id,
2298 int copp_idx, struct cal_block_data *cal_block, int perf_mode,
2299 int app_type, int acdb_id, int sample_rate)
2300{
2301 int ret = 0;
2302
2303 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
2304 ret = remap_cal_data(cal_block, cal_index);
2305 if (ret) {
2306 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2307 __func__, cal_index);
2308 goto done;
2309 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002310 ret = send_adm_cal_block(port_id, copp_idx, cal_block, perf_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302311 if (ret < 0)
2312 pr_debug("%s: No cal sent for cal_index %d, port_id = 0x%x! ret %d sample_rate %d\n",
2313 __func__, cal_index, port_id, ret, sample_rate);
2314done:
2315 return ret;
2316}
2317
2318static void send_adm_cal_type(int cal_index, int path, int port_id,
2319 int copp_idx, int perf_mode, int app_type,
2320 int acdb_id, int sample_rate)
2321{
2322 struct cal_block_data *cal_block = NULL;
2323 int ret;
2324
2325 pr_debug("%s: cal index %d\n", __func__, cal_index);
2326
2327 if (this_adm.cal_data[cal_index] == NULL) {
2328 pr_debug("%s: cal_index %d not allocated!\n",
2329 __func__, cal_index);
2330 goto done;
2331 }
2332
2333 mutex_lock(&this_adm.cal_data[cal_index]->lock);
2334 cal_block = adm_find_cal(cal_index, path, app_type, acdb_id,
2335 sample_rate);
2336 if (cal_block == NULL)
2337 goto unlock;
2338
2339 ret = adm_remap_and_send_cal_block(cal_index, port_id, copp_idx,
2340 cal_block, perf_mode, app_type, acdb_id, sample_rate);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002341
2342 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302343unlock:
2344 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2345done:
2346 return;
2347}
2348
2349static int get_cal_path(int path)
2350{
2351 if (path == 0x1)
2352 return RX_DEVICE;
2353 else
2354 return TX_DEVICE;
2355}
2356
2357static void send_adm_cal(int port_id, int copp_idx, int path, int perf_mode,
Aditya Bavanari5106b562018-01-08 13:16:32 +05302358 int app_type, int acdb_id, int sample_rate,
2359 int passthr_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302360{
2361 pr_debug("%s: port id 0x%x copp_idx %d\n", __func__, port_id, copp_idx);
2362
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002363 if (passthr_mode != LISTEN) {
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302364 send_adm_cal_type(ADM_AUDPROC_CAL, path, port_id, copp_idx,
2365 perf_mode, app_type, acdb_id, sample_rate);
Ramlal Karra471fe912020-04-13 13:47:07 +05302366 send_adm_cal_type(ADM_AUDPROC_PERSISTENT_CAL, path,
2367 port_id, copp_idx, perf_mode, app_type,
2368 acdb_id, sample_rate);
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002369 } else {
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302370 send_adm_cal_type(ADM_LSM_AUDPROC_CAL, path, port_id, copp_idx,
2371 perf_mode, app_type, acdb_id, sample_rate);
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002372
2373 send_adm_cal_type(ADM_LSM_AUDPROC_PERSISTENT_CAL, path,
2374 port_id, copp_idx, perf_mode, app_type,
2375 acdb_id, sample_rate);
2376 }
2377
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302378 send_adm_cal_type(ADM_AUDVOL_CAL, path, port_id, copp_idx, perf_mode,
2379 app_type, acdb_id, sample_rate);
2380}
2381
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302382/**
2383 * adm_connect_afe_port -
2384 * command to send ADM connect AFE port
2385 *
2386 * @mode: value of mode for ADM connect AFE
2387 * @session_id: session active to connect
2388 * @port_id: Port ID number
2389 *
2390 * Returns 0 on success or error on failure
2391 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302392int adm_connect_afe_port(int mode, int session_id, int port_id)
2393{
2394 struct adm_cmd_connect_afe_port_v5 cmd;
2395 int ret = 0;
2396 int port_idx, copp_idx = 0;
2397
2398 pr_debug("%s: port_id: 0x%x session id:%d mode:%d\n", __func__,
2399 port_id, session_id, mode);
2400
2401 port_id = afe_convert_virtual_to_portid(port_id);
2402 port_idx = adm_validate_and_get_port_index(port_id);
2403 if (port_idx < 0) {
2404 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2405 return -EINVAL;
2406 }
2407
2408 if (this_adm.apr == NULL) {
2409 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
2410 0xFFFFFFFF, &this_adm);
2411 if (this_adm.apr == NULL) {
2412 pr_err("%s: Unable to register ADM\n", __func__);
2413 ret = -ENODEV;
2414 return ret;
2415 }
2416 rtac_set_adm_handle(this_adm.apr);
2417 }
2418 pr_debug("%s: Port ID 0x%x, index %d\n", __func__, port_id, port_idx);
2419
2420 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2421 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2422 cmd.hdr.pkt_size = sizeof(cmd);
2423 cmd.hdr.src_svc = APR_SVC_ADM;
2424 cmd.hdr.src_domain = APR_DOMAIN_APPS;
2425 cmd.hdr.src_port = port_id;
2426 cmd.hdr.dest_svc = APR_SVC_ADM;
2427 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
2428 cmd.hdr.dest_port = 0; /* Ignored */
2429 cmd.hdr.token = port_idx << 16 | copp_idx;
2430 cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V5;
2431
2432 cmd.mode = mode;
2433 cmd.session_id = session_id;
2434 cmd.afe_port_id = port_id;
2435
2436 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
2437 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
2438 if (ret < 0) {
2439 pr_err("%s: ADM enable for port_id: 0x%x failed ret %d\n",
2440 __func__, port_id, ret);
2441 ret = -EINVAL;
2442 goto fail_cmd;
2443 }
2444 /* Wait for the callback with copp id */
2445 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
2446 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
2447 msecs_to_jiffies(TIMEOUT_MS));
2448 if (!ret) {
2449 pr_err("%s: ADM connect timedout for port_id: 0x%x\n",
2450 __func__, port_id);
2451 ret = -EINVAL;
2452 goto fail_cmd;
2453 } else if (atomic_read(&this_adm.copp.stat
2454 [port_idx][copp_idx]) > 0) {
2455 pr_err("%s: DSP returned error[%s]\n",
2456 __func__, adsp_err_get_err_str(
2457 atomic_read(&this_adm.copp.stat
2458 [port_idx][copp_idx])));
2459 ret = adsp_err_get_lnx_err_code(
2460 atomic_read(&this_adm.copp.stat
2461 [port_idx][copp_idx]));
2462 goto fail_cmd;
2463 }
2464 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
2465 return 0;
2466
2467fail_cmd:
2468
2469 return ret;
2470}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302471EXPORT_SYMBOL(adm_connect_afe_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302472
2473int adm_arrange_mch_map(struct adm_cmd_device_open_v5 *open, int path,
Rohit kumar2054b692019-02-01 18:01:12 +05302474 int channel_mode, int port_idx)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302475{
2476 int rc = 0, idx;
2477
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -07002478 pr_debug("%s: channel mode %d", __func__, channel_mode);
2479
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302480 memset(open->dev_channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
2481 switch (path) {
2482 case ADM_PATH_PLAYBACK:
2483 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2484 break;
2485 case ADM_PATH_LIVE_REC:
2486 case ADM_PATH_NONLIVE_REC:
2487 idx = ADM_MCH_MAP_IDX_REC;
2488 break;
2489 default:
2490 goto non_mch_path;
2491 };
Rohit kumar2054b692019-02-01 18:01:12 +05302492
2493 if ((open->dev_num_channel > 2) &&
2494 (port_channel_map[port_idx].set_channel_map ||
2495 multi_ch_maps[idx].set_channel_map)) {
2496 if (port_channel_map[port_idx].set_channel_map)
2497 memcpy(open->dev_channel_mapping,
2498 port_channel_map[port_idx].channel_mapping,
2499 PCM_FORMAT_MAX_NUM_CHANNEL);
2500 else
2501 memcpy(open->dev_channel_mapping,
2502 multi_ch_maps[idx].channel_mapping,
2503 PCM_FORMAT_MAX_NUM_CHANNEL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302504 } else {
2505 if (channel_mode == 1) {
2506 open->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2507 } else if (channel_mode == 2) {
2508 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2509 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2510 } else if (channel_mode == 3) {
2511 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2512 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2513 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2514 } else if (channel_mode == 4) {
2515 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2516 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2517 open->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2518 open->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2519 } else if (channel_mode == 5) {
2520 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2521 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2522 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2523 open->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2524 open->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2525 } else if (channel_mode == 6) {
2526 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2527 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2528 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2529 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2530 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2531 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2532 } else if (channel_mode == 7) {
2533 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2534 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2535 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2536 open->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
2537 open->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2538 open->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2539 open->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2540 } else if (channel_mode == 8) {
2541 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2542 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2543 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2544 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2545 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2546 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2547 open->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2548 open->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2549 } else {
2550 pr_err("%s: invalid num_chan %d\n", __func__,
2551 channel_mode);
2552 rc = -EINVAL;
2553 goto inval_ch_mod;
2554 }
2555 }
2556
2557non_mch_path:
2558inval_ch_mod:
2559 return rc;
2560}
2561
2562int adm_arrange_mch_ep2_map(struct adm_cmd_device_open_v6 *open_v6,
2563 int channel_mode)
2564{
2565 int rc = 0;
2566
2567 memset(open_v6->dev_channel_mapping_eid2, 0,
2568 PCM_FORMAT_MAX_NUM_CHANNEL);
2569
2570 if (channel_mode == 1) {
2571 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FC;
2572 } else if (channel_mode == 2) {
2573 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2574 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2575 } else if (channel_mode == 3) {
2576 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2577 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2578 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2579 } else if (channel_mode == 4) {
2580 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2581 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2582 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LS;
2583 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_RS;
2584 } else if (channel_mode == 5) {
2585 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2586 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2587 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2588 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_LS;
2589 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_RS;
2590 } else if (channel_mode == 6) {
2591 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2592 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2593 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
2594 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2595 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2596 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2597 } else if (channel_mode == 8) {
2598 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2599 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2600 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
2601 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2602 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2603 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2604 open_v6->dev_channel_mapping_eid2[6] = PCM_CHANNEL_LB;
2605 open_v6->dev_channel_mapping_eid2[7] = PCM_CHANNEL_RB;
2606 } else {
2607 pr_err("%s: invalid num_chan %d\n", __func__,
2608 channel_mode);
2609 rc = -EINVAL;
2610 }
2611
2612 return rc;
2613}
2614
Dieter Luecking50c55352018-09-28 14:29:17 +02002615static int adm_arrange_mch_map_v8(
2616 struct adm_device_endpoint_payload *ep_payload,
Rohit kumar2054b692019-02-01 18:01:12 +05302617 int path, int channel_mode, int port_idx)
Dieter Luecking50c55352018-09-28 14:29:17 +02002618{
2619 int rc = 0, idx;
2620
2621 memset(ep_payload->dev_channel_mapping,
2622 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2623 switch (path) {
2624 case ADM_PATH_PLAYBACK:
2625 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2626 break;
2627 case ADM_PATH_LIVE_REC:
2628 case ADM_PATH_NONLIVE_REC:
2629 idx = ADM_MCH_MAP_IDX_REC;
2630 break;
2631 default:
2632 goto non_mch_path;
2633 };
2634
2635 if ((ep_payload->dev_num_channel > 2) &&
Rohit kumar2054b692019-02-01 18:01:12 +05302636 (port_channel_map[port_idx].set_channel_map ||
2637 multi_ch_maps[idx].set_channel_map)) {
2638 if (port_channel_map[port_idx].set_channel_map)
2639 memcpy(ep_payload->dev_channel_mapping,
2640 port_channel_map[port_idx].channel_mapping,
2641 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2642 else
2643 memcpy(ep_payload->dev_channel_mapping,
2644 multi_ch_maps[idx].channel_mapping,
2645 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Dieter Luecking50c55352018-09-28 14:29:17 +02002646 } else {
2647 if (channel_mode == 1) {
2648 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2649 } else if (channel_mode == 2) {
2650 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2651 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2652 } else if (channel_mode == 3) {
2653 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2654 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2655 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2656 } else if (channel_mode == 4) {
2657 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2658 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2659 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2660 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2661 } else if (channel_mode == 5) {
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_FC;
2665 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2666 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2667 } else if (channel_mode == 6) {
2668 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2669 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2670 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2671 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2672 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2673 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2674 } else if (channel_mode == 7) {
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_FC;
2678 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
2679 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2680 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2681 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2682 } else if (channel_mode == 8) {
2683 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2684 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2685 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2686 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2687 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2688 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2689 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2690 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2691 } else if (channel_mode == 10) {
2692 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2693 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2694 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2695 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2696 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2697 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2698 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2699 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2700 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2701 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2702 } else if (channel_mode == 12) {
2703 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2704 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2705 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2706 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2707 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2708 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2709 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2710 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2711 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2712 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2713 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2714 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
Chaithanya Krishna Bacharaju3dd8fdf2019-05-02 12:14:37 +05302715 } else if (channel_mode == 14) {
2716 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2717 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2718 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2719 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2720 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2721 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2722 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2723 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2724 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2725 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2726 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2727 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2728 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2729 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
Dieter Luecking50c55352018-09-28 14:29:17 +02002730 } else if (channel_mode == 16) {
2731 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2732 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2733 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2734 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2735 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2736 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2737 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2738 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2739 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2740 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2741 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2742 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2743 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2744 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2745 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2746 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
Cong Tang04a6cfa2019-02-26 15:08:55 +08002747 } else if (channel_mode == 32) {
2748 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2749 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2750 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2751 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2752 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2753 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2754 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2755 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2756 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
2757 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
2758 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2759 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2760 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2761 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2762 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2763 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
2764 ep_payload->dev_channel_mapping[16] = PCM_CHANNEL_LFE2;
2765 ep_payload->dev_channel_mapping[17] = PCM_CHANNEL_SL;
2766 ep_payload->dev_channel_mapping[18] = PCM_CHANNEL_SR;
2767 ep_payload->dev_channel_mapping[19] = PCM_CHANNEL_TFL;
2768 ep_payload->dev_channel_mapping[20] = PCM_CHANNEL_TFR;
2769 ep_payload->dev_channel_mapping[21] = PCM_CHANNEL_TC;
2770 ep_payload->dev_channel_mapping[22] = PCM_CHANNEL_TBL;
2771 ep_payload->dev_channel_mapping[23] = PCM_CHANNEL_TBR;
2772 ep_payload->dev_channel_mapping[24] = PCM_CHANNEL_TSL;
2773 ep_payload->dev_channel_mapping[25] = PCM_CHANNEL_TSR;
2774 ep_payload->dev_channel_mapping[26] = PCM_CHANNEL_TBC;
2775 ep_payload->dev_channel_mapping[27] = PCM_CHANNEL_BFC;
2776 ep_payload->dev_channel_mapping[28] = PCM_CHANNEL_BFL;
2777 ep_payload->dev_channel_mapping[29] = PCM_CHANNEL_BFR;
2778 ep_payload->dev_channel_mapping[30] = PCM_CHANNEL_LW;
2779 ep_payload->dev_channel_mapping[31] = PCM_CHANNEL_RW;
Dieter Luecking50c55352018-09-28 14:29:17 +02002780 } else {
2781 pr_err("%s: invalid num_chan %d\n", __func__,
2782 channel_mode);
2783 rc = -EINVAL;
2784 goto inval_ch_mod;
2785 }
2786 }
2787
2788non_mch_path:
2789inval_ch_mod:
2790 return rc;
2791}
2792
2793static int adm_arrange_mch_ep2_map_v8(
2794 struct adm_device_endpoint_payload *ep_payload,
2795 int channel_mode)
2796{
2797 int rc = 0;
2798
2799 memset(ep_payload->dev_channel_mapping, 0,
2800 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2801
2802 if (channel_mode == 1) {
2803 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2804 } else if (channel_mode == 2) {
2805 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2806 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2807 } else if (channel_mode == 3) {
2808 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2809 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2810 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2811 } else if (channel_mode == 4) {
2812 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2813 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2814 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2815 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2816 } else if (channel_mode == 5) {
2817 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2818 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2819 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2820 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2821 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2822 } else if (channel_mode == 6) {
2823 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2824 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2825 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2826 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2827 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2828 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2829 } else if (channel_mode == 8) {
2830 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2831 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2832 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2833 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2834 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2835 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2836 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2837 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2838 } else if (channel_mode == 10) {
2839 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2840 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2841 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2842 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2843 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2844 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2845 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2846 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2847 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
Ralf Herzfb81b6e2018-12-12 10:36:11 +01002848 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
Dieter Luecking50c55352018-09-28 14:29:17 +02002849 } else if (channel_mode == 12) {
2850 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2851 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2852 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2853 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2854 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2855 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2856 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2857 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2858 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2859 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2860 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2861 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2862 } else if (channel_mode == 16) {
2863 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2864 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2865 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2866 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2867 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2868 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2869 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2870 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2871 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
Ralf Herzfb81b6e2018-12-12 10:36:11 +01002872 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
Dieter Luecking50c55352018-09-28 14:29:17 +02002873 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2874 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2875 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2876 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2877 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2878 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
Cong Tang04a6cfa2019-02-26 15:08:55 +08002879 } else if (channel_mode == 32) {
2880 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2881 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2882 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2883 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2884 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2885 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2886 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2887 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2888 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
2889 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
2890 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2891 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2892 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2893 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2894 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2895 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
2896 ep_payload->dev_channel_mapping[16] = PCM_CHANNEL_LFE2;
2897 ep_payload->dev_channel_mapping[17] = PCM_CHANNEL_SL;
2898 ep_payload->dev_channel_mapping[18] = PCM_CHANNEL_SR;
2899 ep_payload->dev_channel_mapping[19] = PCM_CHANNEL_TFL;
2900 ep_payload->dev_channel_mapping[20] = PCM_CHANNEL_TFR;
2901 ep_payload->dev_channel_mapping[21] = PCM_CHANNEL_TC;
2902 ep_payload->dev_channel_mapping[22] = PCM_CHANNEL_TBL;
2903 ep_payload->dev_channel_mapping[23] = PCM_CHANNEL_TBR;
2904 ep_payload->dev_channel_mapping[24] = PCM_CHANNEL_TSL;
2905 ep_payload->dev_channel_mapping[25] = PCM_CHANNEL_TSR;
2906 ep_payload->dev_channel_mapping[26] = PCM_CHANNEL_TBC;
2907 ep_payload->dev_channel_mapping[27] = PCM_CHANNEL_BFC;
2908 ep_payload->dev_channel_mapping[28] = PCM_CHANNEL_BFL;
2909 ep_payload->dev_channel_mapping[29] = PCM_CHANNEL_BFR;
2910 ep_payload->dev_channel_mapping[30] = PCM_CHANNEL_LW;
2911 ep_payload->dev_channel_mapping[31] = PCM_CHANNEL_RW;
Dieter Luecking50c55352018-09-28 14:29:17 +02002912 } else {
2913 pr_err("%s: invalid num_chan %d\n", __func__,
2914 channel_mode);
2915 rc = -EINVAL;
2916 }
2917
2918 return rc;
2919}
Dhananjay Kumar43034392019-01-16 21:57:58 +05302920
2921static int adm_copp_set_ec_ref_mfc_cfg(int port_id, int copp_idx,
2922 int sample_rate, int bps,
2923 int in_channels, int out_channels)
2924{
2925 struct audproc_mfc_param_media_fmt mfc_cfg;
2926 struct param_hdr_v3 param_hdr;
2927 u16 *chmixer_params = NULL;
2928 int rc = 0, i = 0, j = 0, param_index = 0, param_size = 0;
2929 struct adm_device_endpoint_payload ep_payload = {0, 0, 0, {0}};
2930
2931 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
2932 memset(&ep_payload, 0, sizeof(ep_payload));
2933 memset(&param_hdr, 0, sizeof(param_hdr));
2934
2935 param_hdr.module_id = AUDPROC_MODULE_ID_MFC_EC_REF;
2936 param_hdr.instance_id = INSTANCE_ID_0;
2937
2938 pr_debug("%s: port_id %d copp_idx %d SR %d, BW %d in_ch %d out_ch %d\n",
2939 __func__, port_id, copp_idx, sample_rate,
2940 bps, in_channels, out_channels);
2941
Dhananjay Kumar3d61b362019-03-01 15:47:56 +05302942 if (out_channels <= 0 || out_channels > AUDPROC_MFC_OUT_CHANNELS_MAX) {
2943 pr_err("%s: unsupported out channels=%d\n", __func__, out_channels);
2944 return -EINVAL;
2945 }
2946
Dhananjay Kumar43034392019-01-16 21:57:58 +05302947 /* 1. Update Media Format */
2948 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
2949 param_hdr.param_size = sizeof(mfc_cfg);
2950
2951 mfc_cfg.sampling_rate = sample_rate;
2952 mfc_cfg.bits_per_sample = bps;
2953 mfc_cfg.num_channels = out_channels;
2954
2955 ep_payload.dev_num_channel = out_channels;
2956 rc = adm_arrange_mch_ep2_map_v8(&ep_payload, out_channels);
2957 if (rc < 0) {
2958 pr_err("%s: unable to get map for out channels=%d\n",
2959 __func__, out_channels);
2960 return -EINVAL;
2961 }
2962
2963 for (i = 0; i < out_channels; i++)
2964 mfc_cfg.channel_type[i] = (uint16_t) ep_payload.dev_channel_mapping[i];
2965
2966
2967 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx,
2968 param_hdr, (uint8_t *) &mfc_cfg);
2969 if (rc) {
2970 pr_err("%s: Failed to set media format, err %d\n", __func__, rc);
2971 return rc;
2972 }
2973
2974 /* 2. Send Channel Mixer params */
2975 param_size = 2 * (4 + out_channels + in_channels + (out_channels * in_channels));
2976 param_size = round_up(param_size, 4);
2977 param_hdr.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
2978 param_hdr.param_size = param_size;
2979
2980 pr_debug("%s: chmixer param sz = %d\n", __func__, param_size);
2981 chmixer_params = kzalloc(param_size, GFP_KERNEL);
2982 if (!chmixer_params) {
2983 return -ENOMEM;
2984 }
2985 param_index = 2; /* param[0] and [1] represents chmixer rule(always 0) */
2986 chmixer_params[param_index++] = out_channels;
2987 chmixer_params[param_index++] = in_channels;
2988
2989 /* output channel map is same as one set in media format */
2990 for (i = 0; i < out_channels; i++)
2991 chmixer_params[param_index++] = ep_payload.dev_channel_mapping[i];
2992
2993 /* input channel map should be same as one set for ep2 during copp open */
2994 ep_payload.dev_num_channel = in_channels;
2995 rc = adm_arrange_mch_ep2_map_v8(&ep_payload, in_channels);
2996 if (rc < 0) {
2997 pr_err("%s: unable to get in channal map\n", __func__);
2998 goto exit;
2999 }
3000 for (i = 0; i < in_channels; i++)
3001 chmixer_params[param_index++] = ep_payload.dev_channel_mapping[i];
3002
3003 for (i = 0; i < out_channels; i++)
3004 for (j = 0; j < in_channels; j++)
3005 chmixer_params[param_index++] = this_adm.ec_ref_chmixer_weights[i][j];
3006
3007 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx,
3008 param_hdr, (uint8_t *) chmixer_params);
3009 if (rc)
3010 pr_err("%s: Failed to set chmixer params, err %d\n", __func__, rc);
3011
3012exit:
3013 kfree(chmixer_params);
3014 return rc;
3015}
3016
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303017/**
3018 * adm_open -
3019 * command to send ADM open
3020 *
3021 * @port_id: port id number
3022 * @path: direction or ADM path type
3023 * @rate: sample rate of session
3024 * @channel_mode: number of channels set
3025 * @topology: topology active for this session
3026 * @perf_mode: performance mode like LL/ULL/..
3027 * @bit_width: bit width to set for copp
3028 * @app_type: App type used for this session
3029 * @acdb_id: ACDB ID of this device
Surendar Karkae7507512018-07-20 15:46:54 +05303030 * @session_type: type of session
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303031 *
3032 * Returns 0 on success or error on failure
3033 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303034int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
Surendar Karkae7507512018-07-20 15:46:54 +05303035 int perf_mode, uint16_t bit_width, int app_type, int acdb_id,
Sanjana B61518cf2019-11-12 23:09:27 +05303036 int session_type, uint32_t passthr_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303037{
3038 struct adm_cmd_device_open_v5 open;
3039 struct adm_cmd_device_open_v6 open_v6;
Dieter Luecking50c55352018-09-28 14:29:17 +02003040 struct adm_cmd_device_open_v8 open_v8;
3041 struct adm_device_endpoint_payload ep1_payload;
3042 struct adm_device_endpoint_payload ep2_payload;
3043 int ep1_payload_size = 0;
3044 int ep2_payload_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303045 int ret = 0;
Asish Bhattacharya34504582017-08-08 12:55:01 +05303046 int port_idx, flags;
3047 int copp_idx = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303048 int tmp_port = q6audio_get_port_id(port_id);
Dieter Luecking50c55352018-09-28 14:29:17 +02003049 void *adm_params = NULL;
3050 int param_size;
Dhananjay Kumar43034392019-01-16 21:57:58 +05303051 int num_ec_ref_rx_chans = this_adm.num_ec_ref_rx_chans;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303052
3053 pr_debug("%s:port %#x path:%d rate:%d mode:%d perf_mode:%d,topo_id %d\n",
3054 __func__, port_id, path, rate, channel_mode, perf_mode,
3055 topology);
3056
3057 port_id = q6audio_convert_virtual_to_portid(port_id);
3058 port_idx = adm_validate_and_get_port_index(port_id);
3059 if (port_idx < 0) {
3060 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
3061 return -EINVAL;
3062 }
Dieter Luecking50c55352018-09-28 14:29:17 +02003063 if (channel_mode < 0 || channel_mode > 32) {
3064 pr_err("%s: Invalid channel number 0x%x\n",
3065 __func__, channel_mode);
3066 return -EINVAL;
3067 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303068
3069 if (this_adm.apr == NULL) {
3070 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
3071 0xFFFFFFFF, &this_adm);
3072 if (this_adm.apr == NULL) {
3073 pr_err("%s: Unable to register ADM\n", __func__);
3074 return -ENODEV;
3075 }
3076 rtac_set_adm_handle(this_adm.apr);
3077 }
3078
3079 if (perf_mode == ULL_POST_PROCESSING_PCM_MODE) {
3080 flags = ADM_ULL_POST_PROCESSING_DEVICE_SESSION;
3081 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
3082 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
3083 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
3084 topology = DEFAULT_COPP_TOPOLOGY;
3085 } else if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
3086 flags = ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
3087 topology = NULL_COPP_TOPOLOGY;
3088 rate = ULL_SUPPORTED_SAMPLE_RATE;
3089 bit_width = ULL_SUPPORTED_BITS_PER_SAMPLE;
3090 } else if (perf_mode == LOW_LATENCY_PCM_MODE) {
3091 flags = ADM_LOW_LATENCY_DEVICE_SESSION;
3092 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
3093 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
3094 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
3095 topology = DEFAULT_COPP_TOPOLOGY;
3096 } else {
3097 if ((path == ADM_PATH_COMPRESSED_RX) ||
3098 (path == ADM_PATH_COMPRESSED_TX))
3099 flags = 0;
3100 else
3101 flags = ADM_LEGACY_DEVICE_SESSION;
3102 }
3103
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05303104 if ((topology == VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY) ||
kunleiz1529b552019-01-24 17:15:49 +08003105 (topology == VPM_TX_DM_FLUENCE_EF_COPP_TOPOLOGY)) {
3106 if ((rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_8K) &&
3107 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_16K) &&
3108 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_32K) &&
3109 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_48K))
Yunfei Zhangaf3faf22019-09-15 15:50:39 +08003110 rate = 16000;
3111 }
3112 if ((topology == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY) ||
3113 (topology == VPM_TX_DM_RFECNS_COPP_TOPOLOGY)) {
3114 if ((rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_8K) &&
3115 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_16K) &&
3116 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_32K))
3117 rate = 16000;
kunleiz1529b552019-01-24 17:15:49 +08003118 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303119
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08003120 if (topology == FFECNS_TOPOLOGY) {
3121 this_adm.ffecns_port_id = port_id;
3122 pr_debug("%s: ffecns port id =%x\n", __func__,
3123 this_adm.ffecns_port_id);
3124 }
3125
Kunlei Zhangd3443892020-05-27 17:58:10 +08003126 if (topology == VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY ||
3127 topology == VPM_TX_VOICE_FLUENCE_SM_COPP_TOPOLOGY)
kunleizc0cd19e2018-10-18 17:11:35 +08003128 channel_mode = 1;
3129
Asish Bhattacharya34504582017-08-08 12:55:01 +05303130 /*
3131 * Routing driver reuses the same adm for streams with the same
3132 * app_type, sample_rate etc.
3133 * This isn't allowed for ULL streams as per the DSP interface
3134 */
3135 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE)
3136 copp_idx = adm_get_idx_if_copp_exists(port_idx, topology,
3137 perf_mode,
3138 rate, bit_width,
Surendar Karkae7507512018-07-20 15:46:54 +05303139 app_type, session_type);
Asish Bhattacharya34504582017-08-08 12:55:01 +05303140
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303141 if (copp_idx < 0) {
3142 copp_idx = adm_get_next_available_copp(port_idx);
3143 if (copp_idx >= MAX_COPPS_PER_PORT) {
3144 pr_err("%s: exceeded copp id %d\n",
3145 __func__, copp_idx);
3146 return -EINVAL;
3147 }
3148 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
3149 atomic_set(&this_adm.copp.topology[port_idx][copp_idx],
3150 topology);
3151 atomic_set(&this_adm.copp.mode[port_idx][copp_idx],
3152 perf_mode);
3153 atomic_set(&this_adm.copp.rate[port_idx][copp_idx],
3154 rate);
3155 atomic_set(&this_adm.copp.channels[port_idx][copp_idx],
3156 channel_mode);
3157 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx],
3158 bit_width);
3159 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx],
3160 app_type);
3161 atomic_set(&this_adm.copp.acdb_id[port_idx][copp_idx],
3162 acdb_id);
Surendar Karkae7507512018-07-20 15:46:54 +05303163 atomic_set(&this_adm.copp.session_type[port_idx][copp_idx],
3164 session_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303165 set_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3166 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
3167 if ((path != ADM_PATH_COMPRESSED_RX) &&
3168 (path != ADM_PATH_COMPRESSED_TX))
3169 send_adm_custom_topology();
3170 }
3171
3172 if (this_adm.copp.adm_delay[port_idx][copp_idx] &&
3173 perf_mode == LEGACY_PCM_MODE) {
3174 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
3175 1);
3176 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
3177 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
3178 }
3179
3180 /* Create a COPP if port id are not enabled */
3181 if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) {
3182 pr_debug("%s: open ADM: port_idx: %d, copp_idx: %d\n", __func__,
3183 port_idx, copp_idx);
Dieter Luecking50c55352018-09-28 14:29:17 +02003184 if ((topology == SRS_TRUMEDIA_TOPOLOGY_ID) &&
3185 perf_mode == LEGACY_PCM_MODE) {
3186 int res;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303187
Dieter Luecking50c55352018-09-28 14:29:17 +02003188 atomic_set(&this_adm.mem_map_index, ADM_SRS_TRUMEDIA);
3189 msm_dts_srs_tm_ion_memmap(&this_adm.outband_memmap);
3190 res = adm_memory_map_regions(
3191 &this_adm.outband_memmap.paddr, 0,
3192 (uint32_t *)&this_adm.outband_memmap.size, 1);
3193 if (res < 0) {
3194 pr_err("%s: SRS adm_memory_map_regions failed! addr = 0x%pK, size = %d\n",
3195 __func__,
3196 (void *)this_adm.outband_memmap.paddr,
3197 (uint32_t)this_adm.outband_memmap.size);
3198 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303199 }
3200
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303201
Mangesh Kunchamwar9f295c72018-10-08 18:20:41 +05303202 if ((q6core_get_avcs_api_version_per_service(
Dieter Luecking50c55352018-09-28 14:29:17 +02003203 APRV2_IDS_SERVICE_ID_ADSP_ADM_V) >=
Dieter Luecking9fb7c8c2019-03-06 13:31:09 +01003204 ADSP_ADM_API_VERSION_V3)) {
Dieter Luecking50c55352018-09-28 14:29:17 +02003205 memset(&open_v8, 0, sizeof(open_v8));
3206 memset(&ep1_payload, 0, sizeof(ep1_payload));
3207 memset(&ep2_payload, 0, sizeof(ep2_payload));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303208
Dieter Luecking50c55352018-09-28 14:29:17 +02003209 open_v8.hdr.hdr_field = APR_HDR_FIELD(
3210 APR_MSG_TYPE_SEQ_CMD,
3211 APR_HDR_LEN(APR_HDR_SIZE),
3212 APR_PKT_VER);
3213 open_v8.hdr.src_svc = APR_SVC_ADM;
3214 open_v8.hdr.src_domain = APR_DOMAIN_APPS;
3215 open_v8.hdr.src_port = tmp_port;
3216 open_v8.hdr.dest_svc = APR_SVC_ADM;
3217 open_v8.hdr.dest_domain = APR_DOMAIN_ADSP;
3218 open_v8.hdr.dest_port = tmp_port;
3219 open_v8.hdr.token = port_idx << 16 | copp_idx;
3220 open_v8.hdr.opcode = ADM_CMD_DEVICE_OPEN_V8;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303221
Dieter Luecking50c55352018-09-28 14:29:17 +02003222 if (this_adm.native_mode != 0) {
3223 open_v8.flags = flags |
3224 (this_adm.native_mode << 11);
3225 this_adm.native_mode = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303226 } else {
Dieter Luecking50c55352018-09-28 14:29:17 +02003227 open_v8.flags = flags;
3228 }
3229 open_v8.mode_of_operation = path;
3230 open_v8.endpoint_id_1 = tmp_port;
3231 open_v8.endpoint_id_2 = 0xFFFF;
3232 open_v8.endpoint_id_3 = 0xFFFF;
3233
Chaithanya Krishna Bacharaju8b0abba2019-01-11 19:35:54 +05303234 if (((this_adm.ec_ref_rx & AFE_PORT_INVALID) !=
3235 AFE_PORT_INVALID) &&
3236 (path != ADM_PATH_PLAYBACK)) {
Surendar Karkade79a062018-12-05 14:18:55 +05303237 if (this_adm.num_ec_ref_rx_chans != 0) {
3238 open_v8.endpoint_id_2 =
3239 this_adm.ec_ref_rx;
Chaithanya Krishna Bacharaju757f0d22019-06-21 13:10:22 +05303240 this_adm.ec_ref_rx = AFE_PORT_INVALID;
Surendar Karkade79a062018-12-05 14:18:55 +05303241 } else {
3242 pr_err("%s: EC channels not set %d\n",
3243 __func__,
3244 this_adm.num_ec_ref_rx_chans);
3245 return -EINVAL;
3246 }
Dieter Luecking41620832018-11-14 15:11:47 +01003247 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303248
Dieter Luecking50c55352018-09-28 14:29:17 +02003249 open_v8.topology_id = topology;
Sanjana B61518cf2019-11-12 23:09:27 +05303250 open_v8.compressed_data_type = 0;
3251 if (passthr_mode == COMPRESSED_PASSTHROUGH_DSD)
3252 open_v8.compressed_data_type = 1;
Dieter Luecking50c55352018-09-28 14:29:17 +02003253
3254 /* variable endpoint payload */
3255 ep1_payload.dev_num_channel = channel_mode & 0x00FF;
3256 ep1_payload.bit_width = bit_width;
3257 ep1_payload.sample_rate = rate;
3258 ret = adm_arrange_mch_map_v8(&ep1_payload, path,
Rohit kumar2054b692019-02-01 18:01:12 +05303259 channel_mode, port_idx);
Dieter Luecking50c55352018-09-28 14:29:17 +02003260 if (ret)
3261 return ret;
3262
3263 pr_debug("%s: port_id=0x%x %x %x topology_id=0x%X flags %x ref_ch %x\n",
3264 __func__, open_v8.endpoint_id_1,
3265 open_v8.endpoint_id_2,
3266 open_v8.endpoint_id_3,
3267 open_v8.topology_id,
3268 open_v8.flags,
3269 this_adm.num_ec_ref_rx_chans);
3270
3271 ep1_payload_size = 8 +
3272 roundup(ep1_payload.dev_num_channel, 4);
3273 param_size = sizeof(struct adm_cmd_device_open_v8)
3274 + ep1_payload_size;
3275 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3276
Dieter Luecking27c57722018-10-05 16:45:41 +02003277 if ((this_adm.num_ec_ref_rx_chans != 0)
3278 && (path != ADM_PATH_PLAYBACK)
Dieter Luecking50c55352018-09-28 14:29:17 +02003279 && (open_v8.endpoint_id_2 != 0xFFFF)) {
3280 ep2_payload.dev_num_channel =
3281 this_adm.num_ec_ref_rx_chans;
Dieter Luecking50c55352018-09-28 14:29:17 +02003282
3283 if (this_adm.ec_ref_rx_bit_width != 0) {
3284 ep2_payload.bit_width =
3285 this_adm.ec_ref_rx_bit_width;
Dieter Luecking50c55352018-09-28 14:29:17 +02003286 } else {
3287 ep2_payload.bit_width = bit_width;
3288 }
3289
3290 if (this_adm.ec_ref_rx_sampling_rate != 0) {
3291 ep2_payload.sample_rate =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303292 this_adm.ec_ref_rx_sampling_rate;
Dieter Luecking50c55352018-09-28 14:29:17 +02003293 } else {
3294 ep2_payload.sample_rate = rate;
3295 }
3296
3297 pr_debug("%s: adm open_v8 eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
3298 __func__,
3299 ep2_payload.dev_num_channel,
3300 ep2_payload.bit_width,
3301 ep2_payload.sample_rate);
3302
3303 ret = adm_arrange_mch_ep2_map_v8(&ep2_payload,
3304 ep2_payload.dev_num_channel);
3305
3306 if (ret)
3307 return ret;
3308 ep2_payload_size = 8 +
3309 roundup(ep2_payload.dev_num_channel, 4);
3310 param_size += ep2_payload_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303311 }
3312
Dieter Luecking27c57722018-10-05 16:45:41 +02003313 open_v8.hdr.pkt_size = param_size;
Dieter Luecking50c55352018-09-28 14:29:17 +02003314 adm_params = kzalloc(param_size, GFP_KERNEL);
3315 if (!adm_params)
3316 return -ENOMEM;
Dieter Luecking50c55352018-09-28 14:29:17 +02003317 memcpy(adm_params, &open_v8, sizeof(open_v8));
3318 memcpy(adm_params + sizeof(open_v8),
3319 (void *)&ep1_payload,
3320 ep1_payload_size);
Dieter Luecking27c57722018-10-05 16:45:41 +02003321
3322 if ((this_adm.num_ec_ref_rx_chans != 0)
3323 && (path != ADM_PATH_PLAYBACK)
3324 && (open_v8.endpoint_id_2 != 0xFFFF)) {
3325 memcpy(adm_params + sizeof(open_v8)
3326 + ep1_payload_size,
3327 (void *)&ep2_payload,
3328 ep2_payload_size);
3329 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303330
Dieter Luecking50c55352018-09-28 14:29:17 +02003331 ret = apr_send_pkt(this_adm.apr,
3332 (uint32_t *)adm_params);
3333 if (ret < 0) {
3334 pr_err("%s: port_id: 0x%x for[0x%x] failed %d for open_v8\n",
3335 __func__, tmp_port, port_id, ret);
3336 return -EINVAL;
3337 }
3338 kfree(adm_params);
3339 } else {
3340
3341 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3342 APR_HDR_LEN(APR_HDR_SIZE),
3343 APR_PKT_VER);
3344 open.hdr.pkt_size = sizeof(open);
3345 open.hdr.src_svc = APR_SVC_ADM;
3346 open.hdr.src_domain = APR_DOMAIN_APPS;
3347 open.hdr.src_port = tmp_port;
3348 open.hdr.dest_svc = APR_SVC_ADM;
3349 open.hdr.dest_domain = APR_DOMAIN_ADSP;
3350 open.hdr.dest_port = tmp_port;
3351 open.hdr.token = port_idx << 16 | copp_idx;
3352 open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
3353 open.flags = flags;
3354 open.mode_of_operation = path;
3355 open.endpoint_id_1 = tmp_port;
3356 open.endpoint_id_2 = 0xFFFF;
3357
Surendar Karkae7507512018-07-20 15:46:54 +05303358 if (this_adm.ec_ref_rx && (path != 1) &&
3359 (afe_get_port_type(tmp_port) == MSM_AFE_PORT_TYPE_TX)) {
Dieter Luecking50c55352018-09-28 14:29:17 +02003360 open.endpoint_id_2 = this_adm.ec_ref_rx;
Dieter Luecking50c55352018-09-28 14:29:17 +02003361 }
3362
3363 open.topology_id = topology;
3364
3365 open.dev_num_channel = channel_mode & 0x00FF;
3366 open.bit_width = bit_width;
3367 WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
3368 (rate != ULL_SUPPORTED_SAMPLE_RATE));
3369 open.sample_rate = rate;
3370
Rohit kumar2054b692019-02-01 18:01:12 +05303371 ret = adm_arrange_mch_map(&open, path, channel_mode,
3372 port_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303373 if (ret)
3374 return ret;
3375
Dieter Luecking50c55352018-09-28 14:29:17 +02003376 pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
3377 __func__, open.endpoint_id_1, open.sample_rate,
3378 open.topology_id);
3379
3380 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3381
3382 if ((this_adm.num_ec_ref_rx_chans != 0) &&
3383 (path != 1) && (open.endpoint_id_2 != 0xFFFF)) {
3384 memset(&open_v6, 0,
3385 sizeof(struct adm_cmd_device_open_v6));
3386 memcpy(&open_v6, &open,
3387 sizeof(struct adm_cmd_device_open_v5));
3388 open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
3389 open_v6.hdr.pkt_size = sizeof(open_v6);
3390 open_v6.dev_num_channel_eid2 =
3391 this_adm.num_ec_ref_rx_chans;
Dieter Luecking50c55352018-09-28 14:29:17 +02003392
3393 if (this_adm.ec_ref_rx_bit_width != 0) {
3394 open_v6.bit_width_eid2 =
3395 this_adm.ec_ref_rx_bit_width;
Dieter Luecking50c55352018-09-28 14:29:17 +02003396 } else {
3397 open_v6.bit_width_eid2 = bit_width;
3398 }
3399
3400 if (this_adm.ec_ref_rx_sampling_rate != 0) {
3401 open_v6.sample_rate_eid2 =
3402 this_adm.ec_ref_rx_sampling_rate;
Dieter Luecking50c55352018-09-28 14:29:17 +02003403 } else {
3404 open_v6.sample_rate_eid2 = rate;
3405 }
3406
3407 pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
3408 __func__, open_v6.dev_num_channel_eid2,
3409 open_v6.bit_width_eid2,
3410 open_v6.sample_rate_eid2);
3411
3412 ret = adm_arrange_mch_ep2_map(&open_v6,
3413 open_v6.dev_num_channel_eid2);
3414
3415 if (ret)
3416 return ret;
3417
3418 ret = apr_send_pkt(this_adm.apr,
3419 (uint32_t *)&open_v6);
3420 } else {
3421 ret = apr_send_pkt(this_adm.apr,
3422 (uint32_t *)&open);
3423 }
3424 if (ret < 0) {
3425 pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
3426 __func__, tmp_port, port_id, ret);
3427 return -EINVAL;
3428 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303429 }
Dieter Luecking50c55352018-09-28 14:29:17 +02003430
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303431 /* Wait for the callback with copp id */
3432 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3433 atomic_read(&this_adm.copp.stat
3434 [port_idx][copp_idx]) >= 0,
Xiaoyu Yec7d47162019-12-18 16:33:23 -08003435 msecs_to_jiffies(2 * TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303436 if (!ret) {
3437 pr_err("%s: ADM open timedout for port_id: 0x%x for [0x%x]\n",
3438 __func__, tmp_port, port_id);
3439 return -EINVAL;
3440 } else if (atomic_read(&this_adm.copp.stat
3441 [port_idx][copp_idx]) > 0) {
3442 pr_err("%s: DSP returned error[%s]\n",
3443 __func__, adsp_err_get_err_str(
3444 atomic_read(&this_adm.copp.stat
3445 [port_idx][copp_idx])));
3446 return adsp_err_get_lnx_err_code(
3447 atomic_read(&this_adm.copp.stat
3448 [port_idx][copp_idx]));
3449 }
3450 }
3451 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
Dhananjay Kumar43034392019-01-16 21:57:58 +05303452
3453 /*
3454 * Configure MFC(in ec_ref path) if chmixing param is applicable and set.
3455 * Except channels and channel maps the media format config for this module
3456 * should match with the COPP(EP1) config values.
3457 */
3458 if (path != ADM_PATH_PLAYBACK &&
3459 this_adm.num_ec_ref_rx_chans_downmixed != 0 &&
3460 num_ec_ref_rx_chans != this_adm.num_ec_ref_rx_chans_downmixed) {
3461 ret = adm_copp_set_ec_ref_mfc_cfg(port_id, copp_idx,
3462 rate, bit_width, num_ec_ref_rx_chans,
3463 this_adm.num_ec_ref_rx_chans_downmixed);
3464 this_adm.num_ec_ref_rx_chans_downmixed = 0;
3465 if (ret)
3466 pr_err("%s: set EC REF MFC cfg failed, err %d\n", __func__, ret);
3467 }
3468
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303469 return copp_idx;
3470}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303471EXPORT_SYMBOL(adm_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303472
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303473/**
3474 * adm_copp_mfc_cfg -
3475 * command to send ADM MFC config
3476 *
3477 * @port_id: Port ID number
3478 * @copp_idx: copp index assigned
3479 * @dst_sample_rate: sink sample rate
3480 *
3481 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303482void adm_copp_mfc_cfg(int port_id, int copp_idx, int dst_sample_rate)
3483{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003484 struct audproc_mfc_param_media_fmt mfc_cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303485 struct adm_cmd_device_open_v5 open;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003486 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303487 int port_idx;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303488 int rc = 0;
3489 int i = 0;
3490
3491 port_id = q6audio_convert_virtual_to_portid(port_id);
3492 port_idx = adm_validate_and_get_port_index(port_id);
3493
3494 if (port_idx < 0) {
3495 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
3496 goto fail_cmd;
3497 }
3498
3499 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
3500 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
3501 goto fail_cmd;
3502 }
3503
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003504 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
3505 memset(&open, 0, sizeof(open));
3506 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303507
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003508 param_hdr.module_id = AUDPROC_MODULE_ID_MFC;
3509 param_hdr.instance_id = INSTANCE_ID_0;
3510 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
3511 param_hdr.param_size = sizeof(mfc_cfg);
3512
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303513 mfc_cfg.sampling_rate = dst_sample_rate;
3514 mfc_cfg.bits_per_sample =
3515 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
3516 open.dev_num_channel = mfc_cfg.num_channels =
3517 atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
3518
3519 rc = adm_arrange_mch_map(&open, ADM_PATH_PLAYBACK,
Rohit kumar2054b692019-02-01 18:01:12 +05303520 mfc_cfg.num_channels, port_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303521 if (rc < 0) {
3522 pr_err("%s: unable to get channal map\n", __func__);
3523 goto fail_cmd;
3524 }
3525
3526 for (i = 0; i < mfc_cfg.num_channels; i++)
3527 mfc_cfg.channel_type[i] =
3528 (uint16_t) open.dev_channel_mapping[i];
3529
3530 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3531
3532 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",
3533 __func__, port_idx, copp_idx,
3534 atomic_read(&this_adm.copp.rate[port_idx][copp_idx]),
3535 mfc_cfg.bits_per_sample, mfc_cfg.num_channels,
3536 mfc_cfg.sampling_rate);
3537
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003538 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
3539 (uint8_t *) &mfc_cfg);
3540 if (rc)
3541 pr_err("%s: Failed to set media format configuration data, err %d\n",
3542 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303543
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303544fail_cmd:
3545 return;
3546}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303547EXPORT_SYMBOL(adm_copp_mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303548
3549static void route_set_opcode_matrix_id(
3550 struct adm_cmd_matrix_map_routings_v5 **route_addr,
3551 int path, uint32_t passthr_mode)
3552{
3553 struct adm_cmd_matrix_map_routings_v5 *route = *route_addr;
3554
3555 switch (path) {
3556 case ADM_PATH_PLAYBACK:
3557 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
3558 route->matrix_id = ADM_MATRIX_ID_AUDIO_RX;
3559 break;
3560 case ADM_PATH_LIVE_REC:
3561 if (passthr_mode == LISTEN) {
3562 route->hdr.opcode =
3563 ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3564 route->matrix_id = ADM_MATRIX_ID_LISTEN_TX;
3565 break;
3566 }
3567 /* fall through to set matrix id for non-listen case */
3568 case ADM_PATH_NONLIVE_REC:
3569 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
3570 route->matrix_id = ADM_MATRIX_ID_AUDIO_TX;
3571 break;
3572 case ADM_PATH_COMPRESSED_RX:
3573 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3574 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_RX;
3575 break;
3576 case ADM_PATH_COMPRESSED_TX:
3577 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3578 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_TX;
3579 break;
3580 default:
3581 pr_err("%s: Wrong path set[%d]\n", __func__, path);
3582 break;
3583 }
3584 pr_debug("%s: opcode 0x%x, matrix id %d\n",
3585 __func__, route->hdr.opcode, route->matrix_id);
3586}
3587
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303588/**
3589 * adm_matrix_map -
3590 * command to send ADM matrix map for ADM copp list
3591 *
3592 * @path: direction or ADM path type
3593 * @payload_map: have info of session id and associated copp_idx/num_copps
3594 * @perf_mode: performance mode like LL/ULL/..
3595 * @passthr_mode: flag to indicate passthrough mode
3596 *
3597 * Returns 0 on success or error on failure
3598 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303599int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode,
3600 uint32_t passthr_mode)
3601{
3602 struct adm_cmd_matrix_map_routings_v5 *route;
3603 struct adm_session_map_node_v5 *node;
3604 uint16_t *copps_list;
3605 int cmd_size = 0;
3606 int ret = 0, i = 0;
3607 void *payload = NULL;
3608 void *matrix_map = NULL;
3609 int port_idx, copp_idx;
3610
3611 /* Assumes port_ids have already been validated during adm_open */
3612 cmd_size = (sizeof(struct adm_cmd_matrix_map_routings_v5) +
3613 sizeof(struct adm_session_map_node_v5) +
3614 (sizeof(uint32_t) * payload_map.num_copps));
3615 matrix_map = kzalloc(cmd_size, GFP_KERNEL);
3616 if (matrix_map == NULL) {
3617 pr_err("%s: Mem alloc failed\n", __func__);
3618 ret = -EINVAL;
3619 return ret;
3620 }
3621 route = (struct adm_cmd_matrix_map_routings_v5 *)matrix_map;
3622
3623 route->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3624 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3625 route->hdr.pkt_size = cmd_size;
3626 route->hdr.src_svc = 0;
3627 route->hdr.src_domain = APR_DOMAIN_APPS;
3628 route->hdr.src_port = 0; /* Ignored */;
3629 route->hdr.dest_svc = APR_SVC_ADM;
3630 route->hdr.dest_domain = APR_DOMAIN_ADSP;
3631 route->hdr.dest_port = 0; /* Ignored */;
3632 route->hdr.token = 0;
3633 route->num_sessions = 1;
3634 route_set_opcode_matrix_id(&route, path, passthr_mode);
3635
3636 payload = ((u8 *)matrix_map +
3637 sizeof(struct adm_cmd_matrix_map_routings_v5));
3638 node = (struct adm_session_map_node_v5 *)payload;
3639
3640 node->session_id = payload_map.session_id;
3641 node->num_copps = payload_map.num_copps;
3642 payload = (u8 *)node + sizeof(struct adm_session_map_node_v5);
3643 copps_list = (uint16_t *)payload;
3644 for (i = 0; i < payload_map.num_copps; i++) {
3645 port_idx =
3646 adm_validate_and_get_port_index(payload_map.port_id[i]);
3647 if (port_idx < 0) {
3648 pr_err("%s: Invalid port_id 0x%x\n", __func__,
3649 payload_map.port_id[i]);
3650 ret = -EINVAL;
3651 goto fail_cmd;
3652 }
3653 copp_idx = payload_map.copp_idx[i];
3654 copps_list[i] = atomic_read(&this_adm.copp.id[port_idx]
3655 [copp_idx]);
3656 }
3657 atomic_set(&this_adm.matrix_map_stat, -1);
3658
3659 ret = apr_send_pkt(this_adm.apr, (uint32_t *)matrix_map);
3660 if (ret < 0) {
3661 pr_err("%s: routing for syream %d failed ret %d\n",
3662 __func__, payload_map.session_id, ret);
3663 ret = -EINVAL;
3664 goto fail_cmd;
3665 }
3666 ret = wait_event_timeout(this_adm.matrix_map_wait,
3667 atomic_read(&this_adm.matrix_map_stat) >= 0,
3668 msecs_to_jiffies(TIMEOUT_MS));
3669 if (!ret) {
3670 pr_err("%s: routing for syream %d failed\n", __func__,
3671 payload_map.session_id);
3672 ret = -EINVAL;
3673 goto fail_cmd;
3674 } else if (atomic_read(&this_adm.matrix_map_stat) > 0) {
3675 pr_err("%s: DSP returned error[%s]\n", __func__,
3676 adsp_err_get_err_str(atomic_read(
3677 &this_adm.matrix_map_stat)));
3678 ret = adsp_err_get_lnx_err_code(
3679 atomic_read(&this_adm.matrix_map_stat));
3680 goto fail_cmd;
3681 }
3682
3683 if ((perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) &&
3684 (path != ADM_PATH_COMPRESSED_RX)) {
3685 for (i = 0; i < payload_map.num_copps; i++) {
3686 port_idx = afe_get_port_index(payload_map.port_id[i]);
3687 copp_idx = payload_map.copp_idx[i];
3688 if (port_idx < 0 || copp_idx < 0 ||
3689 (copp_idx > MAX_COPPS_PER_PORT - 1)) {
3690 pr_err("%s: Invalid idx port_idx %d copp_idx %d\n",
3691 __func__, port_idx, copp_idx);
3692 continue;
3693 }
3694 rtac_add_adm_device(payload_map.port_id[i],
3695 atomic_read(&this_adm.copp.id
3696 [port_idx][copp_idx]),
3697 get_cal_path(path),
3698 payload_map.session_id,
3699 payload_map.app_type[i],
3700 payload_map.acdb_dev_id[i]);
3701
3702 if (!test_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3703 (void *)&this_adm.copp.adm_status[port_idx]
3704 [copp_idx])) {
3705 pr_debug("%s: adm copp[0x%x][%d] already sent",
3706 __func__, port_idx, copp_idx);
3707 continue;
3708 }
3709 send_adm_cal(payload_map.port_id[i], copp_idx,
3710 get_cal_path(path), perf_mode,
3711 payload_map.app_type[i],
3712 payload_map.acdb_dev_id[i],
Aditya Bavanari5106b562018-01-08 13:16:32 +05303713 payload_map.sample_rate[i],
3714 passthr_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303715 /* ADM COPP calibration is already sent */
3716 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3717 (void *)&this_adm.copp.
3718 adm_status[port_idx][copp_idx]);
3719 pr_debug("%s: copp_id: %d\n", __func__,
3720 atomic_read(&this_adm.copp.id[port_idx]
3721 [copp_idx]));
3722 }
3723 }
3724
3725fail_cmd:
3726 kfree(matrix_map);
3727 return ret;
3728}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303729EXPORT_SYMBOL(adm_matrix_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303730
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303731/**
3732 * adm_ec_ref_rx_id -
3733 * Update EC ref port ID
3734 *
3735 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303736void adm_ec_ref_rx_id(int port_id)
3737{
3738 this_adm.ec_ref_rx = port_id;
3739 pr_debug("%s: ec_ref_rx:%d\n", __func__, this_adm.ec_ref_rx);
3740}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303741EXPORT_SYMBOL(adm_ec_ref_rx_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303742
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303743/**
3744 * adm_num_ec_ref_rx_chans -
3745 * Update EC ref number of channels
3746 *
3747 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303748void adm_num_ec_ref_rx_chans(int num_chans)
3749{
3750 this_adm.num_ec_ref_rx_chans = num_chans;
3751 pr_debug("%s: num_ec_ref_rx_chans:%d\n",
3752 __func__, this_adm.num_ec_ref_rx_chans);
3753}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303754EXPORT_SYMBOL(adm_num_ec_ref_rx_chans);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303755
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303756/**
Dhananjay Kumar43034392019-01-16 21:57:58 +05303757 * adm_num_ec_rx_ref_chans_downmixed -
3758 * Update EC ref num of channels(downmixed) to be fed to EC algo
3759 *
3760 */
3761void adm_num_ec_ref_rx_chans_downmixed(int num_chans)
3762{
3763 this_adm.num_ec_ref_rx_chans_downmixed = num_chans;
3764 pr_debug("%s: num_ec_ref_rx_chans_downmixed:%d\n",
3765 __func__, this_adm.num_ec_ref_rx_chans_downmixed);
3766}
3767EXPORT_SYMBOL(adm_num_ec_ref_rx_chans_downmixed);
3768
3769/**
3770 * adm_ec_ref_chmixer_weights -
3771 * Update MFC(in ec ref) Channel Mixer Weights to be used
3772 * for downmixing rx channels before feeding them to EC algo
3773 * @out_channel_idx: index of output channel to which weightages are applicable
3774 * @weights: pointer to array having input weightages
3775 * @count: array sizeof pointer weights, max supported value is
3776 * PCM_FORMAT_MAX_NUM_CHANNEL_V8
3777 * Returns 0 on success or error on failure
3778 */
3779int adm_ec_ref_chmixer_weights(int out_channel_idx,
3780 uint16_t *weights, int count)
3781{
3782 int i = 0;
3783
3784 if (weights == NULL || count <= 0 || out_channel_idx < 0 ||
3785 count > PCM_FORMAT_MAX_NUM_CHANNEL_V8 ||
3786 out_channel_idx >= PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
3787 pr_err("%s: invalid weightages count(%d) ch_idx(%d)",
3788 __func__, count, out_channel_idx);
3789 return -EINVAL;
3790 }
3791
3792 for (i = 0; i < count; i++) {
3793 this_adm.ec_ref_chmixer_weights[out_channel_idx][i] = weights[i];
3794 pr_debug("%s: out ch idx :%d, weight[%d] = %d\n",
3795 __func__, out_channel_idx, i, weights[i]);
3796 }
3797
3798 return 0;
3799}
3800EXPORT_SYMBOL(adm_ec_ref_chmixer_weights);
3801
3802/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303803 * adm_ec_ref_rx_bit_width -
3804 * Update EC ref bit_width
3805 *
3806 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303807void adm_ec_ref_rx_bit_width(int bit_width)
3808{
3809 this_adm.ec_ref_rx_bit_width = bit_width;
3810 pr_debug("%s: ec_ref_rx_bit_width:%d\n",
3811 __func__, this_adm.ec_ref_rx_bit_width);
3812}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303813EXPORT_SYMBOL(adm_ec_ref_rx_bit_width);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303814
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303815/**
3816 * adm_ec_ref_rx_sampling_rate -
3817 * Update EC ref sample rate
3818 *
3819 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303820void adm_ec_ref_rx_sampling_rate(int sampling_rate)
3821{
3822 this_adm.ec_ref_rx_sampling_rate = sampling_rate;
3823 pr_debug("%s: ec_ref_rx_sampling_rate:%d\n",
3824 __func__, this_adm.ec_ref_rx_sampling_rate);
3825}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303826EXPORT_SYMBOL(adm_ec_ref_rx_sampling_rate);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303827
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303828/**
Dieter Luecking50c55352018-09-28 14:29:17 +02003829 * adm_set_native_mode -
3830 * Set adm channel native mode.
3831 * If enabled matrix mixer will be
3832 * running in native mode for channel
3833 * configuration for this device session.
3834 *
3835 */
3836void adm_set_native_mode(int mode)
3837{
3838 this_adm.native_mode = mode;
3839 pr_debug("%s: enable native_mode :%d\n",
3840 __func__, this_adm.native_mode);
3841}
3842EXPORT_SYMBOL(adm_set_native_mode);
3843
3844/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303845 * adm_close -
3846 * command to close ADM copp
3847 *
3848 * @port_id: Port ID number
3849 * @perf_mode: performance mode like LL/ULL/..
3850 * @copp_idx: copp index assigned
3851 *
3852 * Returns 0 on success or error on failure
3853 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303854int adm_close(int port_id, int perf_mode, int copp_idx)
3855{
3856 struct apr_hdr close;
3857
3858 int ret = 0, port_idx;
3859 int copp_id = RESET_COPP_ID;
3860
3861 pr_debug("%s: port_id=0x%x perf_mode: %d copp_idx: %d\n", __func__,
3862 port_id, perf_mode, copp_idx);
3863
3864 port_id = q6audio_convert_virtual_to_portid(port_id);
3865 port_idx = adm_validate_and_get_port_index(port_id);
3866 if (port_idx < 0) {
3867 pr_err("%s: Invalid port_id 0x%x\n",
3868 __func__, port_id);
3869 return -EINVAL;
3870 }
3871
3872 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
3873 pr_err("%s: Invalid copp idx: %d\n", __func__, copp_idx);
3874 return -EINVAL;
3875 }
3876
Rohit kumar2054b692019-02-01 18:01:12 +05303877 port_channel_map[port_idx].set_channel_map = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303878 if (this_adm.copp.adm_delay[port_idx][copp_idx] && perf_mode
3879 == LEGACY_PCM_MODE) {
3880 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
3881 1);
3882 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
3883 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
3884 }
3885
3886 atomic_dec(&this_adm.copp.cnt[port_idx][copp_idx]);
3887 if (!(atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]))) {
3888 copp_id = adm_get_copp_id(port_idx, copp_idx);
3889 pr_debug("%s: Closing ADM port_idx:%d copp_idx:%d copp_id:0x%x\n",
3890 __func__, port_idx, copp_idx, copp_id);
3891 if ((!perf_mode) && (this_adm.outband_memmap.paddr != 0) &&
3892 (atomic_read(&this_adm.copp.topology[port_idx][copp_idx]) ==
3893 SRS_TRUMEDIA_TOPOLOGY_ID)) {
3894 atomic_set(&this_adm.mem_map_index,
3895 ADM_SRS_TRUMEDIA);
3896 ret = adm_memory_unmap_regions();
3897 if (ret < 0) {
3898 pr_err("%s: adm mem unmmap err %d",
3899 __func__, ret);
3900 } else {
3901 atomic_set(&this_adm.mem_map_handles
3902 [ADM_SRS_TRUMEDIA], 0);
3903 }
3904 }
3905
3906
3907 if ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) &&
3908 this_adm.sourceTrackingData.memmap.paddr) {
3909 atomic_set(&this_adm.mem_map_index,
3910 ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
3911 ret = adm_memory_unmap_regions();
3912 if (ret < 0) {
3913 pr_err("%s: adm mem unmmap err %d",
3914 __func__, ret);
3915 }
3916 msm_audio_ion_free(
Banajit Goswami08bb7362017-11-03 22:48:23 -07003917 this_adm.sourceTrackingData.dma_buf);
3918 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303919 this_adm.sourceTrackingData.memmap.size = 0;
3920 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
3921 this_adm.sourceTrackingData.memmap.paddr = 0;
3922 this_adm.sourceTrackingData.apr_cmd_status = -1;
3923 atomic_set(&this_adm.mem_map_handles[
3924 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
3925 }
3926
3927 close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3928 APR_HDR_LEN(APR_HDR_SIZE),
3929 APR_PKT_VER);
3930 close.pkt_size = sizeof(close);
3931 close.src_svc = APR_SVC_ADM;
3932 close.src_domain = APR_DOMAIN_APPS;
3933 close.src_port = port_id;
3934 close.dest_svc = APR_SVC_ADM;
3935 close.dest_domain = APR_DOMAIN_ADSP;
3936 close.dest_port = copp_id;
3937 close.token = port_idx << 16 | copp_idx;
3938 close.opcode = ADM_CMD_DEVICE_CLOSE_V5;
3939
3940 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
3941 RESET_COPP_ID);
3942 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
3943 atomic_set(&this_adm.copp.topology[port_idx][copp_idx], 0);
3944 atomic_set(&this_adm.copp.mode[port_idx][copp_idx], 0);
3945 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3946 atomic_set(&this_adm.copp.rate[port_idx][copp_idx], 0);
3947 atomic_set(&this_adm.copp.channels[port_idx][copp_idx], 0);
3948 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx], 0);
3949 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx], 0);
Surendar Karkae7507512018-07-20 15:46:54 +05303950 atomic_set(&this_adm.copp.session_type[port_idx][copp_idx], 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303951
3952 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3953 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
3954
3955 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
3956 if (ret < 0) {
3957 pr_err("%s: ADM close failed %d\n", __func__, ret);
3958 return -EINVAL;
3959 }
3960
3961 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3962 atomic_read(&this_adm.copp.stat
3963 [port_idx][copp_idx]) >= 0,
3964 msecs_to_jiffies(TIMEOUT_MS));
3965 if (!ret) {
3966 pr_err("%s: ADM cmd Route timedout for port 0x%x\n",
3967 __func__, port_id);
3968 return -EINVAL;
3969 } else if (atomic_read(&this_adm.copp.stat
3970 [port_idx][copp_idx]) > 0) {
3971 pr_err("%s: DSP returned error[%s]\n",
3972 __func__, adsp_err_get_err_str(
3973 atomic_read(&this_adm.copp.stat
3974 [port_idx][copp_idx])));
3975 return adsp_err_get_lnx_err_code(
3976 atomic_read(&this_adm.copp.stat
3977 [port_idx][copp_idx]));
3978 }
3979 }
3980
3981 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
3982 pr_debug("%s: remove adm device from rtac\n", __func__);
3983 rtac_remove_adm_device(port_id, copp_id);
3984 }
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08003985
3986 if (port_id == this_adm.ffecns_port_id)
3987 this_adm.ffecns_port_id = -1;
3988
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303989 return 0;
3990}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303991EXPORT_SYMBOL(adm_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303992
3993int send_rtac_audvol_cal(void)
3994{
3995 int ret = 0;
3996 int ret2 = 0;
3997 int i = 0;
3998 int copp_idx, port_idx, acdb_id, app_id, path;
3999 struct cal_block_data *cal_block = NULL;
4000 struct audio_cal_info_audvol *audvol_cal_info = NULL;
4001 struct rtac_adm rtac_adm_data;
4002
4003 mutex_lock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
4004
4005 cal_block = cal_utils_get_only_cal_block(
4006 this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07004007 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304008 pr_err("%s: can't find cal block!\n", __func__);
4009 goto unlock;
4010 }
4011
4012 audvol_cal_info = cal_block->cal_info;
4013 if (audvol_cal_info == NULL) {
4014 pr_err("%s: audvol_cal_info is NULL!\n", __func__);
4015 goto unlock;
4016 }
4017
4018 get_rtac_adm_data(&rtac_adm_data);
4019 for (; i < rtac_adm_data.num_of_dev; i++) {
4020
4021 acdb_id = rtac_adm_data.device[i].acdb_dev_id;
4022 if (acdb_id == 0)
4023 acdb_id = audvol_cal_info->acdb_id;
4024
4025 app_id = rtac_adm_data.device[i].app_type;
4026 if (app_id == 0)
4027 app_id = audvol_cal_info->app_type;
4028
4029 path = afe_get_port_type(rtac_adm_data.device[i].afe_port);
4030 if ((acdb_id == audvol_cal_info->acdb_id) &&
4031 (app_id == audvol_cal_info->app_type) &&
4032 (path == audvol_cal_info->path)) {
4033
4034 if (adm_get_indexes_from_copp_id(rtac_adm_data.
4035 device[i].copp, &copp_idx, &port_idx) != 0) {
4036 pr_debug("%s: Copp Id %d is not active\n",
4037 __func__,
4038 rtac_adm_data.device[i].copp);
4039 continue;
4040 }
4041
4042 ret2 = adm_remap_and_send_cal_block(ADM_RTAC_AUDVOL_CAL,
4043 rtac_adm_data.device[i].afe_port,
4044 copp_idx, cal_block,
4045 atomic_read(&this_adm.copp.
4046 mode[port_idx][copp_idx]),
4047 audvol_cal_info->app_type,
4048 audvol_cal_info->acdb_id,
4049 atomic_read(&this_adm.copp.
4050 rate[port_idx][copp_idx]));
4051 if (ret2 < 0) {
4052 pr_debug("%s: remap and send failed for copp Id %d, acdb id %d, app type %d, path %d\n",
4053 __func__, rtac_adm_data.device[i].copp,
4054 audvol_cal_info->acdb_id,
4055 audvol_cal_info->app_type,
4056 audvol_cal_info->path);
4057 ret = ret2;
4058 }
4059 }
4060 }
4061unlock:
4062 mutex_unlock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
4063 return ret;
4064}
4065
4066int adm_map_rtac_block(struct rtac_cal_block_data *cal_block)
4067{
4068 int result = 0;
4069
4070 pr_debug("%s:\n", __func__);
4071
4072 if (cal_block == NULL) {
4073 pr_err("%s: cal_block is NULL!\n",
4074 __func__);
4075 result = -EINVAL;
4076 goto done;
4077 }
4078
4079 if (cal_block->cal_data.paddr == 0) {
4080 pr_debug("%s: No address to map!\n",
4081 __func__);
4082 result = -EINVAL;
4083 goto done;
4084 }
4085
4086 if (cal_block->map_data.map_size == 0) {
4087 pr_debug("%s: map size is 0!\n",
4088 __func__);
4089 result = -EINVAL;
4090 goto done;
4091 }
4092
4093 /* valid port ID needed for callback use primary I2S */
4094 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
4095 result = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
4096 &cal_block->map_data.map_size, 1);
4097 if (result < 0) {
4098 pr_err("%s: RTAC mmap did not work! size = %d result %d\n",
4099 __func__,
4100 cal_block->map_data.map_size, result);
4101 pr_debug("%s: RTAC mmap did not work! addr = 0x%pK, size = %d\n",
4102 __func__,
4103 &cal_block->cal_data.paddr,
4104 cal_block->map_data.map_size);
4105 goto done;
4106 }
4107
4108 cal_block->map_data.map_handle = atomic_read(
4109 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]);
4110done:
4111 return result;
4112}
4113
4114int adm_unmap_rtac_block(uint32_t *mem_map_handle)
4115{
4116 int result = 0;
4117
4118 pr_debug("%s:\n", __func__);
4119
4120 if (mem_map_handle == NULL) {
4121 pr_debug("%s: Map handle is NULL, nothing to unmap\n",
4122 __func__);
4123 goto done;
4124 }
4125
4126 if (*mem_map_handle == 0) {
4127 pr_debug("%s: Map handle is 0, nothing to unmap\n",
4128 __func__);
4129 goto done;
4130 }
4131
4132 if (*mem_map_handle != atomic_read(
4133 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL])) {
4134 pr_err("%s: Map handles do not match! Unmapping RTAC, RTAC map 0x%x, ADM map 0x%x\n",
4135 __func__, *mem_map_handle, atomic_read(
4136 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]));
4137
4138 /* if mismatch use handle passed in to unmap */
4139 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL],
4140 *mem_map_handle);
4141 }
4142
4143 /* valid port ID needed for callback use primary I2S */
4144 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
4145 result = adm_memory_unmap_regions();
4146 if (result < 0) {
4147 pr_debug("%s: adm_memory_unmap_regions failed, error %d\n",
4148 __func__, result);
4149 } else {
4150 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL], 0);
4151 *mem_map_handle = 0;
4152 }
4153done:
4154 return result;
4155}
4156
4157static int get_cal_type_index(int32_t cal_type)
4158{
4159 int ret = -EINVAL;
4160
4161 switch (cal_type) {
4162 case ADM_AUDPROC_CAL_TYPE:
4163 ret = ADM_AUDPROC_CAL;
4164 break;
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304165 case ADM_LSM_AUDPROC_CAL_TYPE:
4166 ret = ADM_LSM_AUDPROC_CAL;
4167 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304168 case ADM_AUDVOL_CAL_TYPE:
4169 ret = ADM_AUDVOL_CAL;
4170 break;
4171 case ADM_CUST_TOPOLOGY_CAL_TYPE:
4172 ret = ADM_CUSTOM_TOP_CAL;
4173 break;
4174 case ADM_RTAC_INFO_CAL_TYPE:
4175 ret = ADM_RTAC_INFO_CAL;
4176 break;
4177 case ADM_RTAC_APR_CAL_TYPE:
4178 ret = ADM_RTAC_APR_CAL;
4179 break;
4180 case ADM_RTAC_AUDVOL_CAL_TYPE:
4181 ret = ADM_RTAC_AUDVOL_CAL;
4182 break;
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004183 case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
4184 ret = ADM_LSM_AUDPROC_PERSISTENT_CAL;
4185 break;
Ramlal Karra471fe912020-04-13 13:47:07 +05304186 case ADM_AUDPROC_PERSISTENT_CAL_TYPE:
4187 ret = ADM_AUDPROC_PERSISTENT_CAL;
4188 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304189 default:
4190 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
4191 }
4192 return ret;
4193}
4194
4195static int adm_alloc_cal(int32_t cal_type, size_t data_size, void *data)
4196{
4197 int ret = 0;
4198 int cal_index;
4199
4200 pr_debug("%s:\n", __func__);
4201
4202 cal_index = get_cal_type_index(cal_type);
4203 if (cal_index < 0) {
4204 pr_err("%s: could not get cal index %d!\n",
4205 __func__, cal_index);
4206 ret = -EINVAL;
4207 goto done;
4208 }
4209
4210 ret = cal_utils_alloc_cal(data_size, data,
4211 this_adm.cal_data[cal_index], 0, NULL);
4212 if (ret < 0) {
4213 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
4214 __func__, ret, cal_type);
4215 ret = -EINVAL;
4216 goto done;
4217 }
4218done:
4219 return ret;
4220}
4221
4222static int adm_dealloc_cal(int32_t cal_type, size_t data_size, void *data)
4223{
4224 int ret = 0;
4225 int cal_index;
4226
4227 pr_debug("%s:\n", __func__);
4228
4229 cal_index = get_cal_type_index(cal_type);
4230 if (cal_index < 0) {
4231 pr_err("%s: could not get cal index %d!\n",
4232 __func__, cal_index);
4233 ret = -EINVAL;
4234 goto done;
4235 }
4236
4237 ret = cal_utils_dealloc_cal(data_size, data,
4238 this_adm.cal_data[cal_index]);
4239 if (ret < 0) {
4240 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
4241 __func__, ret, cal_type);
4242 ret = -EINVAL;
4243 goto done;
4244 }
4245done:
4246 return ret;
4247}
4248
4249static int adm_set_cal(int32_t cal_type, size_t data_size, void *data)
4250{
4251 int ret = 0;
4252 int cal_index;
4253
4254 pr_debug("%s:\n", __func__);
4255
4256 cal_index = get_cal_type_index(cal_type);
4257 if (cal_index < 0) {
4258 pr_err("%s: could not get cal index %d!\n",
4259 __func__, cal_index);
4260 ret = -EINVAL;
4261 goto done;
4262 }
4263
4264 ret = cal_utils_set_cal(data_size, data,
4265 this_adm.cal_data[cal_index], 0, NULL);
4266 if (ret < 0) {
4267 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
4268 __func__, ret, cal_type);
4269 ret = -EINVAL;
4270 goto done;
4271 }
4272
4273 if (cal_index == ADM_CUSTOM_TOP_CAL) {
4274 mutex_lock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
4275 this_adm.set_custom_topology = 1;
4276 mutex_unlock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
4277 } else if (cal_index == ADM_RTAC_AUDVOL_CAL) {
4278 send_rtac_audvol_cal();
4279 }
4280done:
4281 return ret;
4282}
4283
4284static int adm_map_cal_data(int32_t cal_type,
4285 struct cal_block_data *cal_block)
4286{
4287 int ret = 0;
4288 int cal_index;
4289
4290 pr_debug("%s:\n", __func__);
4291
4292 cal_index = get_cal_type_index(cal_type);
4293 if (cal_index < 0) {
4294 pr_err("%s: could not get cal index %d!\n",
4295 __func__, cal_index);
4296 ret = -EINVAL;
4297 goto done;
4298 }
4299
4300 atomic_set(&this_adm.mem_map_index, cal_index);
4301 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
4302 (uint32_t *)&cal_block->map_data.map_size, 1);
4303 if (ret < 0) {
4304 pr_err("%s: map did not work! cal_type %i ret %d\n",
4305 __func__, cal_index, ret);
4306 ret = -ENODEV;
4307 goto done;
4308 }
4309 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
4310 mem_map_handles[cal_index]);
4311done:
4312 return ret;
4313}
4314
4315static int adm_unmap_cal_data(int32_t cal_type,
4316 struct cal_block_data *cal_block)
4317{
4318 int ret = 0;
4319 int cal_index;
4320
4321 pr_debug("%s:\n", __func__);
4322
4323 cal_index = get_cal_type_index(cal_type);
4324 if (cal_index < 0) {
4325 pr_err("%s: could not get cal index %d!\n",
4326 __func__, cal_index);
4327 ret = -EINVAL;
4328 goto done;
4329 }
4330
4331 if (cal_block == NULL) {
4332 pr_err("%s: Cal block is NULL!\n",
4333 __func__);
4334 goto done;
4335 }
4336
4337 if (cal_block->map_data.q6map_handle == 0) {
4338 pr_err("%s: Map handle is NULL, nothing to unmap\n",
4339 __func__);
4340 goto done;
4341 }
4342
4343 atomic_set(&this_adm.mem_map_handles[cal_index],
4344 cal_block->map_data.q6map_handle);
4345 atomic_set(&this_adm.mem_map_index, cal_index);
4346 ret = adm_memory_unmap_regions();
4347 if (ret < 0) {
4348 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
4349 __func__, cal_index, ret);
4350 ret = -ENODEV;
4351 goto done;
4352 }
4353 cal_block->map_data.q6map_handle = 0;
4354done:
4355 return ret;
4356}
4357
4358static void adm_delete_cal_data(void)
4359{
4360 pr_debug("%s:\n", __func__);
4361
4362 cal_utils_destroy_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data);
4363}
4364
4365static int adm_init_cal_data(void)
4366{
4367 int ret = 0;
4368 struct cal_type_info cal_type_info[] = {
4369 {{ADM_CUST_TOPOLOGY_CAL_TYPE,
4370 {adm_alloc_cal, adm_dealloc_cal, NULL,
4371 adm_set_cal, NULL, NULL} },
4372 {adm_map_cal_data, adm_unmap_cal_data,
4373 cal_utils_match_buf_num} },
4374
4375 {{ADM_AUDPROC_CAL_TYPE,
4376 {adm_alloc_cal, adm_dealloc_cal, NULL,
4377 adm_set_cal, NULL, NULL} },
4378 {adm_map_cal_data, adm_unmap_cal_data,
4379 cal_utils_match_buf_num} },
4380
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304381 {{ADM_LSM_AUDPROC_CAL_TYPE,
4382 {adm_alloc_cal, adm_dealloc_cal, NULL,
4383 adm_set_cal, NULL, NULL} },
4384 {adm_map_cal_data, adm_unmap_cal_data,
4385 cal_utils_match_buf_num} },
4386
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304387 {{ADM_AUDVOL_CAL_TYPE,
4388 {adm_alloc_cal, adm_dealloc_cal, NULL,
4389 adm_set_cal, NULL, NULL} },
4390 {adm_map_cal_data, adm_unmap_cal_data,
4391 cal_utils_match_buf_num} },
4392
4393 {{ADM_RTAC_INFO_CAL_TYPE,
4394 {NULL, NULL, NULL, NULL, NULL, NULL} },
4395 {NULL, NULL, cal_utils_match_buf_num} },
4396
4397 {{ADM_RTAC_APR_CAL_TYPE,
4398 {NULL, NULL, NULL, NULL, NULL, NULL} },
4399 {NULL, NULL, cal_utils_match_buf_num} },
4400
4401 {{SRS_TRUMEDIA_CAL_TYPE,
4402 {NULL, NULL, NULL, NULL, NULL, NULL} },
4403 {NULL, NULL, cal_utils_match_buf_num} },
4404
4405 {{ADM_RTAC_AUDVOL_CAL_TYPE,
4406 {adm_alloc_cal, adm_dealloc_cal, NULL,
4407 adm_set_cal, NULL, NULL} },
4408 {adm_map_cal_data, adm_unmap_cal_data,
4409 cal_utils_match_buf_num} },
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004410
4411 {{ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE,
4412 {adm_alloc_cal, adm_dealloc_cal, NULL,
4413 adm_set_cal, NULL, NULL} },
4414 {adm_map_cal_data, adm_unmap_cal_data,
4415 cal_utils_match_buf_num} },
Ramlal Karra471fe912020-04-13 13:47:07 +05304416
4417 {{ADM_AUDPROC_PERSISTENT_CAL_TYPE,
4418 {adm_alloc_cal, adm_dealloc_cal, NULL,
4419 adm_set_cal, NULL, NULL} },
4420 {adm_map_cal_data, adm_unmap_cal_data,
4421 cal_utils_match_buf_num} },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304422 };
4423 pr_debug("%s:\n", __func__);
4424
4425 ret = cal_utils_create_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data,
4426 cal_type_info);
4427 if (ret < 0) {
4428 pr_err("%s: could not create cal type! ret %d\n",
4429 __func__, ret);
4430 ret = -EINVAL;
4431 goto err;
4432 }
4433
4434 return ret;
4435err:
4436 adm_delete_cal_data();
4437 return ret;
4438}
4439
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304440/**
4441 * adm_set_volume -
4442 * command to set volume on ADM copp
4443 *
4444 * @port_id: Port ID number
4445 * @copp_idx: copp index assigned
4446 * @volume: gain value to set
4447 *
4448 * Returns 0 on success or error on failure
4449 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304450int adm_set_volume(int port_id, int copp_idx, int volume)
4451{
4452 struct audproc_volume_ctrl_master_gain audproc_vol;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004453 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304454 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304455
4456 pr_debug("%s: port_id %d, volume %d\n", __func__, port_id, volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304457
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004458 memset(&audproc_vol, 0, sizeof(audproc_vol));
4459 memset(&param_hdr, 0, sizeof(param_hdr));
4460 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
4461 param_hdr.instance_id = INSTANCE_ID_0;
4462 param_hdr.param_id = AUDPROC_PARAM_ID_VOL_CTRL_MASTER_GAIN;
4463 param_hdr.param_size = sizeof(audproc_vol);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304464
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304465 audproc_vol.master_gain = volume;
4466
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004467 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4468 (uint8_t *) &audproc_vol);
4469 if (rc)
4470 pr_err("%s: Failed to set volume, err %d\n", __func__, rc);
4471
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304472 return rc;
4473}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304474EXPORT_SYMBOL(adm_set_volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304475
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304476/**
4477 * adm_set_softvolume -
4478 * command to set softvolume
4479 *
4480 * @port_id: Port ID number
4481 * @copp_idx: copp index assigned
4482 * @softvol_param: Params to set for softvolume
4483 *
4484 * Returns 0 on success or error on failure
4485 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304486int adm_set_softvolume(int port_id, int copp_idx,
4487 struct audproc_softvolume_params *softvol_param)
4488{
4489 struct audproc_soft_step_volume_params audproc_softvol;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004490 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304491 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304492
4493 pr_debug("%s: period %d step %d curve %d\n", __func__,
4494 softvol_param->period, softvol_param->step,
4495 softvol_param->rampingcurve);
4496
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004497 memset(&audproc_softvol, 0, sizeof(audproc_softvol));
4498 memset(&param_hdr, 0, sizeof(param_hdr));
4499 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
4500 param_hdr.instance_id = INSTANCE_ID_0;
4501 param_hdr.param_id = AUDPROC_PARAM_ID_SOFT_VOL_STEPPING_PARAMETERS;
4502 param_hdr.param_size = sizeof(audproc_softvol);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304503
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304504 audproc_softvol.period = softvol_param->period;
4505 audproc_softvol.step = softvol_param->step;
4506 audproc_softvol.ramping_curve = softvol_param->rampingcurve;
4507
4508 pr_debug("%s: period %d, step %d, curve %d\n", __func__,
4509 audproc_softvol.period, audproc_softvol.step,
4510 audproc_softvol.ramping_curve);
4511
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004512 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4513 (uint8_t *) &audproc_softvol);
4514 if (rc)
4515 pr_err("%s: Failed to set soft volume, err %d\n", __func__, rc);
4516
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304517 return rc;
4518}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304519EXPORT_SYMBOL(adm_set_softvolume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304520
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304521/**
4522 * adm_set_mic_gain -
4523 * command to set MIC gain
4524 *
4525 * @port_id: Port ID number
4526 * @copp_idx: copp index assigned
4527 * @volume: gain value to set
4528 *
4529 * Returns 0 on success or error on failure
4530 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304531int adm_set_mic_gain(int port_id, int copp_idx, int volume)
4532{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004533 struct admx_mic_gain mic_gain_params;
4534 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304535 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304536
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004537 pr_debug("%s: Setting mic gain to %d at port_id 0x%x\n", __func__,
4538 volume, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304539
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004540 memset(&mic_gain_params, 0, sizeof(mic_gain_params));
4541 memset(&param_hdr, 0, sizeof(param_hdr));
4542 param_hdr.module_id = ADM_MODULE_IDX_MIC_GAIN_CTRL;
4543 param_hdr.instance_id = INSTANCE_ID_0;
4544 param_hdr.param_id = ADM_PARAM_IDX_MIC_GAIN;
4545 param_hdr.param_size = sizeof(mic_gain_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304546
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004547 mic_gain_params.tx_mic_gain = volume;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304548
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004549 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4550 (uint8_t *) &mic_gain_params);
4551 if (rc)
4552 pr_err("%s: Failed to set mic gain, err %d\n", __func__, rc);
4553
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304554 return rc;
4555}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304556EXPORT_SYMBOL(adm_set_mic_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304557
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304558/**
4559 * adm_send_set_multichannel_ec_primary_mic_ch -
4560 * command to set multi-ch EC primary mic
4561 *
4562 * @port_id: Port ID number
4563 * @copp_idx: copp index assigned
4564 * @primary_mic_ch: channel number of primary mic
4565 *
4566 * Returns 0 on success or error on failure
4567 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304568int adm_send_set_multichannel_ec_primary_mic_ch(int port_id, int copp_idx,
4569 int primary_mic_ch)
4570{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004571 struct admx_sec_primary_mic_ch sec_primary_ch_params;
4572 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304573 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304574
4575 pr_debug("%s port_id 0x%x, copp_idx 0x%x, primary_mic_ch %d\n",
4576 __func__, port_id, copp_idx, primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304577
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004578 memset(&sec_primary_ch_params, 0, sizeof(sec_primary_ch_params));
4579 memset(&param_hdr, 0, sizeof(param_hdr));
4580 param_hdr.module_id = AUDPROC_MODULE_ID_VOICE_TX_SECNS;
4581 param_hdr.instance_id = INSTANCE_ID_0;
4582 param_hdr.param_id = AUDPROC_PARAM_IDX_SEC_PRIMARY_MIC_CH;
4583 param_hdr.param_size = sizeof(sec_primary_ch_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304584
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004585 sec_primary_ch_params.version = 0;
4586 sec_primary_ch_params.sec_primary_mic_ch = primary_mic_ch;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304587
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004588 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4589 (uint8_t *) &sec_primary_ch_params);
4590 if (rc)
4591 pr_err("%s: Failed to set primary mic chanel, err %d\n",
4592 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304593
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304594 return rc;
4595}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304596EXPORT_SYMBOL(adm_send_set_multichannel_ec_primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304597
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304598/**
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08004599 * adm_set_ffecns_effect -
4600 * command to set effect for ffecns module
4601 *
4602 * @effect: effect payload
4603 *
4604 * Returns 0 on success or error on failure
4605 */
4606int adm_set_ffecns_effect(int effect)
4607{
4608 struct ffecns_effect ffecns_params;
4609 struct param_hdr_v3 param_hdr;
4610 int rc = 0;
4611 int copp_idx = 0;
4612
4613 copp_idx = adm_get_default_copp_idx(this_adm.ffecns_port_id);
4614 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
4615 pr_err("%s, no active copp to query rms copp_idx:%d\n",
4616 __func__, copp_idx);
4617 return -EINVAL;
4618 }
4619
4620 memset(&ffecns_params, 0, sizeof(ffecns_params));
4621 memset(&param_hdr, 0, sizeof(param_hdr));
4622
4623 param_hdr.module_id = FFECNS_MODULE_ID;
4624 param_hdr.instance_id = INSTANCE_ID_0;
4625 param_hdr.param_id = FLUENCE_CMN_GLOBAL_EFFECT_PARAM_ID;
4626 param_hdr.param_size = sizeof(ffecns_params);
4627
4628 ffecns_params.payload = effect;
4629
4630 rc = adm_pack_and_set_one_pp_param(this_adm.ffecns_port_id, copp_idx,
4631 param_hdr, (uint8_t *) &ffecns_params);
4632 if (rc)
4633 pr_err("%s: Failed to set ffecns effect, err %d\n",
4634 __func__, rc);
4635
4636 return rc;
4637}
4638EXPORT_SYMBOL(adm_set_ffecns_effect);
4639
4640/**
Ramu Gottipati34dc3622019-12-26 10:50:00 +05304641 * adm_set_ffecns_freeze_event -
4642 * command to set event for ffecns module
4643 *
4644 * @event: send ffecns freeze event true or false
4645 *
4646 * Returns 0 on success or error on failure
4647 */
4648int adm_set_ffecns_freeze_event(bool ffecns_freeze_event)
4649{
4650 struct ffv_spf_freeze_param_t ffv_param;
4651 struct param_hdr_v3 param_hdr;
4652 int rc = 0;
4653 int copp_idx = 0;
4654
4655 memset(&param_hdr, 0, sizeof(param_hdr));
4656 memset(&ffv_param, 0, sizeof(ffv_param));
4657
4658 ffv_param.freeze = ffecns_freeze_event ? 1 : 0;
4659 ffv_param.source_id = 0; /*default value*/
4660
4661 copp_idx = adm_get_default_copp_idx(this_adm.ffecns_port_id);
4662 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
4663 pr_err("%s, no active copp to query rms copp_idx:%d\n",
4664 __func__, copp_idx);
4665 return -EINVAL;
4666 }
4667
4668 param_hdr.module_id = FFECNS_MODULE_ID;
4669 param_hdr.instance_id = INSTANCE_ID_0;
4670 param_hdr.param_id = PARAM_ID_FFV_SPF_FREEZE;
4671 param_hdr.param_size = sizeof(ffv_param);
4672
4673 rc = adm_pack_and_set_one_pp_param(this_adm.ffecns_port_id, copp_idx,
4674 param_hdr, (uint8_t *) &ffv_param);
4675 if (rc)
4676 pr_err("%s: Failed to set ffecns imc event, err %d\n",
4677 __func__, rc);
4678
4679 return rc;
4680}
4681EXPORT_SYMBOL(adm_set_ffecns_freeze_event);
4682
4683/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304684 * adm_param_enable -
4685 * command to send params to ADM for given module
4686 *
4687 * @port_id: Port ID number
4688 * @copp_idx: copp index assigned
4689 * @module_id: ADM module
4690 * @enable: flag to enable or disable module
4691 *
4692 * Returns 0 on success or error on failure
4693 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304694int adm_param_enable(int port_id, int copp_idx, int module_id, int enable)
4695{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004696 struct module_instance_info mod_inst_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304697
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004698 memset(&mod_inst_info, 0, sizeof(mod_inst_info));
4699 mod_inst_info.module_id = module_id;
4700 mod_inst_info.instance_id = INSTANCE_ID_0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304701
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004702 return adm_param_enable_v2(port_id, copp_idx, mod_inst_info, enable);
4703}
Vidyakumar Athota98464a22018-03-15 20:39:37 -07004704EXPORT_SYMBOL(adm_param_enable);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004705
4706/**
4707 * adm_param_enable_v2 -
4708 * command to send params to ADM for given module
4709 *
4710 * @port_id: Port ID number
4711 * @copp_idx: copp index assigned
4712 * @mod_inst_info: module and instance ID info
4713 * @enable: flag to enable or disable module
4714 *
4715 * Returns 0 on success or error on failure
4716 */
4717int adm_param_enable_v2(int port_id, int copp_idx,
4718 struct module_instance_info mod_inst_info, int enable)
4719{
4720 uint32_t enable_param;
4721 struct param_hdr_v3 param_hdr;
4722 int rc = 0;
4723
4724 if (enable < 0 || enable > 1) {
4725 pr_err("%s: Invalid value for enable %d\n", __func__, enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304726 return -EINVAL;
4727 }
4728
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004729 pr_debug("%s port_id %d, module_id 0x%x, instance_id 0x%x, enable %d\n",
4730 __func__, port_id, mod_inst_info.module_id,
4731 mod_inst_info.instance_id, enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304732
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004733 memset(&param_hdr, 0, sizeof(param_hdr));
4734 param_hdr.module_id = mod_inst_info.module_id;
4735 param_hdr.instance_id = mod_inst_info.instance_id;
4736 param_hdr.param_id = AUDPROC_PARAM_ID_ENABLE;
4737 param_hdr.param_size = sizeof(enable_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304738
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004739 enable_param = enable;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304740
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004741 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4742 (uint8_t *) &enable_param);
4743 if (rc)
4744 pr_err("%s: Failed to set enable of module(%d) instance(%d) to %d, err %d\n",
4745 __func__, mod_inst_info.module_id,
4746 mod_inst_info.instance_id, enable, rc);
4747
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304748 return rc;
4749
4750}
Vidyakumar Athota98464a22018-03-15 20:39:37 -07004751EXPORT_SYMBOL(adm_param_enable_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304752
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304753/**
4754 * adm_send_calibration -
4755 * send ADM calibration to DSP
4756 *
4757 * @port_id: Port ID number
4758 * @copp_idx: copp index assigned
4759 * @path: direction or ADM path type
4760 * @perf_mode: performance mode like LL/ULL/..
4761 * @cal_type: calibration type to use
4762 * @params: pointer with cal data
4763 * @size: cal size
4764 *
4765 * Returns 0 on success or error on failure
4766 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304767int adm_send_calibration(int port_id, int copp_idx, int path, int perf_mode,
4768 int cal_type, char *params, int size)
4769{
4770
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004771 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304772
4773 pr_debug("%s:port_id %d, path %d, perf_mode %d, cal_type %d, size %d\n",
4774 __func__, port_id, path, perf_mode, cal_type, size);
4775
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304776 /* Maps audio_dev_ctrl path definition to ACDB definition */
4777 if (get_cal_path(path) != RX_DEVICE) {
4778 pr_err("%s: acdb_path %d\n", __func__, path);
4779 rc = -EINVAL;
4780 goto end;
4781 }
4782
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004783 rc = adm_set_pp_params(port_id, copp_idx, NULL, (u8 *) params, size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304784
4785end:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304786 return rc;
4787}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304788EXPORT_SYMBOL(adm_send_calibration);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304789
4790/*
4791 * adm_update_wait_parameters must be called with routing driver locks.
4792 * adm_reset_wait_parameters must be called with routing driver locks.
4793 * set and reset parmeters are separated to make sure it is always called
4794 * under routing driver lock.
4795 * adm_wait_timeout is to block until timeout or interrupted. Timeout is
4796 * not a an error.
4797 */
4798int adm_set_wait_parameters(int port_id, int copp_idx)
4799{
4800
4801 int ret = 0, port_idx;
4802
4803 pr_debug("%s: port_id 0x%x, copp_idx %d\n", __func__, port_id,
4804 copp_idx);
4805 port_id = afe_convert_virtual_to_portid(port_id);
4806 port_idx = adm_validate_and_get_port_index(port_id);
4807 if (port_idx < 0) {
4808 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4809 ret = -EINVAL;
4810 goto end;
4811 }
4812
4813 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4814 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4815 return -EINVAL;
4816 }
4817
4818 this_adm.copp.adm_delay[port_idx][copp_idx] = 1;
4819 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 0);
4820
4821end:
4822 return ret;
4823
4824}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304825EXPORT_SYMBOL(adm_set_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304826
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304827/**
4828 * adm_reset_wait_parameters -
4829 * reset wait parameters or ADM delay value
4830 *
4831 * @port_id: Port ID number
4832 * @copp_idx: copp index assigned
4833 *
4834 * Returns 0 on success or error on failure
4835 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304836int adm_reset_wait_parameters(int port_id, int copp_idx)
4837{
4838 int ret = 0, port_idx;
4839
4840 pr_debug("%s: port_id 0x%x copp_idx %d\n", __func__, port_id,
4841 copp_idx);
4842 port_id = afe_convert_virtual_to_portid(port_id);
4843 port_idx = adm_validate_and_get_port_index(port_id);
4844 if (port_idx < 0) {
4845 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4846 ret = -EINVAL;
4847 goto end;
4848 }
4849
4850 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4851 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4852 return -EINVAL;
4853 }
4854
4855 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 1);
4856 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
4857
4858end:
4859 return ret;
4860}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304861EXPORT_SYMBOL(adm_reset_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304862
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304863/**
4864 * adm_wait_timeout -
4865 * ADM wait command after command send to DSP
4866 *
4867 * @port_id: Port ID number
4868 * @copp_idx: copp index assigned
4869 * @wait_time: value in ms for command timeout
4870 *
4871 * Returns 0 on success or error on failure
4872 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304873int adm_wait_timeout(int port_id, int copp_idx, int wait_time)
4874{
4875 int ret = 0, port_idx;
4876
4877 pr_debug("%s: port_id 0x%x, copp_idx %d, wait_time %d\n", __func__,
4878 port_id, copp_idx, wait_time);
4879 port_id = afe_convert_virtual_to_portid(port_id);
4880 port_idx = adm_validate_and_get_port_index(port_id);
4881 if (port_idx < 0) {
4882 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4883 ret = -EINVAL;
4884 goto end;
4885 }
4886
4887 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4888 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4889 return -EINVAL;
4890 }
4891
4892 ret = wait_event_timeout(
4893 this_adm.copp.adm_delay_wait[port_idx][copp_idx],
4894 atomic_read(&this_adm.copp.adm_delay_stat[port_idx][copp_idx]),
4895 msecs_to_jiffies(wait_time));
4896 pr_debug("%s: return %d\n", __func__, ret);
4897 if (ret != 0)
4898 ret = -EINTR;
4899end:
4900 pr_debug("%s: return %d--\n", __func__, ret);
4901 return ret;
4902}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304903EXPORT_SYMBOL(adm_wait_timeout);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304904
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304905/**
4906 * adm_store_cal_data -
4907 * Retrieve calibration data for ADM copp device
4908 *
4909 * @port_id: Port ID number
4910 * @copp_idx: copp index assigned
4911 * @path: direction or copp type
4912 * @perf_mode: performance mode like LL/ULL/..
4913 * @cal_index: calibration index to use
4914 * @params: pointer to store cal data
4915 * @size: pointer to fill with cal size
4916 *
4917 * Returns 0 on success or error on failure
4918 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304919int adm_store_cal_data(int port_id, int copp_idx, int path, int perf_mode,
4920 int cal_index, char *params, int *size)
4921{
4922 int rc = 0;
4923 struct cal_block_data *cal_block = NULL;
4924 int app_type, acdb_id, port_idx, sample_rate;
4925
4926 if (this_adm.cal_data[cal_index] == NULL) {
4927 pr_debug("%s: cal_index %d not allocated!\n",
4928 __func__, cal_index);
4929 goto end;
4930 }
4931
4932 if (get_cal_path(path) != RX_DEVICE) {
4933 pr_debug("%s: Invalid path to store calibration %d\n",
4934 __func__, path);
4935 rc = -EINVAL;
4936 goto end;
4937 }
4938
4939 port_id = afe_convert_virtual_to_portid(port_id);
4940 port_idx = adm_validate_and_get_port_index(port_id);
4941 if (port_idx < 0) {
4942 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
4943 rc = -EINVAL;
4944 goto end;
4945 }
4946
4947 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4948 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4949 return -EINVAL;
4950 }
4951
4952 acdb_id = atomic_read(&this_adm.copp.acdb_id[port_idx][copp_idx]);
4953 app_type = atomic_read(&this_adm.copp.app_type[port_idx][copp_idx]);
4954 sample_rate = atomic_read(&this_adm.copp.rate[port_idx][copp_idx]);
4955
4956 mutex_lock(&this_adm.cal_data[cal_index]->lock);
4957 cal_block = adm_find_cal(cal_index, get_cal_path(path), app_type,
4958 acdb_id, sample_rate);
4959 if (cal_block == NULL)
4960 goto unlock;
4961
4962 if (cal_block->cal_data.size <= 0) {
4963 pr_debug("%s: No ADM cal send for port_id = 0x%x!\n",
4964 __func__, port_id);
4965 rc = -EINVAL;
4966 goto unlock;
4967 }
4968
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304969 if (cal_index == ADM_AUDPROC_CAL || cal_index == ADM_LSM_AUDPROC_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304970 if (cal_block->cal_data.size > AUD_PROC_BLOCK_SIZE) {
4971 pr_err("%s:audproc:invalid size exp/actual[%zd, %d]\n",
4972 __func__, cal_block->cal_data.size, *size);
4973 rc = -ENOMEM;
4974 goto unlock;
4975 }
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004976 } else if (cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
4977 if (cal_block->cal_data.size > AUD_PROC_PERSIST_BLOCK_SIZE) {
4978 pr_err("%s:persist invalid size exp/actual[%zd, %d]\n",
4979 __func__, cal_block->cal_data.size, *size);
4980 rc = -ENOMEM;
4981 goto unlock;
4982 }
Ramlal Karra471fe912020-04-13 13:47:07 +05304983 } else if (cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
4984 if (cal_block->cal_data.size > AUD_PROC_PERSIST_BLOCK_SIZE) {
4985 pr_err("%s:persist invalid size exp/actual[%zd, %d]\n",
4986 __func__, cal_block->cal_data.size, *size);
4987 rc = -ENOMEM;
4988 goto unlock;
4989 }
4990 }
4991 else if (cal_index == ADM_AUDVOL_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304992 if (cal_block->cal_data.size > AUD_VOL_BLOCK_SIZE) {
4993 pr_err("%s:aud_vol:invalid size exp/actual[%zd, %d]\n",
4994 __func__, cal_block->cal_data.size, *size);
4995 rc = -ENOMEM;
4996 goto unlock;
4997 }
4998 } else {
4999 pr_debug("%s: Not valid calibration for dolby topolgy\n",
5000 __func__);
5001 rc = -EINVAL;
5002 goto unlock;
5003 }
5004 memcpy(params, cal_block->cal_data.kvaddr, cal_block->cal_data.size);
5005 *size = cal_block->cal_data.size;
5006
5007 pr_debug("%s:port_id %d, copp_idx %d, path %d",
5008 __func__, port_id, copp_idx, path);
5009 pr_debug("perf_mode %d, cal_type %d, size %d\n",
5010 perf_mode, cal_index, *size);
5011
5012unlock:
5013 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
5014end:
5015 return rc;
5016}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305017EXPORT_SYMBOL(adm_store_cal_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305018
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305019/**
5020 * adm_send_compressed_device_mute -
5021 * command to send mute for compressed device
5022 *
5023 * @port_id: Port ID number
5024 * @copp_idx: copp index assigned
5025 * @mute_on: flag to indicate mute or unmute
5026 *
5027 * Returns 0 on success or error on failure
5028 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305029int adm_send_compressed_device_mute(int port_id, int copp_idx, bool mute_on)
5030{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005031 u32 mute_param = mute_on ? 1 : 0;
5032 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305033 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305034
5035 pr_debug("%s port_id: 0x%x, copp_idx %d, mute_on: %d\n",
5036 __func__, port_id, copp_idx, mute_on);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305037
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005038 memset(&param_hdr, 0, sizeof(param_hdr));
5039 param_hdr.module_id = AUDPROC_MODULE_ID_COMPRESSED_MUTE;
5040 param_hdr.instance_id = INSTANCE_ID_0;
5041 param_hdr.param_id = AUDPROC_PARAM_ID_COMPRESSED_MUTE;
5042 param_hdr.param_size = sizeof(mute_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305043
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005044 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
5045 (uint8_t *) &mute_param);
5046 if (ret)
5047 pr_err("%s: Failed to set mute, err %d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305048
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305049 return ret;
5050}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305051EXPORT_SYMBOL(adm_send_compressed_device_mute);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305052
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305053/**
5054 * adm_send_compressed_device_latency -
5055 * command to send latency for compressed device
5056 *
5057 * @port_id: Port ID number
5058 * @copp_idx: copp index assigned
5059 * @latency: latency value to pass
5060 *
5061 * Returns 0 on success or error on failure
5062 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305063int adm_send_compressed_device_latency(int port_id, int copp_idx, int latency)
5064{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005065 u32 latency_param;
5066 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305067 int ret = 0;
5068
5069 pr_debug("%s port_id: 0x%x, copp_idx %d latency: %d\n", __func__,
5070 port_id, copp_idx, latency);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005071
5072 if (latency < 0) {
5073 pr_err("%s: Invalid value for latency %d", __func__, latency);
5074 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305075 }
5076
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005077 memset(&param_hdr, 0, sizeof(param_hdr));
5078 param_hdr.module_id = AUDPROC_MODULE_ID_COMPRESSED_LATENCY;
5079 param_hdr.instance_id = INSTANCE_ID_0;
5080 param_hdr.param_id = AUDPROC_PARAM_ID_COMPRESSED_LATENCY;
5081 param_hdr.param_size = sizeof(latency_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305082
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005083 latency_param = latency;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305084
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005085 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
5086 (uint8_t *) &latency_param);
5087 if (ret)
5088 pr_err("%s: Failed to set latency, err %d\n", __func__, ret);
5089
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305090 return ret;
5091}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305092EXPORT_SYMBOL(adm_send_compressed_device_latency);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305093
5094/**
5095 * adm_swap_speaker_channels
5096 *
5097 * Receives port_id, copp_idx, sample rate, spk_swap and
5098 * send MFC command to swap speaker channel.
5099 * Return zero on success. On failure returns nonzero.
5100 *
5101 * port_id - Passed value, port_id for which channels swap is wanted
5102 * copp_idx - Passed value, copp_idx for which channels swap is wanted
5103 * sample_rate - Passed value, sample rate used by app type config
5104 * spk_swap - Passed value, spk_swap for check if swap flag is set
5105 */
5106int adm_swap_speaker_channels(int port_id, int copp_idx,
5107 int sample_rate, bool spk_swap)
5108{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005109 struct audproc_mfc_param_media_fmt mfc_cfg;
5110 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305111 uint16_t num_channels;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005112 int port_idx = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305113 int ret = 0;
5114
5115 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5116 __func__, port_id, copp_idx);
5117 port_id = q6audio_convert_virtual_to_portid(port_id);
5118 port_idx = adm_validate_and_get_port_index(port_id);
5119 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
5120 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005121 return -EINVAL;
5122 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
5123 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
5124 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305125 }
5126
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005127 num_channels = atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305128 if (num_channels != 2) {
5129 pr_debug("%s: Invalid number of channels: %d\n",
5130 __func__, num_channels);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005131 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305132 }
5133
5134 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005135 memset(&param_hdr, 0, sizeof(param_hdr));
5136
5137 param_hdr.module_id = AUDPROC_MODULE_ID_MFC;
5138 param_hdr.instance_id = INSTANCE_ID_0;
5139 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
5140 param_hdr.param_size = sizeof(mfc_cfg);
5141
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305142 mfc_cfg.sampling_rate = sample_rate;
5143 mfc_cfg.bits_per_sample =
5144 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
5145 mfc_cfg.num_channels = num_channels;
5146
5147 /* Currently applying speaker swap for only 2 channel use case */
5148 if (spk_swap) {
5149 mfc_cfg.channel_type[0] =
5150 (uint16_t) PCM_CHANNEL_FR;
5151 mfc_cfg.channel_type[1] =
5152 (uint16_t) PCM_CHANNEL_FL;
5153 } else {
5154 mfc_cfg.channel_type[0] =
5155 (uint16_t) PCM_CHANNEL_FL;
5156 mfc_cfg.channel_type[1] =
5157 (uint16_t) PCM_CHANNEL_FR;
5158 }
5159
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005160 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
5161 (u8 *) &mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305162 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005163 pr_err("%s: Failed to set swap speaker channels on port[0x%x] failed %d\n",
5164 __func__, port_id, ret);
5165 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305166 }
5167
5168 pr_debug("%s: mfc_cfg Set params returned success", __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005169 return 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305170}
5171EXPORT_SYMBOL(adm_swap_speaker_channels);
5172
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305173/**
5174 * adm_set_sound_focus -
5175 * Update sound focus info
5176 *
5177 * @port_id: Port ID number
5178 * @copp_idx: copp index assigned
5179 * @soundFocusData: sound focus data to pass
5180 *
5181 * Returns 0 on success or error on failure
5182 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305183int adm_set_sound_focus(int port_id, int copp_idx,
5184 struct sound_focus_param soundFocusData)
5185{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005186 struct adm_param_fluence_soundfocus_t soundfocus_params;
5187 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305188 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305189 int i;
5190
5191 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5192 __func__, port_id, copp_idx);
5193
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005194 memset(&param_hdr, 0, sizeof(param_hdr));
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005195 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005196 param_hdr.instance_id = INSTANCE_ID_0;
5197 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
5198 param_hdr.param_size = sizeof(soundfocus_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305199
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005200 memset(&(soundfocus_params), 0xFF, sizeof(soundfocus_params));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305201 for (i = 0; i < MAX_SECTORS; i++) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005202 soundfocus_params.start_angles[i] =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305203 soundFocusData.start_angle[i];
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005204 soundfocus_params.enables[i] = soundFocusData.enable[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305205 pr_debug("%s: start_angle[%d] = %d\n",
5206 __func__, i, soundFocusData.start_angle[i]);
5207 pr_debug("%s: enable[%d] = %d\n",
5208 __func__, i, soundFocusData.enable[i]);
5209 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005210 soundfocus_params.gain_step = soundFocusData.gain_step;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305211 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData.gain_step);
5212
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005213 soundfocus_params.reserved = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305214
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005215 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
5216 (uint8_t *) &soundfocus_params);
5217 if (ret)
5218 pr_err("%s: Failed to set sound focus params, err %d\n",
5219 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305220
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305221 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
5222
5223 return ret;
5224}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305225EXPORT_SYMBOL(adm_set_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305226
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305227/**
5228 * adm_get_sound_focus -
5229 * Retrieve sound focus info
5230 *
5231 * @port_id: Port ID number
5232 * @copp_idx: copp index assigned
5233 * @soundFocusData: pointer for sound focus data to be updated with
5234 *
5235 * Returns 0 on success or error on failure
5236 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305237int adm_get_sound_focus(int port_id, int copp_idx,
5238 struct sound_focus_param *soundFocusData)
5239{
5240 int ret = 0, i;
5241 char *params_value;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005242 uint32_t max_param_size = 0;
5243 struct adm_param_fluence_soundfocus_t *soundfocus_params = NULL;
5244 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305245
5246 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5247 __func__, port_id, copp_idx);
5248
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005249 max_param_size = sizeof(struct adm_param_fluence_soundfocus_t) +
5250 sizeof(union param_hdrs);
5251 params_value = kzalloc(max_param_size, GFP_KERNEL);
5252 if (!params_value)
5253 return -ENOMEM;
5254
5255 memset(&param_hdr, 0, sizeof(param_hdr));
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005256 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005257 param_hdr.instance_id = INSTANCE_ID_0;
5258 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
5259 param_hdr.param_size = max_param_size;
5260 ret = adm_get_pp_params(port_id, copp_idx,
5261 ADM_CLIENT_ID_SOURCE_TRACKING, NULL, &param_hdr,
5262 params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305263 if (ret) {
5264 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305265 ret = -EINVAL;
5266 goto done;
5267 }
5268
5269 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
5270 pr_err("%s - get params returned error [%s]\n",
5271 __func__, adsp_err_get_err_str(
5272 this_adm.sourceTrackingData.apr_cmd_status));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305273 ret = adsp_err_get_lnx_err_code(
5274 this_adm.sourceTrackingData.apr_cmd_status);
5275 goto done;
5276 }
5277
5278 soundfocus_params = (struct adm_param_fluence_soundfocus_t *)
5279 params_value;
5280 for (i = 0; i < MAX_SECTORS; i++) {
5281 soundFocusData->start_angle[i] =
5282 soundfocus_params->start_angles[i];
5283 soundFocusData->enable[i] = soundfocus_params->enables[i];
5284 pr_debug("%s: start_angle[%d] = %d\n",
5285 __func__, i, soundFocusData->start_angle[i]);
5286 pr_debug("%s: enable[%d] = %d\n",
5287 __func__, i, soundFocusData->enable[i]);
5288 }
5289 soundFocusData->gain_step = soundfocus_params->gain_step;
5290 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData->gain_step);
5291
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305292done:
5293 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5294
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005295 kfree(params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305296 return ret;
5297}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305298EXPORT_SYMBOL(adm_get_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305299
5300static int adm_source_tracking_alloc_map_memory(void)
5301{
5302 int ret;
5303
5304 pr_debug("%s: Enter\n", __func__);
5305
Banajit Goswami08bb7362017-11-03 22:48:23 -07005306 ret = msm_audio_ion_alloc(&this_adm.sourceTrackingData.dma_buf,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305307 AUD_PROC_BLOCK_SIZE,
5308 &this_adm.sourceTrackingData.memmap.paddr,
5309 &this_adm.sourceTrackingData.memmap.size,
5310 &this_adm.sourceTrackingData.memmap.kvaddr);
5311 if (ret) {
5312 pr_err("%s: failed to allocate memory\n", __func__);
5313
5314 ret = -EINVAL;
5315 goto done;
5316 }
5317
5318 atomic_set(&this_adm.mem_map_index, ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
5319 ret = adm_memory_map_regions(&this_adm.sourceTrackingData.memmap.paddr,
5320 0,
5321 (uint32_t *)&this_adm.sourceTrackingData.memmap.size,
5322 1);
5323 if (ret < 0) {
5324 pr_err("%s: failed to map memory, paddr = 0x%pK, size = %d\n",
5325 __func__,
5326 (void *)this_adm.sourceTrackingData.memmap.paddr,
5327 (uint32_t)this_adm.sourceTrackingData.memmap.size);
5328
Banajit Goswami08bb7362017-11-03 22:48:23 -07005329 msm_audio_ion_free(this_adm.sourceTrackingData.dma_buf);
5330 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305331 this_adm.sourceTrackingData.memmap.size = 0;
5332 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5333 this_adm.sourceTrackingData.memmap.paddr = 0;
5334 this_adm.sourceTrackingData.apr_cmd_status = -1;
5335 atomic_set(&this_adm.mem_map_handles
5336 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
5337
5338 ret = -EINVAL;
5339 goto done;
5340 }
5341 ret = 0;
5342 pr_debug("%s: paddr = 0x%pK, size = %d, mem_map_handle = 0x%x\n",
5343 __func__, (void *)this_adm.sourceTrackingData.memmap.paddr,
5344 (uint32_t)this_adm.sourceTrackingData.memmap.size,
5345 atomic_read(&this_adm.mem_map_handles
5346 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING]));
5347
5348done:
5349 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5350
5351 return ret;
5352}
5353
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305354/**
5355 * adm_get_source_tracking -
5356 * Retrieve source tracking info
5357 *
5358 * @port_id: Port ID number
5359 * @copp_idx: copp index assigned
5360 * @sourceTrackingData: pointer for source track data to be updated with
5361 *
5362 * Returns 0 on success or error on failure
5363 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305364int adm_get_source_tracking(int port_id, int copp_idx,
5365 struct source_tracking_param *sourceTrackingData)
5366{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005367 struct adm_param_fluence_sourcetracking_t *source_tracking_params =
5368 NULL;
5369 struct mem_mapping_hdr mem_hdr;
5370 struct param_hdr_v3 param_hdr;
5371 int i = 0;
5372 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305373
5374 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5375 __func__, port_id, copp_idx);
5376
5377 if (!this_adm.sourceTrackingData.memmap.paddr) {
5378 /* Allocate and map shared memory for out of band usage */
5379 ret = adm_source_tracking_alloc_map_memory();
5380 if (ret != 0) {
5381 ret = -EINVAL;
5382 goto done;
5383 }
5384 }
5385
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005386 memset(&mem_hdr, 0, sizeof(mem_hdr));
5387 memset(&param_hdr, 0, sizeof(param_hdr));
5388 mem_hdr.data_payload_addr_lsw =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305389 lower_32_bits(this_adm.sourceTrackingData.memmap.paddr);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005390 mem_hdr.data_payload_addr_msw = msm_audio_populate_upper_32_bits(
5391 this_adm.sourceTrackingData.memmap.paddr);
5392 mem_hdr.mem_map_handle = atomic_read(
5393 &this_adm.mem_map_handles[ADM_MEM_MAP_INDEX_SOURCE_TRACKING]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305394
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005395 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005396 param_hdr.instance_id = INSTANCE_ID_0;
5397 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOURCETRACKING;
5398 /*
5399 * This size should be the max size of the calibration data + header.
5400 * Use the union size to ensure max size is used.
5401 */
5402 param_hdr.param_size =
5403 sizeof(struct adm_param_fluence_sourcetracking_t) +
Avinash Chandra13d9c562020-04-27 19:23:49 +05305404 sizeof(struct param_hdr_v3);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305405
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005406 /*
5407 * Retrieving parameters out of band, so no need to provide a buffer for
5408 * the returned parameter data as it will be at the memory location
5409 * provided.
5410 */
5411 ret = adm_get_pp_params(port_id, copp_idx,
5412 ADM_CLIENT_ID_SOURCE_TRACKING, &mem_hdr,
5413 &param_hdr, NULL);
5414 if (ret) {
5415 pr_err("%s: Failed to get params, error %d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305416 goto done;
5417 }
5418
5419 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
5420 pr_err("%s - get params returned error [%s]\n",
5421 __func__, adsp_err_get_err_str(
5422 this_adm.sourceTrackingData.apr_cmd_status));
5423
5424 ret = adsp_err_get_lnx_err_code(
5425 this_adm.sourceTrackingData.apr_cmd_status);
5426 goto done;
5427 }
5428
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005429 /* How do we know what the param data was retrieved with for hdr size */
5430 source_tracking_params =
5431 (struct adm_param_fluence_sourcetracking_t
5432 *) (this_adm.sourceTrackingData.memmap.kvaddr +
Avinash Chandra13d9c562020-04-27 19:23:49 +05305433 sizeof(struct param_hdr_v3));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305434 for (i = 0; i < MAX_SECTORS; i++) {
5435 sourceTrackingData->vad[i] = source_tracking_params->vad[i];
5436 pr_debug("%s: vad[%d] = %d\n",
5437 __func__, i, sourceTrackingData->vad[i]);
5438 }
5439 sourceTrackingData->doa_speech = source_tracking_params->doa_speech;
5440 pr_debug("%s: doa_speech = %d\n",
5441 __func__, sourceTrackingData->doa_speech);
5442
5443 for (i = 0; i < MAX_NOISE_SOURCE_INDICATORS; i++) {
5444 sourceTrackingData->doa_noise[i] =
5445 source_tracking_params->doa_noise[i];
5446 pr_debug("%s: doa_noise[%d] = %d\n",
5447 __func__, i, sourceTrackingData->doa_noise[i]);
5448 }
5449 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
5450 sourceTrackingData->polar_activity[i] =
5451 source_tracking_params->polar_activity[i];
5452 pr_debug("%s: polar_activity[%d] = %d\n",
5453 __func__, i, sourceTrackingData->polar_activity[i]);
5454 }
5455
5456 ret = 0;
5457
5458done:
5459 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
5460
5461 return ret;
5462}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305463EXPORT_SYMBOL(adm_get_source_tracking);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305464
Chaithanya Krishna Bacharaju8c6a1842018-11-16 15:02:39 +05305465/**
5466 * adm_get_doa_tracking_mon -
5467 * Retrieve doa tracking monitor info
5468 *
5469 * @port_id: Port ID number
5470 * @copp_idx: copp index assigned
5471 * @doa_tracking_data: pointer for doa data to be updated with
5472 *
5473 * Returns 0 on success or error on failure
5474 */
5475int adm_get_doa_tracking_mon(int port_id, int copp_idx,
5476 struct doa_tracking_mon_param *doa_tracking_data)
5477{
5478 int ret = 0, i;
5479 char *params_value;
5480 uint32_t max_param_size = 0;
5481 struct adm_param_doa_tracking_mon_t *doa_tracking_params = NULL;
5482 struct param_hdr_v3 param_hdr;
5483
5484 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5485 __func__, port_id, copp_idx);
5486
5487 if (doa_tracking_data == NULL) {
5488 pr_err("%s: Received NULL pointer for doa tracking data\n",
5489 __func__);
5490 return -EINVAL;
5491 }
5492
5493 max_param_size = sizeof(struct adm_param_doa_tracking_mon_t) +
5494 sizeof(union param_hdrs);
5495 params_value = kzalloc(max_param_size, GFP_KERNEL);
5496 if (!params_value)
5497 return -ENOMEM;
5498
5499 memset(&param_hdr, 0, sizeof(param_hdr));
5500 param_hdr.module_id = AUDPROC_MODULE_ID_FFECNS;
5501 param_hdr.instance_id = INSTANCE_ID_0;
5502 param_hdr.param_id = AUDPROC_PARAM_ID_FFV_DOA_TRACKING_MONITOR;
5503 param_hdr.param_size = max_param_size;
5504 ret = adm_get_pp_params(port_id, copp_idx,
5505 ADM_CLIENT_ID_DEFAULT, NULL, &param_hdr,
5506 params_value);
5507 if (ret) {
5508 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
5509 goto done;
5510 }
5511
5512 doa_tracking_params =
5513 (struct adm_param_doa_tracking_mon_t *)params_value;
5514 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
5515 doa_tracking_data->target_angle_L16[i] =
5516 doa_tracking_params->target_angle_L16[i];
5517 pr_debug("%s: target angle[%d] = %d\n",
5518 __func__, i, doa_tracking_data->target_angle_L16[i]);
5519 }
5520
5521 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
5522 doa_tracking_data->interf_angle_L16[i] =
5523 doa_tracking_params->interf_angle_L16[i];
5524 pr_debug("%s: interference angle[%d] = %d\n",
5525 __func__, i, doa_tracking_data->interf_angle_L16[i]);
5526 }
5527
5528 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
5529 doa_tracking_data->polar_activity[i] =
5530 doa_tracking_params->polar_activity[i];
5531 }
5532
5533done:
5534 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5535 kfree(params_value);
5536 return ret;
5537}
5538EXPORT_SYMBOL(adm_get_doa_tracking_mon);
5539
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305540int __init adm_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305541{
5542 int i = 0, j;
5543
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305544 this_adm.ec_ref_rx = -1;
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08005545 this_adm.ffecns_port_id = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305546 init_waitqueue_head(&this_adm.matrix_map_wait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305547 init_waitqueue_head(&this_adm.adm_wait);
Soumya Managoli97f90ea2020-04-28 09:16:55 +05305548 mutex_init(&this_adm.adm_apr_lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305549
5550 for (i = 0; i < AFE_MAX_PORTS; i++) {
5551 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
5552 atomic_set(&this_adm.copp.id[i][j], RESET_COPP_ID);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305553 init_waitqueue_head(&this_adm.copp.wait[i][j]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305554 init_waitqueue_head(
5555 &this_adm.copp.adm_delay_wait[i][j]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305556 }
5557 }
5558
5559 if (adm_init_cal_data())
5560 pr_err("%s: could not init cal data!\n", __func__);
5561
Banajit Goswami08bb7362017-11-03 22:48:23 -07005562 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305563 this_adm.sourceTrackingData.memmap.size = 0;
5564 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5565 this_adm.sourceTrackingData.memmap.paddr = 0;
5566 this_adm.sourceTrackingData.apr_cmd_status = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305567
5568 return 0;
5569}
5570
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05305571void adm_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305572{
Soumya Managoli97f90ea2020-04-28 09:16:55 +05305573 mutex_destroy(&this_adm.adm_apr_lock);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05305574 if (this_adm.apr)
5575 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305576 adm_delete_cal_data();
5577}