blob: e63547d85738235b5a95fb9fc02a6851f134f3d1 [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,
Soumya Managolid0adc6a2021-02-24 19:33:53 +0530877 int port_idx, int copp_idx, int opcode)
Soumya Managoli97f90ea2020-04-28 09:16:55 +0530878{
879 int ret = 0;
880 atomic_t *copp_stat = NULL;
Soumya Managolid0adc6a2021-02-24 19:33:53 +0530881 int32_t time_out = msecs_to_jiffies(TIMEOUT_MS);
Soumya Managoli97f90ea2020-04-28 09:16:55 +0530882 wait = &this_adm.copp.wait[port_idx][copp_idx];
883
884 if (!wait)
885 return -EINVAL;
886
887 mutex_lock(&this_adm.adm_apr_lock);
888 pr_debug("%s: port idx %d copp idx %d\n", __func__,
889 port_idx, copp_idx);
890 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
891 atomic_set(copp_stat, -1);
892
Soumya Managolid0adc6a2021-02-24 19:33:53 +0530893 if (opcode != ADM_CMD_DEVICE_OPEN_V8 &&
894 opcode != ADM_CMD_DEVICE_OPEN_V6 &&
895 opcode != ADM_CMD_DEVICE_OPEN_V5 &&
896 opcode != ADM_CMD_DEVICE_CLOSE_V5) {
897 if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx])
898 == 0) {
899 pr_err("%s: port[0x%x] copp[0x%x] inactive\n",
900 __func__, port_idx, copp_idx);
901 mutex_unlock(&this_adm.adm_apr_lock);
902 return -EINVAL;
903 }
904 }
905
906 if (opcode == ADM_CMD_DEVICE_OPEN_V8 ||
907 opcode == ADM_CMD_DEVICE_OPEN_V6 ||
908 opcode == ADM_CMD_DEVICE_OPEN_V5) {
909 time_out = msecs_to_jiffies(2 * TIMEOUT_MS);
Soumya Managoli97f90ea2020-04-28 09:16:55 +0530910 }
911
912 ret = apr_send_pkt(this_adm.apr, data);
913 if (ret > 0) {
914 ret = wait_event_timeout(*wait,
915 atomic_read(copp_stat) >= 0,
Soumya Managolid0adc6a2021-02-24 19:33:53 +0530916 time_out);
Soumya Managoli97f90ea2020-04-28 09:16:55 +0530917 if (atomic_read(copp_stat) > 0) {
918 pr_err("%s: DSP returned error[%s]\n", __func__,
919 adsp_err_get_err_str(atomic_read(copp_stat)));
920 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
921 } else if (!ret) {
922 pr_err_ratelimited("%s: request timedout\n",
923 __func__);
924 ret = -ETIMEDOUT;
925 } else {
926 ret = 0;
927 }
928 } else if (ret == 0) {
929 pr_err("%s: packet not transmitted\n", __func__);
930 /* apr_send_pkt can return 0 when nothing is transmitted */
931 ret = -EINVAL;
932 }
933
934 mutex_unlock(&this_adm.adm_apr_lock);
935 return ret;
936}
937
938/*
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800939 * With pre-packed data, only the opcode differes from V5 and V6.
940 * Use q6common_pack_pp_params to pack the data correctly.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530941 */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800942int adm_set_pp_params(int port_id, int copp_idx,
943 struct mem_mapping_hdr *mem_hdr, u8 *param_data,
944 u32 param_size)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530945{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800946 struct adm_cmd_set_pp_params *adm_set_params = NULL;
947 int size = 0;
948 int port_idx = 0;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800949 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530950
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530951 port_id = afe_convert_virtual_to_portid(port_id);
952 port_idx = adm_validate_and_get_port_index(port_id);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800953 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
954 pr_err("%s: Invalid port_idx 0x%x\n", __func__, port_idx);
955 return -EINVAL;
956 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
957 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530958 return -EINVAL;
959 }
960
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800961 /* Only add params_size in inband case */
962 size = sizeof(struct adm_cmd_set_pp_params);
963 if (param_data != NULL)
964 size += param_size;
965 adm_set_params = kzalloc(size, GFP_KERNEL);
966 if (!adm_set_params)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530967 return -ENOMEM;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800968
969 adm_set_params->apr_hdr.hdr_field =
970 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
971 APR_PKT_VER);
972 adm_set_params->apr_hdr.pkt_size = size;
973 adm_set_params->apr_hdr.src_svc = APR_SVC_ADM;
974 adm_set_params->apr_hdr.src_domain = APR_DOMAIN_APPS;
975 adm_set_params->apr_hdr.src_port = port_id;
976 adm_set_params->apr_hdr.dest_svc = APR_SVC_ADM;
977 adm_set_params->apr_hdr.dest_domain = APR_DOMAIN_ADSP;
978 adm_set_params->apr_hdr.dest_port =
979 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
980 adm_set_params->apr_hdr.token = port_idx << 16 | copp_idx;
981
982 if (q6common_is_instance_id_supported())
983 adm_set_params->apr_hdr.opcode = ADM_CMD_SET_PP_PARAMS_V6;
984 else
985 adm_set_params->apr_hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
986
987 adm_set_params->payload_size = param_size;
988
989 if (mem_hdr != NULL) {
990 /* Out of Band Case */
991 adm_set_params->mem_hdr = *mem_hdr;
992 } else if (param_data != NULL) {
993 /*
994 * In band case. Parameter data must be pre-packed with its
995 * header before calling this function. Use
996 * q6common_pack_pp_params to pack parameter data and header
997 * correctly.
998 */
999 memcpy(&adm_set_params->param_data, param_data, param_size);
1000 } else {
1001 pr_err("%s: Received NULL pointers for both memory header and param data\n",
1002 __func__);
1003 ret = -EINVAL;
1004 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301005 }
Soumya Managoli97f90ea2020-04-28 09:16:55 +05301006 ret = adm_apr_send_pkt((uint32_t *) adm_set_params,
1007 &this_adm.copp.wait[port_idx][copp_idx],
Soumya Managolid0adc6a2021-02-24 19:33:53 +05301008 port_idx, copp_idx, adm_set_params->apr_hdr.opcode);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001009done:
1010 kfree(adm_set_params);
1011 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301012}
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001013EXPORT_SYMBOL(adm_set_pp_params);
1014
1015int adm_pack_and_set_one_pp_param(int port_id, int copp_idx,
1016 struct param_hdr_v3 param_hdr, u8 *param_data)
1017{
1018 u8 *packed_data = NULL;
1019 u32 total_size = 0;
1020 int ret = 0;
1021
1022 total_size = sizeof(union param_hdrs) + param_hdr.param_size;
1023 packed_data = kzalloc(total_size, GFP_KERNEL);
1024 if (!packed_data)
1025 return -ENOMEM;
1026
1027 ret = q6common_pack_pp_params(packed_data, &param_hdr, param_data,
1028 &total_size);
1029 if (ret) {
1030 pr_err("%s: Failed to pack parameter data, error %d\n",
1031 __func__, ret);
1032 goto done;
1033 }
1034
1035 ret = adm_set_pp_params(port_id, copp_idx, NULL, packed_data,
1036 total_size);
1037 if (ret)
1038 pr_err("%s: Failed to set parameter data, error %d\n", __func__,
1039 ret);
1040done:
1041 kfree(packed_data);
1042 return ret;
1043}
1044EXPORT_SYMBOL(adm_pack_and_set_one_pp_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301045
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001046/*
1047 * Only one parameter can be requested at a time. Therefore, packing and sending
1048 * the request can be handled locally.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301049 */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001050int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id,
1051 struct mem_mapping_hdr *mem_hdr,
1052 struct param_hdr_v3 *param_hdr, u8 *returned_param_data)
1053{
1054 struct adm_cmd_get_pp_params adm_get_params;
1055 int total_size = 0;
1056 int get_param_array_sz = ARRAY_SIZE(adm_get_parameters);
1057 int returned_param_size = 0;
1058 int returned_param_size_in_bytes = 0;
1059 int port_idx = 0;
1060 int idx = 0;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001061 int ret = 0;
1062
1063 if (param_hdr == NULL) {
1064 pr_err("%s: Received NULL pointer for parameter header\n",
1065 __func__);
1066 return -EINVAL;
1067 }
1068
1069 port_id = afe_convert_virtual_to_portid(port_id);
1070 port_idx = adm_validate_and_get_port_index(port_id);
1071 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1072 pr_err("%s: Invalid port_idx 0x%x\n", __func__, port_idx);
1073 return -EINVAL;
1074 }
1075 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1076 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
1077 return -EINVAL;
1078 }
1079
1080 memset(&adm_get_params, 0, sizeof(adm_get_params));
1081
1082 if (mem_hdr != NULL)
1083 adm_get_params.mem_hdr = *mem_hdr;
1084
1085 q6common_pack_pp_params((u8 *) &adm_get_params.param_hdr, param_hdr,
1086 NULL, &total_size);
1087
1088 /* Pack APR header after filling body so total_size has correct value */
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001089 adm_get_params.apr_hdr.hdr_field =
1090 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1091 APR_PKT_VER);
1092 adm_get_params.apr_hdr.pkt_size = sizeof(adm_get_params);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001093 adm_get_params.apr_hdr.src_svc = APR_SVC_ADM;
1094 adm_get_params.apr_hdr.src_domain = APR_DOMAIN_APPS;
1095 adm_get_params.apr_hdr.src_port = port_id;
1096 adm_get_params.apr_hdr.dest_svc = APR_SVC_ADM;
1097 adm_get_params.apr_hdr.dest_domain = APR_DOMAIN_ADSP;
1098 adm_get_params.apr_hdr.dest_port =
1099 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1100 adm_get_params.apr_hdr.token =
1101 port_idx << 16 | client_id << 8 | copp_idx;
1102
1103 if (q6common_is_instance_id_supported())
1104 adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V6;
1105 else
1106 adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
1107
Soumya Managolid0adc6a2021-02-24 19:33:53 +05301108 ret = adm_apr_send_pkt((uint32_t *) &adm_get_params,
1109 &this_adm.copp.wait[port_idx][copp_idx],
1110 port_idx, copp_idx, adm_get_params.apr_hdr.opcode);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001111
1112 /* Copy data to caller if sent in band */
1113 if (!returned_param_data) {
1114 pr_debug("%s: Received NULL pointer for param destination, not copying payload\n",
1115 __func__);
1116 return 0;
1117 }
1118
1119 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
1120 returned_param_size = adm_get_parameters[idx];
1121 if (returned_param_size < 0 ||
1122 returned_param_size + idx + 1 > get_param_array_sz) {
1123 pr_err("%s: Invalid parameter size %d\n", __func__,
1124 returned_param_size);
1125 return -EINVAL;
1126 }
1127
1128 returned_param_size_in_bytes = returned_param_size * sizeof(uint32_t);
1129 if (param_hdr->param_size < returned_param_size_in_bytes) {
1130 pr_err("%s: Provided buffer is not big enough, provided buffer size(%d) size needed(%d)\n",
1131 __func__, param_hdr->param_size,
1132 returned_param_size_in_bytes);
1133 return -EINVAL;
1134 }
1135
1136 memcpy(returned_param_data, &adm_get_parameters[idx + 1],
1137 returned_param_size_in_bytes);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001138 return ret;
1139}
1140EXPORT_SYMBOL(adm_get_pp_params);
1141
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001142int adm_get_pp_topo_module_list_v2(int port_id, int copp_idx,
1143 int32_t param_length,
1144 int32_t *returned_params)
1145{
1146 struct adm_cmd_get_pp_topo_module_list adm_get_module_list;
1147 bool iid_supported = q6common_is_instance_id_supported();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301148 int *topo_list;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001149 int num_modules = 0;
1150 int list_size = 0;
1151 int port_idx, idx;
1152 int i = 0;
1153 atomic_t *copp_stat = NULL;
1154 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301155
1156 pr_debug("%s : port_id %x", __func__, port_id);
1157 port_id = afe_convert_virtual_to_portid(port_id);
1158 port_idx = adm_validate_and_get_port_index(port_id);
1159 if (port_idx < 0) {
1160 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1161 return -EINVAL;
1162 }
1163
1164 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1165 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
1166 return -EINVAL;
1167 }
1168
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001169 memset(&adm_get_module_list, 0, sizeof(adm_get_module_list));
1170
1171 adm_get_module_list.apr_hdr.pkt_size = sizeof(adm_get_module_list);
1172 adm_get_module_list.apr_hdr.src_svc = APR_SVC_ADM;
1173 adm_get_module_list.apr_hdr.src_domain = APR_DOMAIN_APPS;
1174 adm_get_module_list.apr_hdr.src_port = port_id;
1175 adm_get_module_list.apr_hdr.dest_svc = APR_SVC_ADM;
1176 adm_get_module_list.apr_hdr.dest_domain = APR_DOMAIN_ADSP;
1177 adm_get_module_list.apr_hdr.dest_port =
1178 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1179 adm_get_module_list.apr_hdr.token = port_idx << 16 | copp_idx;
1180 /*
1181 * Out of band functionality is not currently utilized.
1182 * Assume in band.
1183 */
1184 if (iid_supported) {
1185 adm_get_module_list.apr_hdr.opcode =
1186 ADM_CMD_GET_PP_TOPO_MODULE_LIST_V2;
1187 adm_get_module_list.param_max_size = param_length;
1188 } else {
1189 adm_get_module_list.apr_hdr.opcode =
1190 ADM_CMD_GET_PP_TOPO_MODULE_LIST;
1191
1192 if (param_length > U16_MAX) {
1193 pr_err("%s: Invalid param length for V1 %d\n", __func__,
1194 param_length);
1195 return -EINVAL;
1196 }
1197 adm_get_module_list.param_max_size = param_length << 16;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301198 }
1199
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001200 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
1201 atomic_set(copp_stat, -1);
1202 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_module_list);
Vidyakumar Athotae427c412018-06-16 00:02:46 -07001203 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001204 pr_err("%s: APR send pkt failed for port_id: 0x%x failed ret %d\n",
1205 __func__, port_id, ret);
1206 ret = -EINVAL;
1207 goto done;
1208 }
1209 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1210 atomic_read(copp_stat) >= 0,
1211 msecs_to_jiffies(TIMEOUT_MS));
1212 if (!ret) {
1213 pr_err("%s: Timeout for port_id: 0x%x\n", __func__, port_id);
1214 ret = -ETIMEDOUT;
1215 goto done;
1216 }
1217 if (atomic_read(copp_stat) > 0) {
1218 pr_err("%s: DSP returned error[%s]\n", __func__,
1219 adsp_err_get_err_str(atomic_read(copp_stat)));
1220 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
1221 goto done;
1222 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301223
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001224 ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301225
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001226 if (returned_params) {
1227 /*
1228 * When processing ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST IID is
1229 * added since it is not present. Therefore, there is no need to
1230 * do anything different if IID is not supported here as it is
1231 * already taken care of.
1232 */
1233 idx = ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH * copp_idx;
1234 num_modules = adm_module_topo_list[idx];
1235 if (num_modules < 0 || num_modules > MAX_MODULES_IN_TOPO) {
1236 pr_err("%s: Invalid number of modules returned %d\n",
1237 __func__, num_modules);
1238 return -EINVAL;
1239 }
1240
1241 list_size = num_modules * sizeof(struct module_instance_info);
1242 if (param_length < list_size) {
1243 pr_err("%s: Provided buffer not big enough to hold module-instance list, provided size %d, needed size %d\n",
1244 __func__, param_length, list_size);
1245 return -EINVAL;
1246 }
1247
1248 topo_list = (int32_t *) (&adm_module_topo_list[idx]);
1249 memcpy(returned_params, topo_list, list_size);
1250 for (i = 1; i <= num_modules; i += 2) {
1251 pr_debug("module = 0x%x instance = 0x%x\n",
1252 returned_params[i], returned_params[i + 1]);
1253 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301254 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001255done:
1256 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301257}
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001258EXPORT_SYMBOL(adm_get_pp_topo_module_list_v2);
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301259
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301260static void adm_callback_debug_print(struct apr_client_data *data)
1261{
1262 uint32_t *payload;
1263
1264 payload = data->payload;
1265
1266 if (data->payload_size >= 8)
1267 pr_debug("%s: code = 0x%x PL#0[0x%x], PL#1[0x%x], size = %d\n",
1268 __func__, data->opcode, payload[0], payload[1],
1269 data->payload_size);
1270 else if (data->payload_size >= 4)
1271 pr_debug("%s: code = 0x%x PL#0[0x%x], size = %d\n",
1272 __func__, data->opcode, payload[0],
1273 data->payload_size);
1274 else
1275 pr_debug("%s: code = 0x%x, size = %d\n",
1276 __func__, data->opcode, data->payload_size);
1277}
1278
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301279/**
1280 * adm_set_multi_ch_map -
1281 * Update multi channel map info
1282 *
1283 * @channel_map: pointer with channel map info
1284 * @path: direction or ADM path type
1285 *
1286 * Returns 0 on success or error on failure
1287 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301288int adm_set_multi_ch_map(char *channel_map, int path)
1289{
1290 int idx;
1291
1292 if (path == ADM_PATH_PLAYBACK) {
1293 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1294 } else if (path == ADM_PATH_LIVE_REC) {
1295 idx = ADM_MCH_MAP_IDX_REC;
1296 } else {
1297 pr_err("%s: invalid attempt to set path %d\n", __func__, path);
1298 return -EINVAL;
1299 }
1300
1301 memcpy(multi_ch_maps[idx].channel_mapping, channel_map,
Dieter Luecking50c55352018-09-28 14:29:17 +02001302 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301303 multi_ch_maps[idx].set_channel_map = true;
1304
1305 return 0;
1306}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301307EXPORT_SYMBOL(adm_set_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301308
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301309/**
1310 * adm_get_multi_ch_map -
1311 * Retrieves multi channel map info
1312 *
1313 * @channel_map: pointer to be updated with channel map
1314 * @path: direction or ADM path type
1315 *
1316 * Returns 0 on success or error on failure
1317 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301318int adm_get_multi_ch_map(char *channel_map, int path)
1319{
1320 int idx;
1321
1322 if (path == ADM_PATH_PLAYBACK) {
1323 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1324 } else if (path == ADM_PATH_LIVE_REC) {
1325 idx = ADM_MCH_MAP_IDX_REC;
1326 } else {
1327 pr_err("%s: invalid attempt to get path %d\n", __func__, path);
1328 return -EINVAL;
1329 }
1330
1331 if (multi_ch_maps[idx].set_channel_map) {
1332 memcpy(channel_map, multi_ch_maps[idx].channel_mapping,
Dieter Luecking50c55352018-09-28 14:29:17 +02001333 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301334 }
1335
1336 return 0;
1337}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301338EXPORT_SYMBOL(adm_get_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301339
Rohit kumar2054b692019-02-01 18:01:12 +05301340/**
1341 * adm_set_port_multi_ch_map -
1342 * Update port specific channel map info
1343 *
1344 * @channel_map: pointer with channel map info
1345 * @port_id: port for which chmap is set
1346 */
1347void adm_set_port_multi_ch_map(char *channel_map, int port_id)
1348{
1349 int port_idx;
1350
1351 port_id = q6audio_convert_virtual_to_portid(port_id);
1352 port_idx = adm_validate_and_get_port_index(port_id);
1353
1354 if (port_idx < 0) {
1355 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1356 return;
1357 }
1358
1359 memcpy(port_channel_map[port_idx].channel_mapping, channel_map,
1360 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
1361 port_channel_map[port_idx].set_channel_map = true;
1362}
1363EXPORT_SYMBOL(adm_set_port_multi_ch_map);
1364
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001365static int adm_process_get_param_response(u32 opcode, u32 idx, u32 *payload,
1366 u32 payload_size)
1367{
1368 struct adm_cmd_rsp_get_pp_params_v5 *v5_rsp = NULL;
1369 struct adm_cmd_rsp_get_pp_params_v6 *v6_rsp = NULL;
1370 u32 *param_data = NULL;
1371 int data_size = 0;
1372 int struct_size = 0;
1373
1374 if (payload == NULL) {
1375 pr_err("%s: Payload is NULL\n", __func__);
1376 return -EINVAL;
1377 }
1378
1379 switch (opcode) {
1380 case ADM_CMDRSP_GET_PP_PARAMS_V5:
1381 struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v5);
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001382 if (payload_size < struct_size) {
1383 pr_err("%s: payload size %d < expected size %d\n",
1384 __func__, payload_size, struct_size);
1385 break;
1386 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001387 v5_rsp = (struct adm_cmd_rsp_get_pp_params_v5 *) payload;
1388 data_size = v5_rsp->param_hdr.param_size;
1389 param_data = v5_rsp->param_data;
1390 break;
1391 case ADM_CMDRSP_GET_PP_PARAMS_V6:
1392 struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v6);
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001393 if (payload_size < struct_size) {
1394 pr_err("%s: payload size %d < expected size %d\n",
1395 __func__, payload_size, struct_size);
1396 break;
1397 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001398 v6_rsp = (struct adm_cmd_rsp_get_pp_params_v6 *) payload;
1399 data_size = v6_rsp->param_hdr.param_size;
1400 param_data = v6_rsp->param_data;
1401 break;
1402 default:
1403 pr_err("%s: Invalid opcode %d\n", __func__, opcode);
1404 return -EINVAL;
1405 }
1406
1407 /*
1408 * Just store the returned parameter data, not the header. The calling
1409 * function is expected to know what it asked for. Therefore, there is
1410 * no difference between V5 and V6.
1411 */
1412 if ((payload_size >= struct_size + data_size) &&
1413 (ARRAY_SIZE(adm_get_parameters) > idx) &&
Karthikeyan Mani95be5b12018-11-09 14:57:32 -08001414 (ARRAY_SIZE(adm_get_parameters) > idx + 1 + data_size)) {
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001415 pr_debug("%s: Received parameter data in band\n",
1416 __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001417 /*
1418 * data_size is expressed in number of bytes, store in number of
1419 * ints
1420 */
1421 adm_get_parameters[idx] =
1422 data_size / sizeof(*adm_get_parameters);
1423 pr_debug("%s: GET_PP PARAM: received parameter length: 0x%x\n",
1424 __func__, adm_get_parameters[idx]);
1425 /* store params after param_size */
1426 memcpy(&adm_get_parameters[idx + 1], param_data, data_size);
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001427 } else if (payload_size == sizeof(uint32_t)) {
1428 adm_get_parameters[idx] = -1;
1429 pr_debug("%s: Out of band case, setting size to %d\n",
1430 __func__, adm_get_parameters[idx]);
1431 } else {
1432 pr_err("%s: Invalid parameter combination, payload_size %d, idx %d\n",
1433 __func__, payload_size, idx);
1434 return -EINVAL;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001435 }
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001436 return 0;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001437}
1438
1439static int adm_process_get_topo_list_response(u32 opcode, int copp_idx,
1440 u32 num_modules, u32 *payload,
1441 u32 payload_size)
1442{
1443 u32 *fill_list = NULL;
1444 int idx = 0;
1445 int i = 0;
1446 int j = 0;
1447
1448 if (payload == NULL) {
1449 pr_err("%s: Payload is NULL\n", __func__);
1450 return -EINVAL;
1451 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1452 pr_err("%s: Invalid COPP index %d\n", __func__, copp_idx);
1453 return -EINVAL;
1454 }
1455
1456 idx = ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH * copp_idx;
1457 fill_list = adm_module_topo_list + idx;
1458 *fill_list++ = num_modules;
1459 for (i = 0; i < num_modules; i++) {
1460 if (j > payload_size / sizeof(u32)) {
1461 pr_err("%s: Invalid number of modules specified %d\n",
1462 __func__, num_modules);
1463 return -EINVAL;
1464 }
1465
1466 /* store module ID */
1467 *fill_list++ = payload[j];
1468 j++;
1469
1470 switch (opcode) {
1471 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
1472 /* store instance ID */
1473 *fill_list++ = payload[j];
1474 j++;
1475 break;
1476 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
1477 /* Insert IID 0 when repacking */
1478 *fill_list++ = INSTANCE_ID_0;
1479 break;
1480 default:
1481 pr_err("%s: Invalid opcode %d\n", __func__, opcode);
1482 return -EINVAL;
1483 }
1484 }
1485
1486 return 0;
1487}
1488
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301489static void adm_reset_data(void)
1490{
1491 int i, j;
1492
1493 apr_reset(this_adm.apr);
1494 for (i = 0; i < AFE_MAX_PORTS; i++) {
1495 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
1496 atomic_set(&this_adm.copp.id[i][j],
1497 RESET_COPP_ID);
1498 atomic_set(&this_adm.copp.cnt[i][j], 0);
1499 atomic_set(
1500 &this_adm.copp.topology[i][j], 0);
1501 atomic_set(&this_adm.copp.mode[i][j],
1502 0);
1503 atomic_set(&this_adm.copp.stat[i][j],
1504 0);
1505 atomic_set(&this_adm.copp.rate[i][j],
1506 0);
1507 atomic_set(
1508 &this_adm.copp.channels[i][j],
1509 0);
1510 atomic_set(
1511 &this_adm.copp.bit_width[i][j], 0);
1512 atomic_set(
1513 &this_adm.copp.app_type[i][j], 0);
1514 atomic_set(
1515 &this_adm.copp.acdb_id[i][j], 0);
Surendar Karkae7507512018-07-20 15:46:54 +05301516 atomic_set(
1517 &this_adm.copp.session_type[i][j], 0);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301518 this_adm.copp.adm_status[i][j] =
1519 ADM_STATUS_CALIBRATION_REQUIRED;
1520 }
1521 }
1522 this_adm.apr = NULL;
1523 cal_utils_clear_cal_block_q6maps(ADM_MAX_CAL_TYPES,
1524 this_adm.cal_data);
1525 mutex_lock(&this_adm.cal_data
1526 [ADM_CUSTOM_TOP_CAL]->lock);
1527 this_adm.set_custom_topology = 1;
1528 mutex_unlock(&this_adm.cal_data[
1529 ADM_CUSTOM_TOP_CAL]->lock);
1530 rtac_clear_mapping(ADM_RTAC_CAL);
1531 /*
1532 * Free the ION memory and clear the map handles
1533 * for Source Tracking
1534 */
1535 if (this_adm.sourceTrackingData.memmap.paddr != 0) {
1536 msm_audio_ion_free(
1537 this_adm.sourceTrackingData.dma_buf);
1538 this_adm.sourceTrackingData.dma_buf = NULL;
1539 this_adm.sourceTrackingData.memmap.size = 0;
1540 this_adm.sourceTrackingData.memmap.kvaddr =
1541 NULL;
1542 this_adm.sourceTrackingData.memmap.paddr = 0;
1543 this_adm.sourceTrackingData.apr_cmd_status = -1;
1544 atomic_set(&this_adm.mem_map_handles[
1545 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
1546 }
1547}
1548
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301549static int32_t adm_callback(struct apr_client_data *data, void *priv)
1550{
1551 uint32_t *payload;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001552 int port_idx, copp_idx, idx, client_id;
1553 int num_modules;
1554 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301555
1556 if (data == NULL) {
1557 pr_err("%s: data parameter is null\n", __func__);
1558 return -EINVAL;
1559 }
1560
1561 payload = data->payload;
1562
1563 if (data->opcode == RESET_EVENTS) {
1564 pr_debug("%s: Reset event is received: %d %d apr[%pK]\n",
1565 __func__,
1566 data->reset_event, data->reset_proc, this_adm.apr);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301567 if (this_adm.apr)
1568 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301569 return 0;
1570 }
1571
1572 adm_callback_debug_print(data);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001573 if (data->payload_size >= sizeof(uint32_t)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301574 copp_idx = (data->token) & 0XFF;
1575 port_idx = ((data->token) >> 16) & 0xFF;
1576 client_id = ((data->token) >> 8) & 0xFF;
1577 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1578 pr_err("%s: Invalid port idx %d token %d\n",
1579 __func__, port_idx, data->token);
1580 return 0;
1581 }
1582 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1583 pr_err("%s: Invalid copp idx %d token %d\n",
1584 __func__, copp_idx, data->token);
1585 return 0;
1586 }
1587 if (client_id < 0 || client_id >= ADM_CLIENT_ID_MAX) {
1588 pr_err("%s: Invalid client id %d\n", __func__,
1589 client_id);
1590 return 0;
1591 }
1592 if (data->opcode == APR_BASIC_RSP_RESULT) {
1593 pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
1594 __func__, payload[0]);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001595
1596 if (!((client_id != ADM_CLIENT_ID_SOURCE_TRACKING) &&
1597 ((payload[0] == ADM_CMD_SET_PP_PARAMS_V5) ||
1598 (payload[0] == ADM_CMD_SET_PP_PARAMS_V6)))) {
1599 if (data->payload_size <
1600 (2 * sizeof(uint32_t))) {
1601 pr_err("%s: Invalid payload size %d\n",
1602 __func__, data->payload_size);
1603 return 0;
1604 }
1605 }
1606
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301607 if (payload[1] != 0) {
1608 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
1609 __func__, payload[0], payload[1]);
1610 }
1611 switch (payload[0]) {
1612 case ADM_CMD_SET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001613 case ADM_CMD_SET_PP_PARAMS_V6:
1614 pr_debug("%s: ADM_CMD_SET_PP_PARAMS\n",
1615 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301616 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1617 this_adm.sourceTrackingData.
1618 apr_cmd_status = payload[1];
1619 else if (rtac_make_adm_callback(payload,
Soumya Managoli97f90ea2020-04-28 09:16:55 +05301620 data->payload_size)) {
1621 pr_debug("%s: rtac cmd response\n",
1622 __func__);
1623 }
1624 atomic_set(&this_adm.copp.stat[port_idx]
1625 [copp_idx], payload[1]);
1626 wake_up(
1627 &this_adm.copp.wait[port_idx][copp_idx]);
1628 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301629 /*
1630 * if soft volume is called and already
1631 * interrupted break out of the sequence here
1632 */
1633 case ADM_CMD_DEVICE_OPEN_V5:
1634 case ADM_CMD_DEVICE_CLOSE_V5:
1635 case ADM_CMD_DEVICE_OPEN_V6:
Dieter Luecking50c55352018-09-28 14:29:17 +02001636 case ADM_CMD_DEVICE_OPEN_V8:
Soumya Managoli97f90ea2020-04-28 09:16:55 +05301637 pr_debug("%s: Basic callback received for 0x%x, wake up.\n",
1638 __func__, payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301639 atomic_set(&this_adm.copp.stat[port_idx]
1640 [copp_idx], payload[1]);
1641 wake_up(
1642 &this_adm.copp.wait[port_idx][copp_idx]);
1643 break;
1644 case ADM_CMD_ADD_TOPOLOGIES:
1645 pr_debug("%s: callback received, ADM_CMD_ADD_TOPOLOGIES.\n",
1646 __func__);
1647 atomic_set(&this_adm.adm_stat, payload[1]);
1648 wake_up(&this_adm.adm_wait);
1649 break;
1650 case ADM_CMD_MATRIX_MAP_ROUTINGS_V5:
1651 case ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5:
1652 pr_debug("%s: Basic callback received, wake up.\n",
1653 __func__);
1654 atomic_set(&this_adm.matrix_map_stat,
1655 payload[1]);
1656 wake_up(&this_adm.matrix_map_wait);
1657 break;
1658 case ADM_CMD_SHARED_MEM_UNMAP_REGIONS:
1659 pr_debug("%s: ADM_CMD_SHARED_MEM_UNMAP_REGIONS\n",
1660 __func__);
1661 atomic_set(&this_adm.adm_stat, payload[1]);
1662 wake_up(&this_adm.adm_wait);
1663 break;
1664 case ADM_CMD_SHARED_MEM_MAP_REGIONS:
1665 pr_debug("%s: ADM_CMD_SHARED_MEM_MAP_REGIONS\n",
1666 __func__);
1667 /* Should only come here if there is an APR */
1668 /* error or malformed APR packet. Otherwise */
1669 /* response will be returned as */
1670 if (payload[1] != 0) {
1671 pr_err("%s: ADM map error, resuming\n",
1672 __func__);
1673 atomic_set(&this_adm.adm_stat,
1674 payload[1]);
1675 wake_up(&this_adm.adm_wait);
1676 }
1677 break;
1678 case ADM_CMD_GET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001679 case ADM_CMD_GET_PP_PARAMS_V6:
1680 pr_debug("%s: ADM_CMD_GET_PP_PARAMS\n",
1681 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301682 /* Should only come here if there is an APR */
1683 /* error or malformed APR packet. Otherwise */
1684 /* response will be returned as */
1685 /* ADM_CMDRSP_GET_PP_PARAMS_V5 */
1686 if (client_id ==
1687 ADM_CLIENT_ID_SOURCE_TRACKING) {
1688 this_adm.sourceTrackingData.
1689 apr_cmd_status = payload[1];
1690 if (payload[1] != 0)
1691 pr_err("%s: ADM get param error = %d\n",
1692 __func__, payload[1]);
1693
1694 atomic_set(&this_adm.copp.stat
1695 [port_idx][copp_idx],
1696 payload[1]);
1697 wake_up(&this_adm.copp.wait
1698 [port_idx][copp_idx]);
1699 } else {
1700 if (payload[1] != 0) {
1701 pr_err("%s: ADM get param error = %d, resuming\n",
1702 __func__, payload[1]);
1703
1704 rtac_make_adm_callback(payload,
1705 data->payload_size);
1706 }
1707 }
1708 break;
1709 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5:
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -07001710 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6:
1711 pr_debug("%s:callback received PSPD MTMX, wake up\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301712 __func__);
1713 atomic_set(&this_adm.copp.stat[port_idx]
1714 [copp_idx], payload[1]);
1715 wake_up(
1716 &this_adm.copp.wait[port_idx][copp_idx]);
1717 break;
1718 case ADM_CMD_GET_PP_TOPO_MODULE_LIST:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001719 case ADM_CMD_GET_PP_TOPO_MODULE_LIST_V2:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301720 pr_debug("%s:ADM_CMD_GET_PP_TOPO_MODULE_LIST\n",
1721 __func__);
1722 if (payload[1] != 0)
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001723 pr_err("%s: ADM get topo list error = %d\n",
1724 __func__, payload[1]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301725 break;
1726 default:
1727 pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
1728 payload[0]);
1729 break;
1730 }
1731 return 0;
1732 }
1733
1734 switch (data->opcode) {
1735 case ADM_CMDRSP_DEVICE_OPEN_V5:
Dieter Luecking50c55352018-09-28 14:29:17 +02001736 case ADM_CMDRSP_DEVICE_OPEN_V6:
1737 case ADM_CMDRSP_DEVICE_OPEN_V8: {
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001738 struct adm_cmd_rsp_device_open_v5 *open = NULL;
1739 if (data->payload_size <
1740 sizeof(struct adm_cmd_rsp_device_open_v5)) {
1741 pr_err("%s: Invalid payload size %d\n", __func__,
1742 data->payload_size);
1743 return 0;
1744 }
1745 open = (struct adm_cmd_rsp_device_open_v5 *)data->payload;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301746 if (open->copp_id == INVALID_COPP_ID) {
1747 pr_err("%s: invalid coppid rxed %d\n",
1748 __func__, open->copp_id);
1749 atomic_set(&this_adm.copp.stat[port_idx]
1750 [copp_idx], ADSP_EBADPARAM);
1751 wake_up(
1752 &this_adm.copp.wait[port_idx][copp_idx]);
1753 break;
1754 }
1755 atomic_set(&this_adm.copp.stat
1756 [port_idx][copp_idx], payload[0]);
1757 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
1758 open->copp_id);
1759 pr_debug("%s: coppid rxed=%d\n", __func__,
1760 open->copp_id);
1761 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1762 }
1763 break;
1764 case ADM_CMDRSP_GET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001765 case ADM_CMDRSP_GET_PP_PARAMS_V6:
1766 pr_debug("%s: ADM_CMDRSP_GET_PP_PARAMS\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301767 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1768 this_adm.sourceTrackingData.apr_cmd_status =
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001769 payload[0];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301770 else if (rtac_make_adm_callback(payload,
Soumya Managoli97f90ea2020-04-28 09:16:55 +05301771 data->payload_size)) {
1772 pr_debug("%s: rtac cmd response\n", __func__);
1773 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1774 payload[0]);
1775 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301776 break;
Soumya Managoli97f90ea2020-04-28 09:16:55 +05301777 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301778
1779 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001780 if (payload[0] == 0 && data->payload_size > 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001781 ret = adm_process_get_param_response(
1782 data->opcode, idx, payload,
1783 data->payload_size);
1784 if (ret)
1785 pr_err("%s: Failed to process get param response, error %d\n",
1786 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301787 } else {
1788 adm_get_parameters[idx] = -1;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001789 pr_err("%s: ADM_CMDRSP_GET_PP_PARAMS returned error 0x%x\n",
1790 __func__, payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301791 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001792 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1793 payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301794 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1795 break;
1796 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001797 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301798 pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n",
1799 __func__);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001800 if (data->payload_size >= (2 * sizeof(uint32_t))) {
1801 num_modules = payload[1];
1802 pr_debug("%s: Num modules %d\n", __func__,
1803 num_modules);
1804 if (payload[0]) {
1805 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
1806 __func__, payload[0]);
1807 } else if (num_modules > MAX_MODULES_IN_TOPO) {
1808 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n",
1809 __func__, num_modules);
1810 } else {
1811 ret = adm_process_get_topo_list_response(
1812 data->opcode, copp_idx,
1813 num_modules, payload,
1814 data->payload_size);
1815 if (ret)
1816 pr_err("%s: Failed to process get topo modules list response, error %d\n",
1817 __func__, ret);
1818 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301819 } else {
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001820 pr_err("%s: Invalid payload size %d\n",
1821 __func__, data->payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301822 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001823 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1824 payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301825 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1826 break;
1827 case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
1828 pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
1829 __func__);
1830 atomic_set(&this_adm.mem_map_handles[
1831 atomic_read(&this_adm.mem_map_index)],
1832 *payload);
1833 atomic_set(&this_adm.adm_stat, 0);
1834 wake_up(&this_adm.adm_wait);
1835 break;
1836 default:
1837 pr_err("%s: Unknown cmd:0x%x\n", __func__,
1838 data->opcode);
1839 break;
1840 }
1841 }
1842 return 0;
1843}
1844
1845static int adm_memory_map_regions(phys_addr_t *buf_add, uint32_t mempool_id,
1846 uint32_t *bufsz, uint32_t bufcnt)
1847{
1848 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
1849 struct avs_shared_map_region_payload *mregions = NULL;
1850 void *mmap_region_cmd = NULL;
1851 void *payload = NULL;
1852 int ret = 0;
1853 int i = 0;
1854 int cmd_size = 0;
1855
1856 pr_debug("%s:\n", __func__);
1857 if (this_adm.apr == NULL) {
1858 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
1859 0xFFFFFFFF, &this_adm);
1860 if (this_adm.apr == NULL) {
1861 pr_err("%s: Unable to register ADM\n", __func__);
1862 ret = -ENODEV;
1863 return ret;
1864 }
1865 rtac_set_adm_handle(this_adm.apr);
1866 }
1867
1868 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
1869 + sizeof(struct avs_shared_map_region_payload)
1870 * bufcnt;
1871
1872 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1873 if (!mmap_region_cmd)
1874 return -ENOMEM;
1875
1876 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)mmap_region_cmd;
1877 mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1878 APR_HDR_LEN(APR_HDR_SIZE),
1879 APR_PKT_VER);
1880 mmap_regions->hdr.pkt_size = cmd_size;
1881 mmap_regions->hdr.src_port = 0;
1882
1883 mmap_regions->hdr.dest_port = 0;
1884 mmap_regions->hdr.token = 0;
1885 mmap_regions->hdr.opcode = ADM_CMD_SHARED_MEM_MAP_REGIONS;
1886 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL & 0x00ff;
1887 mmap_regions->num_regions = bufcnt & 0x00ff;
1888 mmap_regions->property_flag = 0x00;
1889
1890 pr_debug("%s: map_regions->num_regions = %d\n", __func__,
1891 mmap_regions->num_regions);
1892 payload = ((u8 *) mmap_region_cmd +
1893 sizeof(struct avs_cmd_shared_mem_map_regions));
1894 mregions = (struct avs_shared_map_region_payload *)payload;
1895
1896 for (i = 0; i < bufcnt; i++) {
1897 mregions->shm_addr_lsw = lower_32_bits(buf_add[i]);
1898 mregions->shm_addr_msw =
1899 msm_audio_populate_upper_32_bits(buf_add[i]);
1900 mregions->mem_size_bytes = bufsz[i];
1901 ++mregions;
1902 }
1903
1904 atomic_set(&this_adm.adm_stat, -1);
1905 ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
1906 if (ret < 0) {
1907 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1908 mmap_regions->hdr.opcode, ret);
1909 ret = -EINVAL;
1910 goto fail_cmd;
1911 }
1912
1913 ret = wait_event_timeout(this_adm.adm_wait,
1914 atomic_read(&this_adm.adm_stat) >= 0,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001915 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301916 if (!ret) {
1917 pr_err("%s: timeout. waited for memory_map\n", __func__);
1918 ret = -EINVAL;
1919 goto fail_cmd;
1920 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1921 pr_err("%s: DSP returned error[%s]\n",
1922 __func__, adsp_err_get_err_str(
1923 atomic_read(&this_adm.adm_stat)));
1924 ret = adsp_err_get_lnx_err_code(
1925 atomic_read(&this_adm.adm_stat));
1926 goto fail_cmd;
1927 }
1928fail_cmd:
1929 kfree(mmap_region_cmd);
1930 return ret;
1931}
1932
1933static int adm_memory_unmap_regions(void)
1934{
1935 struct avs_cmd_shared_mem_unmap_regions unmap_regions;
1936 int ret = 0;
1937
1938 pr_debug("%s:\n", __func__);
1939 if (this_adm.apr == NULL) {
1940 pr_err("%s: APR handle NULL\n", __func__);
1941 return -EINVAL;
1942 }
1943
1944 unmap_regions.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1945 APR_HDR_LEN(APR_HDR_SIZE),
1946 APR_PKT_VER);
1947 unmap_regions.hdr.pkt_size = sizeof(unmap_regions);
1948 unmap_regions.hdr.src_port = 0;
1949 unmap_regions.hdr.dest_port = 0;
1950 unmap_regions.hdr.token = 0;
1951 unmap_regions.hdr.opcode = ADM_CMD_SHARED_MEM_UNMAP_REGIONS;
1952 unmap_regions.mem_map_handle = atomic_read(&this_adm.
1953 mem_map_handles[atomic_read(&this_adm.mem_map_index)]);
1954 atomic_set(&this_adm.adm_stat, -1);
1955 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &unmap_regions);
1956 if (ret < 0) {
1957 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1958 unmap_regions.hdr.opcode, ret);
1959 ret = -EINVAL;
1960 goto fail_cmd;
1961 }
1962
1963 ret = wait_event_timeout(this_adm.adm_wait,
1964 atomic_read(&this_adm.adm_stat) >= 0,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001965 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301966 if (!ret) {
1967 pr_err("%s: timeout. waited for memory_unmap\n",
1968 __func__);
1969 ret = -EINVAL;
1970 goto fail_cmd;
1971 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1972 pr_err("%s: DSP returned error[%s]\n",
1973 __func__, adsp_err_get_err_str(
1974 atomic_read(&this_adm.adm_stat)));
1975 ret = adsp_err_get_lnx_err_code(
1976 atomic_read(&this_adm.adm_stat));
1977 goto fail_cmd;
1978 } else {
1979 pr_debug("%s: Unmap handle 0x%x succeeded\n", __func__,
1980 unmap_regions.mem_map_handle);
1981 }
1982fail_cmd:
1983 return ret;
1984}
1985
1986static int remap_cal_data(struct cal_block_data *cal_block, int cal_index)
1987{
1988 int ret = 0;
1989
Banajit Goswami08bb7362017-11-03 22:48:23 -07001990 if (cal_block->map_data.dma_buf == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301991 pr_err("%s: No ION allocation for cal index %d!\n",
1992 __func__, cal_index);
1993 ret = -EINVAL;
1994 goto done;
1995 }
1996
1997 if ((cal_block->map_data.map_size > 0) &&
1998 (cal_block->map_data.q6map_handle == 0)) {
1999 atomic_set(&this_adm.mem_map_index, cal_index);
2000 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
2001 (uint32_t *)&cal_block->map_data.map_size, 1);
2002 if (ret < 0) {
2003 pr_err("%s: ADM mmap did not work! size = %zd ret %d\n",
2004 __func__,
2005 cal_block->map_data.map_size, ret);
2006 pr_debug("%s: ADM mmap did not work! addr = 0x%pK, size = %zd ret %d\n",
2007 __func__,
2008 &cal_block->cal_data.paddr,
2009 cal_block->map_data.map_size, ret);
2010 goto done;
2011 }
2012 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
2013 mem_map_handles[cal_index]);
2014 }
2015done:
2016 return ret;
2017}
2018
2019static void send_adm_custom_topology(void)
2020{
2021 struct cal_block_data *cal_block = NULL;
2022 struct cmd_set_topologies adm_top;
2023 int cal_index = ADM_CUSTOM_TOP_CAL;
2024 int result;
2025
2026 if (this_adm.cal_data[cal_index] == NULL)
2027 goto done;
2028
2029 mutex_lock(&this_adm.cal_data[cal_index]->lock);
2030 if (!this_adm.set_custom_topology)
2031 goto unlock;
2032 this_adm.set_custom_topology = 0;
2033
2034 cal_block = cal_utils_get_only_cal_block(this_adm.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002035 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302036 goto unlock;
2037
2038 pr_debug("%s: Sending cal_index %d\n", __func__, cal_index);
2039
2040 result = remap_cal_data(cal_block, cal_index);
2041 if (result) {
2042 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2043 __func__, cal_index);
2044 goto unlock;
2045 }
2046 atomic_set(&this_adm.mem_map_index, cal_index);
2047 atomic_set(&this_adm.mem_map_handles[cal_index],
2048 cal_block->map_data.q6map_handle);
2049
2050 if (cal_block->cal_data.size == 0) {
2051 pr_debug("%s: No ADM cal to send\n", __func__);
2052 goto unlock;
2053 }
2054
2055 adm_top.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2056 APR_HDR_LEN(20), APR_PKT_VER);
2057 adm_top.hdr.pkt_size = sizeof(adm_top);
2058 adm_top.hdr.src_svc = APR_SVC_ADM;
2059 adm_top.hdr.src_domain = APR_DOMAIN_APPS;
2060 adm_top.hdr.src_port = 0;
2061 adm_top.hdr.dest_svc = APR_SVC_ADM;
2062 adm_top.hdr.dest_domain = APR_DOMAIN_ADSP;
2063 adm_top.hdr.dest_port = 0;
2064 adm_top.hdr.token = 0;
2065 adm_top.hdr.opcode = ADM_CMD_ADD_TOPOLOGIES;
2066 adm_top.payload_addr_lsw = lower_32_bits(cal_block->cal_data.paddr);
2067 adm_top.payload_addr_msw = msm_audio_populate_upper_32_bits(
2068 cal_block->cal_data.paddr);
2069 adm_top.mem_map_handle = cal_block->map_data.q6map_handle;
2070 adm_top.payload_size = cal_block->cal_data.size;
2071
2072 atomic_set(&this_adm.adm_stat, -1);
2073 pr_debug("%s: Sending ADM_CMD_ADD_TOPOLOGIES payload = 0x%pK, size = %d\n",
2074 __func__, &cal_block->cal_data.paddr,
2075 adm_top.payload_size);
2076 result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_top);
2077 if (result < 0) {
2078 pr_err("%s: Set topologies failed payload size = %zd result %d\n",
2079 __func__, cal_block->cal_data.size, result);
2080 goto unlock;
2081 }
2082 /* Wait for the callback */
2083 result = wait_event_timeout(this_adm.adm_wait,
2084 atomic_read(&this_adm.adm_stat) >= 0,
2085 msecs_to_jiffies(TIMEOUT_MS));
2086 if (!result) {
2087 pr_err("%s: Set topologies timed out payload size = %zd\n",
2088 __func__, cal_block->cal_data.size);
2089 goto unlock;
2090 } else if (atomic_read(&this_adm.adm_stat) > 0) {
2091 pr_err("%s: DSP returned error[%s]\n",
2092 __func__, adsp_err_get_err_str(
2093 atomic_read(&this_adm.adm_stat)));
2094 result = adsp_err_get_lnx_err_code(
2095 atomic_read(&this_adm.adm_stat));
2096 goto unlock;
2097 }
2098unlock:
2099 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2100done:
2101 return;
2102}
2103
2104static int send_adm_cal_block(int port_id, int copp_idx,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002105 struct cal_block_data *cal_block, int perf_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302106{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002107 struct mem_mapping_hdr mem_hdr;
2108 int payload_size = 0;
2109 int port_idx = 0;
2110 int topology = 0;
2111 int result = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302112
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002113 pr_debug("%s: Port id 0x%x,\n", __func__, port_id);
2114
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302115 if (!cal_block) {
2116 pr_debug("%s: No ADM cal to send for port_id = 0x%x!\n",
2117 __func__, port_id);
2118 result = -EINVAL;
2119 goto done;
2120 }
2121 if (cal_block->cal_data.size <= 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002122 pr_debug("%s: No ADM cal sent for port_id = 0x%x!\n", __func__,
2123 port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302124 result = -EINVAL;
2125 goto done;
2126 }
2127
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002128 memset(&mem_hdr, 0, sizeof(mem_hdr));
2129 port_id = afe_convert_virtual_to_portid(port_id);
2130 port_idx = adm_validate_and_get_port_index(port_id);
2131 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
2132 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2133 return -EINVAL;
2134 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
2135 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
2136 return -EINVAL;
2137 }
2138
2139 topology = atomic_read(&this_adm.copp.topology[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302140 if (perf_mode == LEGACY_PCM_MODE &&
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002141 topology == DS2_ADM_COPP_TOPOLOGY_ID) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302142 pr_err("%s: perf_mode %d, topology 0x%x\n", __func__, perf_mode,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002143 topology);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302144 goto done;
2145 }
2146
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002147 mem_hdr.data_payload_addr_lsw =
2148 lower_32_bits(cal_block->cal_data.paddr);
2149 mem_hdr.data_payload_addr_msw =
2150 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
2151 mem_hdr.mem_map_handle = cal_block->map_data.q6map_handle;
2152 payload_size = cal_block->cal_data.size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302153
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002154 adm_set_pp_params(port_id, copp_idx, &mem_hdr, NULL, payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302155
2156done:
2157 return result;
2158}
2159
2160static struct cal_block_data *adm_find_cal_by_path(int cal_index, int path)
2161{
2162 struct list_head *ptr, *next;
2163 struct cal_block_data *cal_block = NULL;
2164 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2165 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2166
2167 pr_debug("%s:\n", __func__);
2168
2169 list_for_each_safe(ptr, next,
2170 &this_adm.cal_data[cal_index]->cal_blocks) {
2171
2172 cal_block = list_entry(ptr,
2173 struct cal_block_data, list);
2174
Vikram Panduranga770b8382017-09-27 12:17:36 -07002175 if (cal_utils_is_cal_stale(cal_block))
2176 continue;
2177
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302178 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002179 cal_index == ADM_LSM_AUDPROC_CAL ||
Ramlal Karra471fe912020-04-13 13:47:07 +05302180 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL ||
2181 cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302182 audproc_cal_info = cal_block->cal_info;
2183 if ((audproc_cal_info->path == path) &&
2184 (cal_block->cal_data.size > 0))
2185 return cal_block;
2186 } else if (cal_index == ADM_AUDVOL_CAL) {
2187 audvol_cal_info = cal_block->cal_info;
2188 if ((audvol_cal_info->path == path) &&
2189 (cal_block->cal_data.size > 0))
2190 return cal_block;
2191 }
2192 }
2193 pr_debug("%s: Can't find ADM cal for cal_index %d, path %d\n",
2194 __func__, cal_index, path);
2195 return NULL;
2196}
2197
2198static struct cal_block_data *adm_find_cal_by_app_type(int cal_index, int path,
2199 int app_type)
2200{
2201 struct list_head *ptr, *next;
2202 struct cal_block_data *cal_block = NULL;
2203 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2204 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2205
2206 pr_debug("%s\n", __func__);
2207
2208 list_for_each_safe(ptr, next,
2209 &this_adm.cal_data[cal_index]->cal_blocks) {
2210
2211 cal_block = list_entry(ptr,
2212 struct cal_block_data, list);
2213
Vikram Panduranga770b8382017-09-27 12:17:36 -07002214 if (cal_utils_is_cal_stale(cal_block))
2215 continue;
2216
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302217 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002218 cal_index == ADM_LSM_AUDPROC_CAL ||
Ramlal Karra471fe912020-04-13 13:47:07 +05302219 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL ||
2220 cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302221 audproc_cal_info = cal_block->cal_info;
2222 if ((audproc_cal_info->path == path) &&
2223 (audproc_cal_info->app_type == app_type) &&
2224 (cal_block->cal_data.size > 0))
2225 return cal_block;
2226 } else if (cal_index == ADM_AUDVOL_CAL) {
2227 audvol_cal_info = cal_block->cal_info;
2228 if ((audvol_cal_info->path == path) &&
2229 (audvol_cal_info->app_type == app_type) &&
2230 (cal_block->cal_data.size > 0))
2231 return cal_block;
2232 }
2233 }
2234 pr_debug("%s: Can't find ADM cali for cal_index %d, path %d, app %d, defaulting to search by path\n",
2235 __func__, cal_index, path, app_type);
2236 return adm_find_cal_by_path(cal_index, path);
2237}
2238
2239
2240static struct cal_block_data *adm_find_cal(int cal_index, int path,
2241 int app_type, int acdb_id,
2242 int sample_rate)
2243{
2244 struct list_head *ptr, *next;
2245 struct cal_block_data *cal_block = NULL;
2246 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2247 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2248
2249 pr_debug("%s:\n", __func__);
2250
2251 list_for_each_safe(ptr, next,
2252 &this_adm.cal_data[cal_index]->cal_blocks) {
2253
2254 cal_block = list_entry(ptr,
2255 struct cal_block_data, list);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002256 if (cal_utils_is_cal_stale(cal_block))
2257 continue;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302258
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302259 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002260 cal_index == ADM_LSM_AUDPROC_CAL ||
Ramlal Karra471fe912020-04-13 13:47:07 +05302261 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL||
2262 cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302263 audproc_cal_info = cal_block->cal_info;
2264 if ((audproc_cal_info->path == path) &&
2265 (audproc_cal_info->app_type == app_type) &&
2266 (audproc_cal_info->acdb_id == acdb_id) &&
2267 (audproc_cal_info->sample_rate == sample_rate) &&
2268 (cal_block->cal_data.size > 0))
2269 return cal_block;
2270 } else if (cal_index == ADM_AUDVOL_CAL) {
2271 audvol_cal_info = cal_block->cal_info;
2272 if ((audvol_cal_info->path == path) &&
2273 (audvol_cal_info->app_type == app_type) &&
2274 (audvol_cal_info->acdb_id == acdb_id) &&
2275 (cal_block->cal_data.size > 0))
2276 return cal_block;
2277 }
2278 }
2279 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",
2280 __func__, cal_index, path, app_type, acdb_id, sample_rate);
2281 return adm_find_cal_by_app_type(cal_index, path, app_type);
2282}
2283
2284static int adm_remap_and_send_cal_block(int cal_index, int port_id,
2285 int copp_idx, struct cal_block_data *cal_block, int perf_mode,
2286 int app_type, int acdb_id, int sample_rate)
2287{
2288 int ret = 0;
2289
2290 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
2291 ret = remap_cal_data(cal_block, cal_index);
2292 if (ret) {
2293 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2294 __func__, cal_index);
2295 goto done;
2296 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002297 ret = send_adm_cal_block(port_id, copp_idx, cal_block, perf_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302298 if (ret < 0)
2299 pr_debug("%s: No cal sent for cal_index %d, port_id = 0x%x! ret %d sample_rate %d\n",
2300 __func__, cal_index, port_id, ret, sample_rate);
2301done:
2302 return ret;
2303}
2304
2305static void send_adm_cal_type(int cal_index, int path, int port_id,
2306 int copp_idx, int perf_mode, int app_type,
2307 int acdb_id, int sample_rate)
2308{
2309 struct cal_block_data *cal_block = NULL;
2310 int ret;
2311
2312 pr_debug("%s: cal index %d\n", __func__, cal_index);
2313
2314 if (this_adm.cal_data[cal_index] == NULL) {
2315 pr_debug("%s: cal_index %d not allocated!\n",
2316 __func__, cal_index);
2317 goto done;
2318 }
2319
2320 mutex_lock(&this_adm.cal_data[cal_index]->lock);
2321 cal_block = adm_find_cal(cal_index, path, app_type, acdb_id,
2322 sample_rate);
2323 if (cal_block == NULL)
2324 goto unlock;
2325
2326 ret = adm_remap_and_send_cal_block(cal_index, port_id, copp_idx,
2327 cal_block, perf_mode, app_type, acdb_id, sample_rate);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002328
2329 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302330unlock:
2331 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2332done:
2333 return;
2334}
2335
2336static int get_cal_path(int path)
2337{
2338 if (path == 0x1)
2339 return RX_DEVICE;
2340 else
2341 return TX_DEVICE;
2342}
2343
2344static void send_adm_cal(int port_id, int copp_idx, int path, int perf_mode,
Aditya Bavanari5106b562018-01-08 13:16:32 +05302345 int app_type, int acdb_id, int sample_rate,
2346 int passthr_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302347{
2348 pr_debug("%s: port id 0x%x copp_idx %d\n", __func__, port_id, copp_idx);
2349
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002350 if (passthr_mode != LISTEN) {
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302351 send_adm_cal_type(ADM_AUDPROC_CAL, path, port_id, copp_idx,
2352 perf_mode, app_type, acdb_id, sample_rate);
Ramlal Karra471fe912020-04-13 13:47:07 +05302353 send_adm_cal_type(ADM_AUDPROC_PERSISTENT_CAL, path,
2354 port_id, copp_idx, perf_mode, app_type,
2355 acdb_id, sample_rate);
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002356 } else {
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302357 send_adm_cal_type(ADM_LSM_AUDPROC_CAL, path, port_id, copp_idx,
2358 perf_mode, app_type, acdb_id, sample_rate);
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002359
2360 send_adm_cal_type(ADM_LSM_AUDPROC_PERSISTENT_CAL, path,
2361 port_id, copp_idx, perf_mode, app_type,
2362 acdb_id, sample_rate);
2363 }
2364
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302365 send_adm_cal_type(ADM_AUDVOL_CAL, path, port_id, copp_idx, perf_mode,
2366 app_type, acdb_id, sample_rate);
2367}
2368
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302369/**
2370 * adm_connect_afe_port -
2371 * command to send ADM connect AFE port
2372 *
2373 * @mode: value of mode for ADM connect AFE
2374 * @session_id: session active to connect
2375 * @port_id: Port ID number
2376 *
2377 * Returns 0 on success or error on failure
2378 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302379int adm_connect_afe_port(int mode, int session_id, int port_id)
2380{
2381 struct adm_cmd_connect_afe_port_v5 cmd;
2382 int ret = 0;
2383 int port_idx, copp_idx = 0;
2384
2385 pr_debug("%s: port_id: 0x%x session id:%d mode:%d\n", __func__,
2386 port_id, session_id, mode);
2387
2388 port_id = afe_convert_virtual_to_portid(port_id);
2389 port_idx = adm_validate_and_get_port_index(port_id);
2390 if (port_idx < 0) {
2391 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2392 return -EINVAL;
2393 }
2394
2395 if (this_adm.apr == NULL) {
2396 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
2397 0xFFFFFFFF, &this_adm);
2398 if (this_adm.apr == NULL) {
2399 pr_err("%s: Unable to register ADM\n", __func__);
2400 ret = -ENODEV;
2401 return ret;
2402 }
2403 rtac_set_adm_handle(this_adm.apr);
2404 }
2405 pr_debug("%s: Port ID 0x%x, index %d\n", __func__, port_id, port_idx);
2406
2407 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2408 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2409 cmd.hdr.pkt_size = sizeof(cmd);
2410 cmd.hdr.src_svc = APR_SVC_ADM;
2411 cmd.hdr.src_domain = APR_DOMAIN_APPS;
2412 cmd.hdr.src_port = port_id;
2413 cmd.hdr.dest_svc = APR_SVC_ADM;
2414 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
2415 cmd.hdr.dest_port = 0; /* Ignored */
2416 cmd.hdr.token = port_idx << 16 | copp_idx;
2417 cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V5;
2418
2419 cmd.mode = mode;
2420 cmd.session_id = session_id;
2421 cmd.afe_port_id = port_id;
2422
2423 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
2424 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
2425 if (ret < 0) {
2426 pr_err("%s: ADM enable for port_id: 0x%x failed ret %d\n",
2427 __func__, port_id, ret);
2428 ret = -EINVAL;
2429 goto fail_cmd;
2430 }
2431 /* Wait for the callback with copp id */
2432 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
2433 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
2434 msecs_to_jiffies(TIMEOUT_MS));
2435 if (!ret) {
2436 pr_err("%s: ADM connect timedout for port_id: 0x%x\n",
2437 __func__, port_id);
2438 ret = -EINVAL;
2439 goto fail_cmd;
2440 } else if (atomic_read(&this_adm.copp.stat
2441 [port_idx][copp_idx]) > 0) {
2442 pr_err("%s: DSP returned error[%s]\n",
2443 __func__, adsp_err_get_err_str(
2444 atomic_read(&this_adm.copp.stat
2445 [port_idx][copp_idx])));
2446 ret = adsp_err_get_lnx_err_code(
2447 atomic_read(&this_adm.copp.stat
2448 [port_idx][copp_idx]));
2449 goto fail_cmd;
2450 }
2451 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
2452 return 0;
2453
2454fail_cmd:
2455
2456 return ret;
2457}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302458EXPORT_SYMBOL(adm_connect_afe_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302459
2460int adm_arrange_mch_map(struct adm_cmd_device_open_v5 *open, int path,
Rohit kumar2054b692019-02-01 18:01:12 +05302461 int channel_mode, int port_idx)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302462{
2463 int rc = 0, idx;
2464
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -07002465 pr_debug("%s: channel mode %d", __func__, channel_mode);
2466
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302467 memset(open->dev_channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
2468 switch (path) {
2469 case ADM_PATH_PLAYBACK:
2470 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2471 break;
2472 case ADM_PATH_LIVE_REC:
2473 case ADM_PATH_NONLIVE_REC:
2474 idx = ADM_MCH_MAP_IDX_REC;
2475 break;
2476 default:
2477 goto non_mch_path;
2478 };
Rohit kumar2054b692019-02-01 18:01:12 +05302479
2480 if ((open->dev_num_channel > 2) &&
2481 (port_channel_map[port_idx].set_channel_map ||
2482 multi_ch_maps[idx].set_channel_map)) {
2483 if (port_channel_map[port_idx].set_channel_map)
2484 memcpy(open->dev_channel_mapping,
2485 port_channel_map[port_idx].channel_mapping,
2486 PCM_FORMAT_MAX_NUM_CHANNEL);
2487 else
2488 memcpy(open->dev_channel_mapping,
2489 multi_ch_maps[idx].channel_mapping,
2490 PCM_FORMAT_MAX_NUM_CHANNEL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302491 } else {
2492 if (channel_mode == 1) {
2493 open->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2494 } else if (channel_mode == 2) {
2495 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2496 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2497 } else if (channel_mode == 3) {
2498 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2499 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2500 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2501 } else if (channel_mode == 4) {
2502 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2503 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2504 open->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2505 open->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2506 } else if (channel_mode == 5) {
2507 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2508 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2509 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2510 open->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2511 open->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2512 } else if (channel_mode == 6) {
2513 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2514 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2515 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2516 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2517 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2518 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2519 } else if (channel_mode == 7) {
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_LFE;
2524 open->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2525 open->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2526 open->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2527 } else if (channel_mode == 8) {
2528 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2529 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2530 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2531 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2532 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2533 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2534 open->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2535 open->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2536 } else {
2537 pr_err("%s: invalid num_chan %d\n", __func__,
2538 channel_mode);
2539 rc = -EINVAL;
2540 goto inval_ch_mod;
2541 }
2542 }
2543
2544non_mch_path:
2545inval_ch_mod:
2546 return rc;
2547}
2548
2549int adm_arrange_mch_ep2_map(struct adm_cmd_device_open_v6 *open_v6,
2550 int channel_mode)
2551{
2552 int rc = 0;
2553
2554 memset(open_v6->dev_channel_mapping_eid2, 0,
2555 PCM_FORMAT_MAX_NUM_CHANNEL);
2556
2557 if (channel_mode == 1) {
2558 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FC;
2559 } else if (channel_mode == 2) {
2560 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2561 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2562 } else if (channel_mode == 3) {
2563 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2564 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2565 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2566 } else if (channel_mode == 4) {
2567 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2568 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2569 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LS;
2570 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_RS;
2571 } else if (channel_mode == 5) {
2572 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2573 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2574 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2575 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_LS;
2576 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_RS;
2577 } else if (channel_mode == 6) {
2578 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2579 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2580 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
2581 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2582 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2583 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2584 } else if (channel_mode == 8) {
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_LFE;
2588 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2589 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2590 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2591 open_v6->dev_channel_mapping_eid2[6] = PCM_CHANNEL_LB;
2592 open_v6->dev_channel_mapping_eid2[7] = PCM_CHANNEL_RB;
2593 } else {
2594 pr_err("%s: invalid num_chan %d\n", __func__,
2595 channel_mode);
2596 rc = -EINVAL;
2597 }
2598
2599 return rc;
2600}
2601
Dieter Luecking50c55352018-09-28 14:29:17 +02002602static int adm_arrange_mch_map_v8(
2603 struct adm_device_endpoint_payload *ep_payload,
Rohit kumar2054b692019-02-01 18:01:12 +05302604 int path, int channel_mode, int port_idx)
Dieter Luecking50c55352018-09-28 14:29:17 +02002605{
2606 int rc = 0, idx;
2607
2608 memset(ep_payload->dev_channel_mapping,
2609 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2610 switch (path) {
2611 case ADM_PATH_PLAYBACK:
2612 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2613 break;
2614 case ADM_PATH_LIVE_REC:
2615 case ADM_PATH_NONLIVE_REC:
2616 idx = ADM_MCH_MAP_IDX_REC;
2617 break;
2618 default:
2619 goto non_mch_path;
2620 };
2621
2622 if ((ep_payload->dev_num_channel > 2) &&
Rohit kumar2054b692019-02-01 18:01:12 +05302623 (port_channel_map[port_idx].set_channel_map ||
2624 multi_ch_maps[idx].set_channel_map)) {
2625 if (port_channel_map[port_idx].set_channel_map)
2626 memcpy(ep_payload->dev_channel_mapping,
2627 port_channel_map[port_idx].channel_mapping,
2628 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2629 else
2630 memcpy(ep_payload->dev_channel_mapping,
2631 multi_ch_maps[idx].channel_mapping,
2632 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Dieter Luecking50c55352018-09-28 14:29:17 +02002633 } else {
2634 if (channel_mode == 1) {
2635 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2636 } else if (channel_mode == 2) {
2637 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2638 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2639 } else if (channel_mode == 3) {
2640 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2641 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2642 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2643 } else if (channel_mode == 4) {
2644 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2645 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2646 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2647 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2648 } else if (channel_mode == 5) {
2649 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2650 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2651 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2652 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2653 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2654 } else if (channel_mode == 6) {
2655 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2656 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2657 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2658 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2659 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2660 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2661 } else if (channel_mode == 7) {
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_LFE;
2666 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2667 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2668 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2669 } else if (channel_mode == 8) {
2670 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2671 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2672 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2673 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2674 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2675 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2676 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2677 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2678 } else if (channel_mode == 10) {
2679 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2680 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2681 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2682 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2683 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2684 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2685 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2686 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2687 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2688 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2689 } else if (channel_mode == 12) {
2690 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2691 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2692 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2693 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2694 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2695 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2696 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2697 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2698 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2699 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2700 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2701 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
Chaithanya Krishna Bacharaju3dd8fdf2019-05-02 12:14:37 +05302702 } else if (channel_mode == 14) {
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;
2715 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2716 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
Dieter Luecking50c55352018-09-28 14:29:17 +02002717 } else if (channel_mode == 16) {
2718 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2719 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2720 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2721 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2722 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2723 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2724 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2725 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2726 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2727 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2728 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2729 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2730 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2731 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2732 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2733 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
Cong Tang04a6cfa2019-02-26 15:08:55 +08002734 } else if (channel_mode == 32) {
2735 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2736 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2737 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2738 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2739 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2740 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2741 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2742 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2743 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
2744 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
2745 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2746 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2747 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2748 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2749 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2750 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
2751 ep_payload->dev_channel_mapping[16] = PCM_CHANNEL_LFE2;
2752 ep_payload->dev_channel_mapping[17] = PCM_CHANNEL_SL;
2753 ep_payload->dev_channel_mapping[18] = PCM_CHANNEL_SR;
2754 ep_payload->dev_channel_mapping[19] = PCM_CHANNEL_TFL;
2755 ep_payload->dev_channel_mapping[20] = PCM_CHANNEL_TFR;
2756 ep_payload->dev_channel_mapping[21] = PCM_CHANNEL_TC;
2757 ep_payload->dev_channel_mapping[22] = PCM_CHANNEL_TBL;
2758 ep_payload->dev_channel_mapping[23] = PCM_CHANNEL_TBR;
2759 ep_payload->dev_channel_mapping[24] = PCM_CHANNEL_TSL;
2760 ep_payload->dev_channel_mapping[25] = PCM_CHANNEL_TSR;
2761 ep_payload->dev_channel_mapping[26] = PCM_CHANNEL_TBC;
2762 ep_payload->dev_channel_mapping[27] = PCM_CHANNEL_BFC;
2763 ep_payload->dev_channel_mapping[28] = PCM_CHANNEL_BFL;
2764 ep_payload->dev_channel_mapping[29] = PCM_CHANNEL_BFR;
2765 ep_payload->dev_channel_mapping[30] = PCM_CHANNEL_LW;
2766 ep_payload->dev_channel_mapping[31] = PCM_CHANNEL_RW;
Dieter Luecking50c55352018-09-28 14:29:17 +02002767 } else {
2768 pr_err("%s: invalid num_chan %d\n", __func__,
2769 channel_mode);
2770 rc = -EINVAL;
2771 goto inval_ch_mod;
2772 }
2773 }
2774
2775non_mch_path:
2776inval_ch_mod:
2777 return rc;
2778}
2779
2780static int adm_arrange_mch_ep2_map_v8(
2781 struct adm_device_endpoint_payload *ep_payload,
2782 int channel_mode)
2783{
2784 int rc = 0;
2785
2786 memset(ep_payload->dev_channel_mapping, 0,
2787 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2788
2789 if (channel_mode == 1) {
2790 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2791 } else if (channel_mode == 2) {
2792 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2793 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2794 } else if (channel_mode == 3) {
2795 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2796 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2797 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2798 } else if (channel_mode == 4) {
2799 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2800 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2801 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2802 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2803 } else if (channel_mode == 5) {
2804 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2805 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2806 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2807 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2808 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2809 } else if (channel_mode == 6) {
2810 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2811 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2812 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2813 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2814 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2815 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2816 } else if (channel_mode == 8) {
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_LFE;
2820 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2821 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2822 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2823 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2824 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2825 } else if (channel_mode == 10) {
2826 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2827 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2828 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2829 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2830 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2831 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2832 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2833 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2834 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
Ralf Herzfb81b6e2018-12-12 10:36:11 +01002835 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
Dieter Luecking50c55352018-09-28 14:29:17 +02002836 } else if (channel_mode == 12) {
2837 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2838 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2839 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2840 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2841 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2842 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2843 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2844 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2845 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2846 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2847 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2848 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2849 } else if (channel_mode == 16) {
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_CS;
Ralf Herzfb81b6e2018-12-12 10:36:11 +01002859 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
Dieter Luecking50c55352018-09-28 14:29:17 +02002860 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2861 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2862 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2863 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2864 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2865 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
Cong Tang04a6cfa2019-02-26 15:08:55 +08002866 } else if (channel_mode == 32) {
2867 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2868 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2869 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2870 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2871 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2872 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2873 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2874 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2875 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
2876 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
2877 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2878 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2879 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2880 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2881 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2882 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
2883 ep_payload->dev_channel_mapping[16] = PCM_CHANNEL_LFE2;
2884 ep_payload->dev_channel_mapping[17] = PCM_CHANNEL_SL;
2885 ep_payload->dev_channel_mapping[18] = PCM_CHANNEL_SR;
2886 ep_payload->dev_channel_mapping[19] = PCM_CHANNEL_TFL;
2887 ep_payload->dev_channel_mapping[20] = PCM_CHANNEL_TFR;
2888 ep_payload->dev_channel_mapping[21] = PCM_CHANNEL_TC;
2889 ep_payload->dev_channel_mapping[22] = PCM_CHANNEL_TBL;
2890 ep_payload->dev_channel_mapping[23] = PCM_CHANNEL_TBR;
2891 ep_payload->dev_channel_mapping[24] = PCM_CHANNEL_TSL;
2892 ep_payload->dev_channel_mapping[25] = PCM_CHANNEL_TSR;
2893 ep_payload->dev_channel_mapping[26] = PCM_CHANNEL_TBC;
2894 ep_payload->dev_channel_mapping[27] = PCM_CHANNEL_BFC;
2895 ep_payload->dev_channel_mapping[28] = PCM_CHANNEL_BFL;
2896 ep_payload->dev_channel_mapping[29] = PCM_CHANNEL_BFR;
2897 ep_payload->dev_channel_mapping[30] = PCM_CHANNEL_LW;
2898 ep_payload->dev_channel_mapping[31] = PCM_CHANNEL_RW;
Dieter Luecking50c55352018-09-28 14:29:17 +02002899 } else {
2900 pr_err("%s: invalid num_chan %d\n", __func__,
2901 channel_mode);
2902 rc = -EINVAL;
2903 }
2904
2905 return rc;
2906}
Dhananjay Kumar43034392019-01-16 21:57:58 +05302907
2908static int adm_copp_set_ec_ref_mfc_cfg(int port_id, int copp_idx,
2909 int sample_rate, int bps,
2910 int in_channels, int out_channels)
2911{
2912 struct audproc_mfc_param_media_fmt mfc_cfg;
2913 struct param_hdr_v3 param_hdr;
2914 u16 *chmixer_params = NULL;
2915 int rc = 0, i = 0, j = 0, param_index = 0, param_size = 0;
2916 struct adm_device_endpoint_payload ep_payload = {0, 0, 0, {0}};
2917
2918 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
2919 memset(&ep_payload, 0, sizeof(ep_payload));
2920 memset(&param_hdr, 0, sizeof(param_hdr));
2921
2922 param_hdr.module_id = AUDPROC_MODULE_ID_MFC_EC_REF;
2923 param_hdr.instance_id = INSTANCE_ID_0;
2924
2925 pr_debug("%s: port_id %d copp_idx %d SR %d, BW %d in_ch %d out_ch %d\n",
2926 __func__, port_id, copp_idx, sample_rate,
2927 bps, in_channels, out_channels);
2928
Dhananjay Kumar3d61b362019-03-01 15:47:56 +05302929 if (out_channels <= 0 || out_channels > AUDPROC_MFC_OUT_CHANNELS_MAX) {
2930 pr_err("%s: unsupported out channels=%d\n", __func__, out_channels);
2931 return -EINVAL;
2932 }
2933
Dhananjay Kumar43034392019-01-16 21:57:58 +05302934 /* 1. Update Media Format */
2935 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
2936 param_hdr.param_size = sizeof(mfc_cfg);
2937
2938 mfc_cfg.sampling_rate = sample_rate;
2939 mfc_cfg.bits_per_sample = bps;
2940 mfc_cfg.num_channels = out_channels;
2941
2942 ep_payload.dev_num_channel = out_channels;
2943 rc = adm_arrange_mch_ep2_map_v8(&ep_payload, out_channels);
2944 if (rc < 0) {
2945 pr_err("%s: unable to get map for out channels=%d\n",
2946 __func__, out_channels);
2947 return -EINVAL;
2948 }
2949
2950 for (i = 0; i < out_channels; i++)
2951 mfc_cfg.channel_type[i] = (uint16_t) ep_payload.dev_channel_mapping[i];
2952
2953
2954 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx,
2955 param_hdr, (uint8_t *) &mfc_cfg);
2956 if (rc) {
2957 pr_err("%s: Failed to set media format, err %d\n", __func__, rc);
2958 return rc;
2959 }
2960
2961 /* 2. Send Channel Mixer params */
2962 param_size = 2 * (4 + out_channels + in_channels + (out_channels * in_channels));
2963 param_size = round_up(param_size, 4);
2964 param_hdr.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
2965 param_hdr.param_size = param_size;
2966
2967 pr_debug("%s: chmixer param sz = %d\n", __func__, param_size);
2968 chmixer_params = kzalloc(param_size, GFP_KERNEL);
2969 if (!chmixer_params) {
2970 return -ENOMEM;
2971 }
2972 param_index = 2; /* param[0] and [1] represents chmixer rule(always 0) */
2973 chmixer_params[param_index++] = out_channels;
2974 chmixer_params[param_index++] = in_channels;
2975
2976 /* output channel map is same as one set in media format */
2977 for (i = 0; i < out_channels; i++)
2978 chmixer_params[param_index++] = ep_payload.dev_channel_mapping[i];
2979
2980 /* input channel map should be same as one set for ep2 during copp open */
2981 ep_payload.dev_num_channel = in_channels;
2982 rc = adm_arrange_mch_ep2_map_v8(&ep_payload, in_channels);
2983 if (rc < 0) {
2984 pr_err("%s: unable to get in channal map\n", __func__);
2985 goto exit;
2986 }
2987 for (i = 0; i < in_channels; i++)
2988 chmixer_params[param_index++] = ep_payload.dev_channel_mapping[i];
2989
2990 for (i = 0; i < out_channels; i++)
2991 for (j = 0; j < in_channels; j++)
2992 chmixer_params[param_index++] = this_adm.ec_ref_chmixer_weights[i][j];
2993
2994 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx,
2995 param_hdr, (uint8_t *) chmixer_params);
2996 if (rc)
2997 pr_err("%s: Failed to set chmixer params, err %d\n", __func__, rc);
2998
2999exit:
3000 kfree(chmixer_params);
3001 return rc;
3002}
3003
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303004/**
3005 * adm_open -
3006 * command to send ADM open
3007 *
3008 * @port_id: port id number
3009 * @path: direction or ADM path type
3010 * @rate: sample rate of session
3011 * @channel_mode: number of channels set
3012 * @topology: topology active for this session
3013 * @perf_mode: performance mode like LL/ULL/..
3014 * @bit_width: bit width to set for copp
3015 * @app_type: App type used for this session
3016 * @acdb_id: ACDB ID of this device
Surendar Karkae7507512018-07-20 15:46:54 +05303017 * @session_type: type of session
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303018 *
3019 * Returns 0 on success or error on failure
3020 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303021int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
Surendar Karkae7507512018-07-20 15:46:54 +05303022 int perf_mode, uint16_t bit_width, int app_type, int acdb_id,
Sanjana B61518cf2019-11-12 23:09:27 +05303023 int session_type, uint32_t passthr_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303024{
3025 struct adm_cmd_device_open_v5 open;
3026 struct adm_cmd_device_open_v6 open_v6;
Dieter Luecking50c55352018-09-28 14:29:17 +02003027 struct adm_cmd_device_open_v8 open_v8;
3028 struct adm_device_endpoint_payload ep1_payload;
3029 struct adm_device_endpoint_payload ep2_payload;
3030 int ep1_payload_size = 0;
3031 int ep2_payload_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303032 int ret = 0;
Asish Bhattacharya34504582017-08-08 12:55:01 +05303033 int port_idx, flags;
3034 int copp_idx = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303035 int tmp_port = q6audio_get_port_id(port_id);
Dieter Luecking50c55352018-09-28 14:29:17 +02003036 void *adm_params = NULL;
3037 int param_size;
Dhananjay Kumar43034392019-01-16 21:57:58 +05303038 int num_ec_ref_rx_chans = this_adm.num_ec_ref_rx_chans;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303039
3040 pr_debug("%s:port %#x path:%d rate:%d mode:%d perf_mode:%d,topo_id %d\n",
3041 __func__, port_id, path, rate, channel_mode, perf_mode,
3042 topology);
3043
3044 port_id = q6audio_convert_virtual_to_portid(port_id);
3045 port_idx = adm_validate_and_get_port_index(port_id);
3046 if (port_idx < 0) {
3047 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
3048 return -EINVAL;
3049 }
Dieter Luecking50c55352018-09-28 14:29:17 +02003050 if (channel_mode < 0 || channel_mode > 32) {
3051 pr_err("%s: Invalid channel number 0x%x\n",
3052 __func__, channel_mode);
3053 return -EINVAL;
3054 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303055
3056 if (this_adm.apr == NULL) {
3057 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
3058 0xFFFFFFFF, &this_adm);
3059 if (this_adm.apr == NULL) {
3060 pr_err("%s: Unable to register ADM\n", __func__);
3061 return -ENODEV;
3062 }
3063 rtac_set_adm_handle(this_adm.apr);
3064 }
3065
3066 if (perf_mode == ULL_POST_PROCESSING_PCM_MODE) {
3067 flags = ADM_ULL_POST_PROCESSING_DEVICE_SESSION;
3068 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
3069 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
3070 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
3071 topology = DEFAULT_COPP_TOPOLOGY;
3072 } else if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
3073 flags = ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
3074 topology = NULL_COPP_TOPOLOGY;
3075 rate = ULL_SUPPORTED_SAMPLE_RATE;
3076 bit_width = ULL_SUPPORTED_BITS_PER_SAMPLE;
3077 } else if (perf_mode == LOW_LATENCY_PCM_MODE) {
3078 flags = ADM_LOW_LATENCY_DEVICE_SESSION;
3079 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
3080 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
3081 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
3082 topology = DEFAULT_COPP_TOPOLOGY;
3083 } else {
3084 if ((path == ADM_PATH_COMPRESSED_RX) ||
3085 (path == ADM_PATH_COMPRESSED_TX))
3086 flags = 0;
3087 else
3088 flags = ADM_LEGACY_DEVICE_SESSION;
3089 }
3090
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05303091 if ((topology == VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY) ||
kunleiz1529b552019-01-24 17:15:49 +08003092 (topology == VPM_TX_DM_FLUENCE_EF_COPP_TOPOLOGY)) {
3093 if ((rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_8K) &&
3094 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_16K) &&
3095 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_32K) &&
3096 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_48K))
Yunfei Zhangaf3faf22019-09-15 15:50:39 +08003097 rate = 16000;
3098 }
3099 if ((topology == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY) ||
3100 (topology == VPM_TX_DM_RFECNS_COPP_TOPOLOGY)) {
3101 if ((rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_8K) &&
3102 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_16K) &&
3103 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_32K))
3104 rate = 16000;
kunleiz1529b552019-01-24 17:15:49 +08003105 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303106
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08003107 if (topology == FFECNS_TOPOLOGY) {
3108 this_adm.ffecns_port_id = port_id;
3109 pr_debug("%s: ffecns port id =%x\n", __func__,
3110 this_adm.ffecns_port_id);
3111 }
3112
Kunlei Zhangd3443892020-05-27 17:58:10 +08003113 if (topology == VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY ||
3114 topology == VPM_TX_VOICE_FLUENCE_SM_COPP_TOPOLOGY)
kunleizc0cd19e2018-10-18 17:11:35 +08003115 channel_mode = 1;
3116
Asish Bhattacharya34504582017-08-08 12:55:01 +05303117 /*
3118 * Routing driver reuses the same adm for streams with the same
3119 * app_type, sample_rate etc.
3120 * This isn't allowed for ULL streams as per the DSP interface
3121 */
3122 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE)
3123 copp_idx = adm_get_idx_if_copp_exists(port_idx, topology,
3124 perf_mode,
3125 rate, bit_width,
Surendar Karkae7507512018-07-20 15:46:54 +05303126 app_type, session_type);
Asish Bhattacharya34504582017-08-08 12:55:01 +05303127
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303128 if (copp_idx < 0) {
3129 copp_idx = adm_get_next_available_copp(port_idx);
3130 if (copp_idx >= MAX_COPPS_PER_PORT) {
3131 pr_err("%s: exceeded copp id %d\n",
3132 __func__, copp_idx);
3133 return -EINVAL;
3134 }
3135 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
3136 atomic_set(&this_adm.copp.topology[port_idx][copp_idx],
3137 topology);
3138 atomic_set(&this_adm.copp.mode[port_idx][copp_idx],
3139 perf_mode);
3140 atomic_set(&this_adm.copp.rate[port_idx][copp_idx],
3141 rate);
3142 atomic_set(&this_adm.copp.channels[port_idx][copp_idx],
3143 channel_mode);
3144 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx],
3145 bit_width);
3146 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx],
3147 app_type);
3148 atomic_set(&this_adm.copp.acdb_id[port_idx][copp_idx],
3149 acdb_id);
Surendar Karkae7507512018-07-20 15:46:54 +05303150 atomic_set(&this_adm.copp.session_type[port_idx][copp_idx],
3151 session_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303152 set_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3153 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
3154 if ((path != ADM_PATH_COMPRESSED_RX) &&
3155 (path != ADM_PATH_COMPRESSED_TX))
3156 send_adm_custom_topology();
3157 }
3158
3159 if (this_adm.copp.adm_delay[port_idx][copp_idx] &&
3160 perf_mode == LEGACY_PCM_MODE) {
3161 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
3162 1);
3163 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
3164 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
3165 }
3166
3167 /* Create a COPP if port id are not enabled */
3168 if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) {
3169 pr_debug("%s: open ADM: port_idx: %d, copp_idx: %d\n", __func__,
3170 port_idx, copp_idx);
Dieter Luecking50c55352018-09-28 14:29:17 +02003171 if ((topology == SRS_TRUMEDIA_TOPOLOGY_ID) &&
3172 perf_mode == LEGACY_PCM_MODE) {
3173 int res;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303174
Dieter Luecking50c55352018-09-28 14:29:17 +02003175 atomic_set(&this_adm.mem_map_index, ADM_SRS_TRUMEDIA);
3176 msm_dts_srs_tm_ion_memmap(&this_adm.outband_memmap);
3177 res = adm_memory_map_regions(
3178 &this_adm.outband_memmap.paddr, 0,
3179 (uint32_t *)&this_adm.outband_memmap.size, 1);
3180 if (res < 0) {
3181 pr_err("%s: SRS adm_memory_map_regions failed! addr = 0x%pK, size = %d\n",
3182 __func__,
3183 (void *)this_adm.outband_memmap.paddr,
3184 (uint32_t)this_adm.outband_memmap.size);
3185 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303186 }
3187
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303188
Mangesh Kunchamwar9f295c72018-10-08 18:20:41 +05303189 if ((q6core_get_avcs_api_version_per_service(
Dieter Luecking50c55352018-09-28 14:29:17 +02003190 APRV2_IDS_SERVICE_ID_ADSP_ADM_V) >=
Dieter Luecking9fb7c8c2019-03-06 13:31:09 +01003191 ADSP_ADM_API_VERSION_V3)) {
Dieter Luecking50c55352018-09-28 14:29:17 +02003192 memset(&open_v8, 0, sizeof(open_v8));
3193 memset(&ep1_payload, 0, sizeof(ep1_payload));
3194 memset(&ep2_payload, 0, sizeof(ep2_payload));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303195
Dieter Luecking50c55352018-09-28 14:29:17 +02003196 open_v8.hdr.hdr_field = APR_HDR_FIELD(
3197 APR_MSG_TYPE_SEQ_CMD,
3198 APR_HDR_LEN(APR_HDR_SIZE),
3199 APR_PKT_VER);
3200 open_v8.hdr.src_svc = APR_SVC_ADM;
3201 open_v8.hdr.src_domain = APR_DOMAIN_APPS;
3202 open_v8.hdr.src_port = tmp_port;
3203 open_v8.hdr.dest_svc = APR_SVC_ADM;
3204 open_v8.hdr.dest_domain = APR_DOMAIN_ADSP;
3205 open_v8.hdr.dest_port = tmp_port;
3206 open_v8.hdr.token = port_idx << 16 | copp_idx;
3207 open_v8.hdr.opcode = ADM_CMD_DEVICE_OPEN_V8;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303208
Dieter Luecking50c55352018-09-28 14:29:17 +02003209 if (this_adm.native_mode != 0) {
3210 open_v8.flags = flags |
3211 (this_adm.native_mode << 11);
3212 this_adm.native_mode = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303213 } else {
Dieter Luecking50c55352018-09-28 14:29:17 +02003214 open_v8.flags = flags;
3215 }
3216 open_v8.mode_of_operation = path;
3217 open_v8.endpoint_id_1 = tmp_port;
3218 open_v8.endpoint_id_2 = 0xFFFF;
3219 open_v8.endpoint_id_3 = 0xFFFF;
3220
Chaithanya Krishna Bacharaju8b0abba2019-01-11 19:35:54 +05303221 if (((this_adm.ec_ref_rx & AFE_PORT_INVALID) !=
3222 AFE_PORT_INVALID) &&
3223 (path != ADM_PATH_PLAYBACK)) {
Surendar Karkade79a062018-12-05 14:18:55 +05303224 if (this_adm.num_ec_ref_rx_chans != 0) {
3225 open_v8.endpoint_id_2 =
3226 this_adm.ec_ref_rx;
Chaithanya Krishna Bacharaju757f0d22019-06-21 13:10:22 +05303227 this_adm.ec_ref_rx = AFE_PORT_INVALID;
Surendar Karkade79a062018-12-05 14:18:55 +05303228 } else {
3229 pr_err("%s: EC channels not set %d\n",
3230 __func__,
3231 this_adm.num_ec_ref_rx_chans);
3232 return -EINVAL;
3233 }
Dieter Luecking41620832018-11-14 15:11:47 +01003234 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303235
Dieter Luecking50c55352018-09-28 14:29:17 +02003236 open_v8.topology_id = topology;
Sanjana B61518cf2019-11-12 23:09:27 +05303237 open_v8.compressed_data_type = 0;
3238 if (passthr_mode == COMPRESSED_PASSTHROUGH_DSD)
3239 open_v8.compressed_data_type = 1;
Dieter Luecking50c55352018-09-28 14:29:17 +02003240
3241 /* variable endpoint payload */
3242 ep1_payload.dev_num_channel = channel_mode & 0x00FF;
3243 ep1_payload.bit_width = bit_width;
3244 ep1_payload.sample_rate = rate;
3245 ret = adm_arrange_mch_map_v8(&ep1_payload, path,
Rohit kumar2054b692019-02-01 18:01:12 +05303246 channel_mode, port_idx);
Dieter Luecking50c55352018-09-28 14:29:17 +02003247 if (ret)
3248 return ret;
3249
3250 pr_debug("%s: port_id=0x%x %x %x topology_id=0x%X flags %x ref_ch %x\n",
3251 __func__, open_v8.endpoint_id_1,
3252 open_v8.endpoint_id_2,
3253 open_v8.endpoint_id_3,
3254 open_v8.topology_id,
3255 open_v8.flags,
3256 this_adm.num_ec_ref_rx_chans);
3257
3258 ep1_payload_size = 8 +
3259 roundup(ep1_payload.dev_num_channel, 4);
3260 param_size = sizeof(struct adm_cmd_device_open_v8)
3261 + ep1_payload_size;
3262 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3263
Dieter Luecking27c57722018-10-05 16:45:41 +02003264 if ((this_adm.num_ec_ref_rx_chans != 0)
3265 && (path != ADM_PATH_PLAYBACK)
Dieter Luecking50c55352018-09-28 14:29:17 +02003266 && (open_v8.endpoint_id_2 != 0xFFFF)) {
3267 ep2_payload.dev_num_channel =
3268 this_adm.num_ec_ref_rx_chans;
Dieter Luecking50c55352018-09-28 14:29:17 +02003269
3270 if (this_adm.ec_ref_rx_bit_width != 0) {
3271 ep2_payload.bit_width =
3272 this_adm.ec_ref_rx_bit_width;
Dieter Luecking50c55352018-09-28 14:29:17 +02003273 } else {
3274 ep2_payload.bit_width = bit_width;
3275 }
3276
3277 if (this_adm.ec_ref_rx_sampling_rate != 0) {
3278 ep2_payload.sample_rate =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303279 this_adm.ec_ref_rx_sampling_rate;
Dieter Luecking50c55352018-09-28 14:29:17 +02003280 } else {
3281 ep2_payload.sample_rate = rate;
3282 }
3283
3284 pr_debug("%s: adm open_v8 eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
3285 __func__,
3286 ep2_payload.dev_num_channel,
3287 ep2_payload.bit_width,
3288 ep2_payload.sample_rate);
3289
3290 ret = adm_arrange_mch_ep2_map_v8(&ep2_payload,
3291 ep2_payload.dev_num_channel);
3292
3293 if (ret)
3294 return ret;
3295 ep2_payload_size = 8 +
3296 roundup(ep2_payload.dev_num_channel, 4);
3297 param_size += ep2_payload_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303298 }
3299
Dieter Luecking27c57722018-10-05 16:45:41 +02003300 open_v8.hdr.pkt_size = param_size;
Dieter Luecking50c55352018-09-28 14:29:17 +02003301 adm_params = kzalloc(param_size, GFP_KERNEL);
3302 if (!adm_params)
3303 return -ENOMEM;
Dieter Luecking50c55352018-09-28 14:29:17 +02003304 memcpy(adm_params, &open_v8, sizeof(open_v8));
3305 memcpy(adm_params + sizeof(open_v8),
3306 (void *)&ep1_payload,
3307 ep1_payload_size);
Dieter Luecking27c57722018-10-05 16:45:41 +02003308
3309 if ((this_adm.num_ec_ref_rx_chans != 0)
3310 && (path != ADM_PATH_PLAYBACK)
3311 && (open_v8.endpoint_id_2 != 0xFFFF)) {
3312 memcpy(adm_params + sizeof(open_v8)
3313 + ep1_payload_size,
3314 (void *)&ep2_payload,
3315 ep2_payload_size);
3316 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303317
Soumya Managolid0adc6a2021-02-24 19:33:53 +05303318 ret = adm_apr_send_pkt((uint32_t *) adm_params,
3319 &this_adm.copp.wait[port_idx][copp_idx],
3320 port_idx, copp_idx, open_v8.hdr.opcode);
Dieter Luecking50c55352018-09-28 14:29:17 +02003321 if (ret < 0) {
3322 pr_err("%s: port_id: 0x%x for[0x%x] failed %d for open_v8\n",
3323 __func__, tmp_port, port_id, ret);
3324 return -EINVAL;
3325 }
3326 kfree(adm_params);
3327 } else {
3328
3329 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3330 APR_HDR_LEN(APR_HDR_SIZE),
3331 APR_PKT_VER);
3332 open.hdr.pkt_size = sizeof(open);
3333 open.hdr.src_svc = APR_SVC_ADM;
3334 open.hdr.src_domain = APR_DOMAIN_APPS;
3335 open.hdr.src_port = tmp_port;
3336 open.hdr.dest_svc = APR_SVC_ADM;
3337 open.hdr.dest_domain = APR_DOMAIN_ADSP;
3338 open.hdr.dest_port = tmp_port;
3339 open.hdr.token = port_idx << 16 | copp_idx;
3340 open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
3341 open.flags = flags;
3342 open.mode_of_operation = path;
3343 open.endpoint_id_1 = tmp_port;
3344 open.endpoint_id_2 = 0xFFFF;
3345
Surendar Karkae7507512018-07-20 15:46:54 +05303346 if (this_adm.ec_ref_rx && (path != 1) &&
3347 (afe_get_port_type(tmp_port) == MSM_AFE_PORT_TYPE_TX)) {
Dieter Luecking50c55352018-09-28 14:29:17 +02003348 open.endpoint_id_2 = this_adm.ec_ref_rx;
Dieter Luecking50c55352018-09-28 14:29:17 +02003349 }
3350
3351 open.topology_id = topology;
3352
3353 open.dev_num_channel = channel_mode & 0x00FF;
3354 open.bit_width = bit_width;
3355 WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
3356 (rate != ULL_SUPPORTED_SAMPLE_RATE));
3357 open.sample_rate = rate;
3358
Rohit kumar2054b692019-02-01 18:01:12 +05303359 ret = adm_arrange_mch_map(&open, path, channel_mode,
3360 port_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303361 if (ret)
3362 return ret;
3363
Dieter Luecking50c55352018-09-28 14:29:17 +02003364 pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
3365 __func__, open.endpoint_id_1, open.sample_rate,
3366 open.topology_id);
3367
3368 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3369
3370 if ((this_adm.num_ec_ref_rx_chans != 0) &&
3371 (path != 1) && (open.endpoint_id_2 != 0xFFFF)) {
3372 memset(&open_v6, 0,
3373 sizeof(struct adm_cmd_device_open_v6));
3374 memcpy(&open_v6, &open,
3375 sizeof(struct adm_cmd_device_open_v5));
3376 open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
3377 open_v6.hdr.pkt_size = sizeof(open_v6);
3378 open_v6.dev_num_channel_eid2 =
3379 this_adm.num_ec_ref_rx_chans;
Dieter Luecking50c55352018-09-28 14:29:17 +02003380
3381 if (this_adm.ec_ref_rx_bit_width != 0) {
3382 open_v6.bit_width_eid2 =
3383 this_adm.ec_ref_rx_bit_width;
Dieter Luecking50c55352018-09-28 14:29:17 +02003384 } else {
3385 open_v6.bit_width_eid2 = bit_width;
3386 }
3387
3388 if (this_adm.ec_ref_rx_sampling_rate != 0) {
3389 open_v6.sample_rate_eid2 =
3390 this_adm.ec_ref_rx_sampling_rate;
Dieter Luecking50c55352018-09-28 14:29:17 +02003391 } else {
3392 open_v6.sample_rate_eid2 = rate;
3393 }
3394
3395 pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
3396 __func__, open_v6.dev_num_channel_eid2,
3397 open_v6.bit_width_eid2,
3398 open_v6.sample_rate_eid2);
3399
3400 ret = adm_arrange_mch_ep2_map(&open_v6,
3401 open_v6.dev_num_channel_eid2);
3402
3403 if (ret)
3404 return ret;
3405
Soumya Managolid0adc6a2021-02-24 19:33:53 +05303406 ret = adm_apr_send_pkt((uint32_t *) &open_v6,
3407 &this_adm.copp.wait[port_idx][copp_idx],
3408 port_idx, copp_idx, open_v6.hdr.opcode);
Dieter Luecking50c55352018-09-28 14:29:17 +02003409 } else {
Soumya Managolid0adc6a2021-02-24 19:33:53 +05303410 ret = adm_apr_send_pkt((uint32_t *) &open,
3411 &this_adm.copp.wait[port_idx][copp_idx],
3412 port_idx, copp_idx, open.hdr.opcode);
Dieter Luecking50c55352018-09-28 14:29:17 +02003413 }
3414 if (ret < 0) {
3415 pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
3416 __func__, tmp_port, port_id, ret);
3417 return -EINVAL;
3418 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303419 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303420 }
3421 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
Dhananjay Kumar43034392019-01-16 21:57:58 +05303422
3423 /*
3424 * Configure MFC(in ec_ref path) if chmixing param is applicable and set.
3425 * Except channels and channel maps the media format config for this module
3426 * should match with the COPP(EP1) config values.
3427 */
3428 if (path != ADM_PATH_PLAYBACK &&
3429 this_adm.num_ec_ref_rx_chans_downmixed != 0 &&
3430 num_ec_ref_rx_chans != this_adm.num_ec_ref_rx_chans_downmixed) {
3431 ret = adm_copp_set_ec_ref_mfc_cfg(port_id, copp_idx,
3432 rate, bit_width, num_ec_ref_rx_chans,
3433 this_adm.num_ec_ref_rx_chans_downmixed);
3434 this_adm.num_ec_ref_rx_chans_downmixed = 0;
3435 if (ret)
3436 pr_err("%s: set EC REF MFC cfg failed, err %d\n", __func__, ret);
3437 }
3438
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303439 return copp_idx;
3440}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303441EXPORT_SYMBOL(adm_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303442
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303443/**
3444 * adm_copp_mfc_cfg -
3445 * command to send ADM MFC config
3446 *
3447 * @port_id: Port ID number
3448 * @copp_idx: copp index assigned
3449 * @dst_sample_rate: sink sample rate
3450 *
3451 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303452void adm_copp_mfc_cfg(int port_id, int copp_idx, int dst_sample_rate)
3453{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003454 struct audproc_mfc_param_media_fmt mfc_cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303455 struct adm_cmd_device_open_v5 open;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003456 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303457 int port_idx;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303458 int rc = 0;
3459 int i = 0;
3460
3461 port_id = q6audio_convert_virtual_to_portid(port_id);
3462 port_idx = adm_validate_and_get_port_index(port_id);
3463
3464 if (port_idx < 0) {
3465 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
3466 goto fail_cmd;
3467 }
3468
3469 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
3470 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
3471 goto fail_cmd;
3472 }
3473
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003474 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
3475 memset(&open, 0, sizeof(open));
3476 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303477
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003478 param_hdr.module_id = AUDPROC_MODULE_ID_MFC;
3479 param_hdr.instance_id = INSTANCE_ID_0;
3480 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
3481 param_hdr.param_size = sizeof(mfc_cfg);
3482
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303483 mfc_cfg.sampling_rate = dst_sample_rate;
3484 mfc_cfg.bits_per_sample =
3485 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
3486 open.dev_num_channel = mfc_cfg.num_channels =
3487 atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
3488
3489 rc = adm_arrange_mch_map(&open, ADM_PATH_PLAYBACK,
Rohit kumar2054b692019-02-01 18:01:12 +05303490 mfc_cfg.num_channels, port_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303491 if (rc < 0) {
3492 pr_err("%s: unable to get channal map\n", __func__);
3493 goto fail_cmd;
3494 }
3495
3496 for (i = 0; i < mfc_cfg.num_channels; i++)
3497 mfc_cfg.channel_type[i] =
3498 (uint16_t) open.dev_channel_mapping[i];
3499
3500 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3501
3502 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",
3503 __func__, port_idx, copp_idx,
3504 atomic_read(&this_adm.copp.rate[port_idx][copp_idx]),
3505 mfc_cfg.bits_per_sample, mfc_cfg.num_channels,
3506 mfc_cfg.sampling_rate);
3507
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003508 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
3509 (uint8_t *) &mfc_cfg);
3510 if (rc)
3511 pr_err("%s: Failed to set media format configuration data, err %d\n",
3512 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303513
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303514fail_cmd:
3515 return;
3516}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303517EXPORT_SYMBOL(adm_copp_mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303518
3519static void route_set_opcode_matrix_id(
3520 struct adm_cmd_matrix_map_routings_v5 **route_addr,
3521 int path, uint32_t passthr_mode)
3522{
3523 struct adm_cmd_matrix_map_routings_v5 *route = *route_addr;
3524
3525 switch (path) {
3526 case ADM_PATH_PLAYBACK:
3527 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
3528 route->matrix_id = ADM_MATRIX_ID_AUDIO_RX;
3529 break;
3530 case ADM_PATH_LIVE_REC:
3531 if (passthr_mode == LISTEN) {
3532 route->hdr.opcode =
3533 ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3534 route->matrix_id = ADM_MATRIX_ID_LISTEN_TX;
3535 break;
3536 }
3537 /* fall through to set matrix id for non-listen case */
3538 case ADM_PATH_NONLIVE_REC:
3539 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
3540 route->matrix_id = ADM_MATRIX_ID_AUDIO_TX;
3541 break;
3542 case ADM_PATH_COMPRESSED_RX:
3543 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3544 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_RX;
3545 break;
3546 case ADM_PATH_COMPRESSED_TX:
3547 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3548 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_TX;
3549 break;
3550 default:
3551 pr_err("%s: Wrong path set[%d]\n", __func__, path);
3552 break;
3553 }
3554 pr_debug("%s: opcode 0x%x, matrix id %d\n",
3555 __func__, route->hdr.opcode, route->matrix_id);
3556}
3557
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303558/**
3559 * adm_matrix_map -
3560 * command to send ADM matrix map for ADM copp list
3561 *
3562 * @path: direction or ADM path type
3563 * @payload_map: have info of session id and associated copp_idx/num_copps
3564 * @perf_mode: performance mode like LL/ULL/..
3565 * @passthr_mode: flag to indicate passthrough mode
3566 *
3567 * Returns 0 on success or error on failure
3568 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303569int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode,
3570 uint32_t passthr_mode)
3571{
3572 struct adm_cmd_matrix_map_routings_v5 *route;
3573 struct adm_session_map_node_v5 *node;
3574 uint16_t *copps_list;
3575 int cmd_size = 0;
3576 int ret = 0, i = 0;
3577 void *payload = NULL;
3578 void *matrix_map = NULL;
3579 int port_idx, copp_idx;
3580
3581 /* Assumes port_ids have already been validated during adm_open */
3582 cmd_size = (sizeof(struct adm_cmd_matrix_map_routings_v5) +
3583 sizeof(struct adm_session_map_node_v5) +
3584 (sizeof(uint32_t) * payload_map.num_copps));
3585 matrix_map = kzalloc(cmd_size, GFP_KERNEL);
3586 if (matrix_map == NULL) {
3587 pr_err("%s: Mem alloc failed\n", __func__);
3588 ret = -EINVAL;
3589 return ret;
3590 }
3591 route = (struct adm_cmd_matrix_map_routings_v5 *)matrix_map;
3592
3593 route->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3594 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3595 route->hdr.pkt_size = cmd_size;
3596 route->hdr.src_svc = 0;
3597 route->hdr.src_domain = APR_DOMAIN_APPS;
3598 route->hdr.src_port = 0; /* Ignored */;
3599 route->hdr.dest_svc = APR_SVC_ADM;
3600 route->hdr.dest_domain = APR_DOMAIN_ADSP;
3601 route->hdr.dest_port = 0; /* Ignored */;
3602 route->hdr.token = 0;
3603 route->num_sessions = 1;
3604 route_set_opcode_matrix_id(&route, path, passthr_mode);
3605
3606 payload = ((u8 *)matrix_map +
3607 sizeof(struct adm_cmd_matrix_map_routings_v5));
3608 node = (struct adm_session_map_node_v5 *)payload;
3609
3610 node->session_id = payload_map.session_id;
3611 node->num_copps = payload_map.num_copps;
3612 payload = (u8 *)node + sizeof(struct adm_session_map_node_v5);
3613 copps_list = (uint16_t *)payload;
3614 for (i = 0; i < payload_map.num_copps; i++) {
3615 port_idx =
3616 adm_validate_and_get_port_index(payload_map.port_id[i]);
3617 if (port_idx < 0) {
3618 pr_err("%s: Invalid port_id 0x%x\n", __func__,
3619 payload_map.port_id[i]);
3620 ret = -EINVAL;
3621 goto fail_cmd;
3622 }
3623 copp_idx = payload_map.copp_idx[i];
3624 copps_list[i] = atomic_read(&this_adm.copp.id[port_idx]
3625 [copp_idx]);
3626 }
3627 atomic_set(&this_adm.matrix_map_stat, -1);
3628
3629 ret = apr_send_pkt(this_adm.apr, (uint32_t *)matrix_map);
3630 if (ret < 0) {
3631 pr_err("%s: routing for syream %d failed ret %d\n",
3632 __func__, payload_map.session_id, ret);
3633 ret = -EINVAL;
3634 goto fail_cmd;
3635 }
3636 ret = wait_event_timeout(this_adm.matrix_map_wait,
3637 atomic_read(&this_adm.matrix_map_stat) >= 0,
3638 msecs_to_jiffies(TIMEOUT_MS));
3639 if (!ret) {
3640 pr_err("%s: routing for syream %d failed\n", __func__,
3641 payload_map.session_id);
3642 ret = -EINVAL;
3643 goto fail_cmd;
3644 } else if (atomic_read(&this_adm.matrix_map_stat) > 0) {
3645 pr_err("%s: DSP returned error[%s]\n", __func__,
3646 adsp_err_get_err_str(atomic_read(
3647 &this_adm.matrix_map_stat)));
3648 ret = adsp_err_get_lnx_err_code(
3649 atomic_read(&this_adm.matrix_map_stat));
3650 goto fail_cmd;
3651 }
3652
3653 if ((perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) &&
3654 (path != ADM_PATH_COMPRESSED_RX)) {
3655 for (i = 0; i < payload_map.num_copps; i++) {
3656 port_idx = afe_get_port_index(payload_map.port_id[i]);
3657 copp_idx = payload_map.copp_idx[i];
3658 if (port_idx < 0 || copp_idx < 0 ||
3659 (copp_idx > MAX_COPPS_PER_PORT - 1)) {
3660 pr_err("%s: Invalid idx port_idx %d copp_idx %d\n",
3661 __func__, port_idx, copp_idx);
3662 continue;
3663 }
3664 rtac_add_adm_device(payload_map.port_id[i],
3665 atomic_read(&this_adm.copp.id
3666 [port_idx][copp_idx]),
3667 get_cal_path(path),
3668 payload_map.session_id,
3669 payload_map.app_type[i],
3670 payload_map.acdb_dev_id[i]);
3671
3672 if (!test_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3673 (void *)&this_adm.copp.adm_status[port_idx]
3674 [copp_idx])) {
3675 pr_debug("%s: adm copp[0x%x][%d] already sent",
3676 __func__, port_idx, copp_idx);
3677 continue;
3678 }
3679 send_adm_cal(payload_map.port_id[i], copp_idx,
3680 get_cal_path(path), perf_mode,
3681 payload_map.app_type[i],
3682 payload_map.acdb_dev_id[i],
Aditya Bavanari5106b562018-01-08 13:16:32 +05303683 payload_map.sample_rate[i],
3684 passthr_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303685 /* ADM COPP calibration is already sent */
3686 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3687 (void *)&this_adm.copp.
3688 adm_status[port_idx][copp_idx]);
3689 pr_debug("%s: copp_id: %d\n", __func__,
3690 atomic_read(&this_adm.copp.id[port_idx]
3691 [copp_idx]));
3692 }
3693 }
3694
3695fail_cmd:
3696 kfree(matrix_map);
3697 return ret;
3698}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303699EXPORT_SYMBOL(adm_matrix_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303700
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303701/**
3702 * adm_ec_ref_rx_id -
3703 * Update EC ref port ID
3704 *
3705 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303706void adm_ec_ref_rx_id(int port_id)
3707{
3708 this_adm.ec_ref_rx = port_id;
3709 pr_debug("%s: ec_ref_rx:%d\n", __func__, this_adm.ec_ref_rx);
3710}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303711EXPORT_SYMBOL(adm_ec_ref_rx_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303712
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303713/**
3714 * adm_num_ec_ref_rx_chans -
3715 * Update EC ref number of channels
3716 *
3717 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303718void adm_num_ec_ref_rx_chans(int num_chans)
3719{
3720 this_adm.num_ec_ref_rx_chans = num_chans;
3721 pr_debug("%s: num_ec_ref_rx_chans:%d\n",
3722 __func__, this_adm.num_ec_ref_rx_chans);
3723}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303724EXPORT_SYMBOL(adm_num_ec_ref_rx_chans);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303725
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303726/**
Dhananjay Kumar43034392019-01-16 21:57:58 +05303727 * adm_num_ec_rx_ref_chans_downmixed -
3728 * Update EC ref num of channels(downmixed) to be fed to EC algo
3729 *
3730 */
3731void adm_num_ec_ref_rx_chans_downmixed(int num_chans)
3732{
3733 this_adm.num_ec_ref_rx_chans_downmixed = num_chans;
3734 pr_debug("%s: num_ec_ref_rx_chans_downmixed:%d\n",
3735 __func__, this_adm.num_ec_ref_rx_chans_downmixed);
3736}
3737EXPORT_SYMBOL(adm_num_ec_ref_rx_chans_downmixed);
3738
3739/**
3740 * adm_ec_ref_chmixer_weights -
3741 * Update MFC(in ec ref) Channel Mixer Weights to be used
3742 * for downmixing rx channels before feeding them to EC algo
3743 * @out_channel_idx: index of output channel to which weightages are applicable
3744 * @weights: pointer to array having input weightages
3745 * @count: array sizeof pointer weights, max supported value is
3746 * PCM_FORMAT_MAX_NUM_CHANNEL_V8
3747 * Returns 0 on success or error on failure
3748 */
3749int adm_ec_ref_chmixer_weights(int out_channel_idx,
3750 uint16_t *weights, int count)
3751{
3752 int i = 0;
3753
3754 if (weights == NULL || count <= 0 || out_channel_idx < 0 ||
3755 count > PCM_FORMAT_MAX_NUM_CHANNEL_V8 ||
3756 out_channel_idx >= PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
3757 pr_err("%s: invalid weightages count(%d) ch_idx(%d)",
3758 __func__, count, out_channel_idx);
3759 return -EINVAL;
3760 }
3761
3762 for (i = 0; i < count; i++) {
3763 this_adm.ec_ref_chmixer_weights[out_channel_idx][i] = weights[i];
3764 pr_debug("%s: out ch idx :%d, weight[%d] = %d\n",
3765 __func__, out_channel_idx, i, weights[i]);
3766 }
3767
3768 return 0;
3769}
3770EXPORT_SYMBOL(adm_ec_ref_chmixer_weights);
3771
3772/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303773 * adm_ec_ref_rx_bit_width -
3774 * Update EC ref bit_width
3775 *
3776 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303777void adm_ec_ref_rx_bit_width(int bit_width)
3778{
3779 this_adm.ec_ref_rx_bit_width = bit_width;
3780 pr_debug("%s: ec_ref_rx_bit_width:%d\n",
3781 __func__, this_adm.ec_ref_rx_bit_width);
3782}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303783EXPORT_SYMBOL(adm_ec_ref_rx_bit_width);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303784
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303785/**
3786 * adm_ec_ref_rx_sampling_rate -
3787 * Update EC ref sample rate
3788 *
3789 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303790void adm_ec_ref_rx_sampling_rate(int sampling_rate)
3791{
3792 this_adm.ec_ref_rx_sampling_rate = sampling_rate;
3793 pr_debug("%s: ec_ref_rx_sampling_rate:%d\n",
3794 __func__, this_adm.ec_ref_rx_sampling_rate);
3795}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303796EXPORT_SYMBOL(adm_ec_ref_rx_sampling_rate);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303797
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303798/**
Dieter Luecking50c55352018-09-28 14:29:17 +02003799 * adm_set_native_mode -
3800 * Set adm channel native mode.
3801 * If enabled matrix mixer will be
3802 * running in native mode for channel
3803 * configuration for this device session.
3804 *
3805 */
3806void adm_set_native_mode(int mode)
3807{
3808 this_adm.native_mode = mode;
3809 pr_debug("%s: enable native_mode :%d\n",
3810 __func__, this_adm.native_mode);
3811}
3812EXPORT_SYMBOL(adm_set_native_mode);
3813
3814/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303815 * adm_close -
3816 * command to close ADM copp
3817 *
3818 * @port_id: Port ID number
3819 * @perf_mode: performance mode like LL/ULL/..
3820 * @copp_idx: copp index assigned
3821 *
3822 * Returns 0 on success or error on failure
3823 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303824int adm_close(int port_id, int perf_mode, int copp_idx)
3825{
3826 struct apr_hdr close;
3827
3828 int ret = 0, port_idx;
3829 int copp_id = RESET_COPP_ID;
3830
3831 pr_debug("%s: port_id=0x%x perf_mode: %d copp_idx: %d\n", __func__,
3832 port_id, perf_mode, copp_idx);
3833
3834 port_id = q6audio_convert_virtual_to_portid(port_id);
3835 port_idx = adm_validate_and_get_port_index(port_id);
3836 if (port_idx < 0) {
3837 pr_err("%s: Invalid port_id 0x%x\n",
3838 __func__, port_id);
3839 return -EINVAL;
3840 }
3841
3842 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
3843 pr_err("%s: Invalid copp idx: %d\n", __func__, copp_idx);
3844 return -EINVAL;
3845 }
3846
Rohit kumar2054b692019-02-01 18:01:12 +05303847 port_channel_map[port_idx].set_channel_map = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303848 if (this_adm.copp.adm_delay[port_idx][copp_idx] && perf_mode
3849 == LEGACY_PCM_MODE) {
3850 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
3851 1);
3852 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
3853 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
3854 }
3855
3856 atomic_dec(&this_adm.copp.cnt[port_idx][copp_idx]);
3857 if (!(atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]))) {
3858 copp_id = adm_get_copp_id(port_idx, copp_idx);
3859 pr_debug("%s: Closing ADM port_idx:%d copp_idx:%d copp_id:0x%x\n",
3860 __func__, port_idx, copp_idx, copp_id);
3861 if ((!perf_mode) && (this_adm.outband_memmap.paddr != 0) &&
3862 (atomic_read(&this_adm.copp.topology[port_idx][copp_idx]) ==
3863 SRS_TRUMEDIA_TOPOLOGY_ID)) {
3864 atomic_set(&this_adm.mem_map_index,
3865 ADM_SRS_TRUMEDIA);
3866 ret = adm_memory_unmap_regions();
3867 if (ret < 0) {
3868 pr_err("%s: adm mem unmmap err %d",
3869 __func__, ret);
3870 } else {
3871 atomic_set(&this_adm.mem_map_handles
3872 [ADM_SRS_TRUMEDIA], 0);
3873 }
3874 }
3875
3876
3877 if ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) &&
3878 this_adm.sourceTrackingData.memmap.paddr) {
3879 atomic_set(&this_adm.mem_map_index,
3880 ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
3881 ret = adm_memory_unmap_regions();
3882 if (ret < 0) {
3883 pr_err("%s: adm mem unmmap err %d",
3884 __func__, ret);
3885 }
3886 msm_audio_ion_free(
Banajit Goswami08bb7362017-11-03 22:48:23 -07003887 this_adm.sourceTrackingData.dma_buf);
3888 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303889 this_adm.sourceTrackingData.memmap.size = 0;
3890 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
3891 this_adm.sourceTrackingData.memmap.paddr = 0;
3892 this_adm.sourceTrackingData.apr_cmd_status = -1;
3893 atomic_set(&this_adm.mem_map_handles[
3894 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
3895 }
3896
3897 close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3898 APR_HDR_LEN(APR_HDR_SIZE),
3899 APR_PKT_VER);
3900 close.pkt_size = sizeof(close);
3901 close.src_svc = APR_SVC_ADM;
3902 close.src_domain = APR_DOMAIN_APPS;
3903 close.src_port = port_id;
3904 close.dest_svc = APR_SVC_ADM;
3905 close.dest_domain = APR_DOMAIN_ADSP;
3906 close.dest_port = copp_id;
3907 close.token = port_idx << 16 | copp_idx;
3908 close.opcode = ADM_CMD_DEVICE_CLOSE_V5;
3909
3910 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
3911 RESET_COPP_ID);
3912 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
3913 atomic_set(&this_adm.copp.topology[port_idx][copp_idx], 0);
3914 atomic_set(&this_adm.copp.mode[port_idx][copp_idx], 0);
3915 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3916 atomic_set(&this_adm.copp.rate[port_idx][copp_idx], 0);
3917 atomic_set(&this_adm.copp.channels[port_idx][copp_idx], 0);
3918 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx], 0);
3919 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx], 0);
Surendar Karkae7507512018-07-20 15:46:54 +05303920 atomic_set(&this_adm.copp.session_type[port_idx][copp_idx], 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303921
3922 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3923 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
Soumya Managolid0adc6a2021-02-24 19:33:53 +05303924 ret = adm_apr_send_pkt((uint32_t *) &close,
3925 &this_adm.copp.wait[port_idx][copp_idx],
3926 port_idx, copp_idx, close.opcode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303927 if (ret < 0) {
3928 pr_err("%s: ADM close failed %d\n", __func__, ret);
3929 return -EINVAL;
3930 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303931 }
3932
3933 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
3934 pr_debug("%s: remove adm device from rtac\n", __func__);
3935 rtac_remove_adm_device(port_id, copp_id);
3936 }
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08003937
3938 if (port_id == this_adm.ffecns_port_id)
3939 this_adm.ffecns_port_id = -1;
3940
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303941 return 0;
3942}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303943EXPORT_SYMBOL(adm_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303944
3945int send_rtac_audvol_cal(void)
3946{
3947 int ret = 0;
3948 int ret2 = 0;
3949 int i = 0;
3950 int copp_idx, port_idx, acdb_id, app_id, path;
3951 struct cal_block_data *cal_block = NULL;
3952 struct audio_cal_info_audvol *audvol_cal_info = NULL;
3953 struct rtac_adm rtac_adm_data;
3954
3955 mutex_lock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
3956
3957 cal_block = cal_utils_get_only_cal_block(
3958 this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07003959 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303960 pr_err("%s: can't find cal block!\n", __func__);
3961 goto unlock;
3962 }
3963
3964 audvol_cal_info = cal_block->cal_info;
3965 if (audvol_cal_info == NULL) {
3966 pr_err("%s: audvol_cal_info is NULL!\n", __func__);
3967 goto unlock;
3968 }
3969
3970 get_rtac_adm_data(&rtac_adm_data);
3971 for (; i < rtac_adm_data.num_of_dev; i++) {
3972
3973 acdb_id = rtac_adm_data.device[i].acdb_dev_id;
3974 if (acdb_id == 0)
3975 acdb_id = audvol_cal_info->acdb_id;
3976
3977 app_id = rtac_adm_data.device[i].app_type;
3978 if (app_id == 0)
3979 app_id = audvol_cal_info->app_type;
3980
3981 path = afe_get_port_type(rtac_adm_data.device[i].afe_port);
3982 if ((acdb_id == audvol_cal_info->acdb_id) &&
3983 (app_id == audvol_cal_info->app_type) &&
3984 (path == audvol_cal_info->path)) {
3985
3986 if (adm_get_indexes_from_copp_id(rtac_adm_data.
3987 device[i].copp, &copp_idx, &port_idx) != 0) {
3988 pr_debug("%s: Copp Id %d is not active\n",
3989 __func__,
3990 rtac_adm_data.device[i].copp);
3991 continue;
3992 }
3993
3994 ret2 = adm_remap_and_send_cal_block(ADM_RTAC_AUDVOL_CAL,
3995 rtac_adm_data.device[i].afe_port,
3996 copp_idx, cal_block,
3997 atomic_read(&this_adm.copp.
3998 mode[port_idx][copp_idx]),
3999 audvol_cal_info->app_type,
4000 audvol_cal_info->acdb_id,
4001 atomic_read(&this_adm.copp.
4002 rate[port_idx][copp_idx]));
4003 if (ret2 < 0) {
4004 pr_debug("%s: remap and send failed for copp Id %d, acdb id %d, app type %d, path %d\n",
4005 __func__, rtac_adm_data.device[i].copp,
4006 audvol_cal_info->acdb_id,
4007 audvol_cal_info->app_type,
4008 audvol_cal_info->path);
4009 ret = ret2;
4010 }
4011 }
4012 }
4013unlock:
4014 mutex_unlock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
4015 return ret;
4016}
4017
4018int adm_map_rtac_block(struct rtac_cal_block_data *cal_block)
4019{
4020 int result = 0;
4021
4022 pr_debug("%s:\n", __func__);
4023
4024 if (cal_block == NULL) {
4025 pr_err("%s: cal_block is NULL!\n",
4026 __func__);
4027 result = -EINVAL;
4028 goto done;
4029 }
4030
4031 if (cal_block->cal_data.paddr == 0) {
4032 pr_debug("%s: No address to map!\n",
4033 __func__);
4034 result = -EINVAL;
4035 goto done;
4036 }
4037
4038 if (cal_block->map_data.map_size == 0) {
4039 pr_debug("%s: map size is 0!\n",
4040 __func__);
4041 result = -EINVAL;
4042 goto done;
4043 }
4044
4045 /* valid port ID needed for callback use primary I2S */
4046 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
4047 result = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
4048 &cal_block->map_data.map_size, 1);
4049 if (result < 0) {
4050 pr_err("%s: RTAC mmap did not work! size = %d result %d\n",
4051 __func__,
4052 cal_block->map_data.map_size, result);
4053 pr_debug("%s: RTAC mmap did not work! addr = 0x%pK, size = %d\n",
4054 __func__,
4055 &cal_block->cal_data.paddr,
4056 cal_block->map_data.map_size);
4057 goto done;
4058 }
4059
4060 cal_block->map_data.map_handle = atomic_read(
4061 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]);
4062done:
4063 return result;
4064}
4065
4066int adm_unmap_rtac_block(uint32_t *mem_map_handle)
4067{
4068 int result = 0;
4069
4070 pr_debug("%s:\n", __func__);
4071
4072 if (mem_map_handle == NULL) {
4073 pr_debug("%s: Map handle is NULL, nothing to unmap\n",
4074 __func__);
4075 goto done;
4076 }
4077
4078 if (*mem_map_handle == 0) {
4079 pr_debug("%s: Map handle is 0, nothing to unmap\n",
4080 __func__);
4081 goto done;
4082 }
4083
4084 if (*mem_map_handle != atomic_read(
4085 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL])) {
4086 pr_err("%s: Map handles do not match! Unmapping RTAC, RTAC map 0x%x, ADM map 0x%x\n",
4087 __func__, *mem_map_handle, atomic_read(
4088 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]));
4089
4090 /* if mismatch use handle passed in to unmap */
4091 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL],
4092 *mem_map_handle);
4093 }
4094
4095 /* valid port ID needed for callback use primary I2S */
4096 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
4097 result = adm_memory_unmap_regions();
4098 if (result < 0) {
4099 pr_debug("%s: adm_memory_unmap_regions failed, error %d\n",
4100 __func__, result);
4101 } else {
4102 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL], 0);
4103 *mem_map_handle = 0;
4104 }
4105done:
4106 return result;
4107}
4108
4109static int get_cal_type_index(int32_t cal_type)
4110{
4111 int ret = -EINVAL;
4112
4113 switch (cal_type) {
4114 case ADM_AUDPROC_CAL_TYPE:
4115 ret = ADM_AUDPROC_CAL;
4116 break;
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304117 case ADM_LSM_AUDPROC_CAL_TYPE:
4118 ret = ADM_LSM_AUDPROC_CAL;
4119 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304120 case ADM_AUDVOL_CAL_TYPE:
4121 ret = ADM_AUDVOL_CAL;
4122 break;
4123 case ADM_CUST_TOPOLOGY_CAL_TYPE:
4124 ret = ADM_CUSTOM_TOP_CAL;
4125 break;
4126 case ADM_RTAC_INFO_CAL_TYPE:
4127 ret = ADM_RTAC_INFO_CAL;
4128 break;
4129 case ADM_RTAC_APR_CAL_TYPE:
4130 ret = ADM_RTAC_APR_CAL;
4131 break;
4132 case ADM_RTAC_AUDVOL_CAL_TYPE:
4133 ret = ADM_RTAC_AUDVOL_CAL;
4134 break;
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004135 case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
4136 ret = ADM_LSM_AUDPROC_PERSISTENT_CAL;
4137 break;
Ramlal Karra471fe912020-04-13 13:47:07 +05304138 case ADM_AUDPROC_PERSISTENT_CAL_TYPE:
4139 ret = ADM_AUDPROC_PERSISTENT_CAL;
4140 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304141 default:
4142 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
4143 }
4144 return ret;
4145}
4146
4147static int adm_alloc_cal(int32_t cal_type, size_t data_size, void *data)
4148{
4149 int ret = 0;
4150 int cal_index;
4151
4152 pr_debug("%s:\n", __func__);
4153
4154 cal_index = get_cal_type_index(cal_type);
4155 if (cal_index < 0) {
4156 pr_err("%s: could not get cal index %d!\n",
4157 __func__, cal_index);
4158 ret = -EINVAL;
4159 goto done;
4160 }
4161
4162 ret = cal_utils_alloc_cal(data_size, data,
4163 this_adm.cal_data[cal_index], 0, NULL);
4164 if (ret < 0) {
4165 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
4166 __func__, ret, cal_type);
4167 ret = -EINVAL;
4168 goto done;
4169 }
4170done:
4171 return ret;
4172}
4173
4174static int adm_dealloc_cal(int32_t cal_type, size_t data_size, void *data)
4175{
4176 int ret = 0;
4177 int cal_index;
4178
4179 pr_debug("%s:\n", __func__);
4180
4181 cal_index = get_cal_type_index(cal_type);
4182 if (cal_index < 0) {
4183 pr_err("%s: could not get cal index %d!\n",
4184 __func__, cal_index);
4185 ret = -EINVAL;
4186 goto done;
4187 }
4188
4189 ret = cal_utils_dealloc_cal(data_size, data,
4190 this_adm.cal_data[cal_index]);
4191 if (ret < 0) {
4192 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
4193 __func__, ret, cal_type);
4194 ret = -EINVAL;
4195 goto done;
4196 }
4197done:
4198 return ret;
4199}
4200
4201static int adm_set_cal(int32_t cal_type, size_t data_size, void *data)
4202{
4203 int ret = 0;
4204 int cal_index;
4205
4206 pr_debug("%s:\n", __func__);
4207
4208 cal_index = get_cal_type_index(cal_type);
4209 if (cal_index < 0) {
4210 pr_err("%s: could not get cal index %d!\n",
4211 __func__, cal_index);
4212 ret = -EINVAL;
4213 goto done;
4214 }
4215
4216 ret = cal_utils_set_cal(data_size, data,
4217 this_adm.cal_data[cal_index], 0, NULL);
4218 if (ret < 0) {
4219 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
4220 __func__, ret, cal_type);
4221 ret = -EINVAL;
4222 goto done;
4223 }
4224
4225 if (cal_index == ADM_CUSTOM_TOP_CAL) {
4226 mutex_lock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
4227 this_adm.set_custom_topology = 1;
4228 mutex_unlock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
4229 } else if (cal_index == ADM_RTAC_AUDVOL_CAL) {
4230 send_rtac_audvol_cal();
4231 }
4232done:
4233 return ret;
4234}
4235
4236static int adm_map_cal_data(int32_t cal_type,
4237 struct cal_block_data *cal_block)
4238{
4239 int ret = 0;
4240 int cal_index;
4241
4242 pr_debug("%s:\n", __func__);
4243
4244 cal_index = get_cal_type_index(cal_type);
4245 if (cal_index < 0) {
4246 pr_err("%s: could not get cal index %d!\n",
4247 __func__, cal_index);
4248 ret = -EINVAL;
4249 goto done;
4250 }
4251
4252 atomic_set(&this_adm.mem_map_index, cal_index);
4253 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
4254 (uint32_t *)&cal_block->map_data.map_size, 1);
4255 if (ret < 0) {
4256 pr_err("%s: map did not work! cal_type %i ret %d\n",
4257 __func__, cal_index, ret);
4258 ret = -ENODEV;
4259 goto done;
4260 }
4261 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
4262 mem_map_handles[cal_index]);
4263done:
4264 return ret;
4265}
4266
4267static int adm_unmap_cal_data(int32_t cal_type,
4268 struct cal_block_data *cal_block)
4269{
4270 int ret = 0;
4271 int cal_index;
4272
4273 pr_debug("%s:\n", __func__);
4274
4275 cal_index = get_cal_type_index(cal_type);
4276 if (cal_index < 0) {
4277 pr_err("%s: could not get cal index %d!\n",
4278 __func__, cal_index);
4279 ret = -EINVAL;
4280 goto done;
4281 }
4282
4283 if (cal_block == NULL) {
4284 pr_err("%s: Cal block is NULL!\n",
4285 __func__);
4286 goto done;
4287 }
4288
4289 if (cal_block->map_data.q6map_handle == 0) {
4290 pr_err("%s: Map handle is NULL, nothing to unmap\n",
4291 __func__);
4292 goto done;
4293 }
4294
4295 atomic_set(&this_adm.mem_map_handles[cal_index],
4296 cal_block->map_data.q6map_handle);
4297 atomic_set(&this_adm.mem_map_index, cal_index);
4298 ret = adm_memory_unmap_regions();
4299 if (ret < 0) {
4300 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
4301 __func__, cal_index, ret);
4302 ret = -ENODEV;
4303 goto done;
4304 }
4305 cal_block->map_data.q6map_handle = 0;
4306done:
4307 return ret;
4308}
4309
4310static void adm_delete_cal_data(void)
4311{
4312 pr_debug("%s:\n", __func__);
4313
4314 cal_utils_destroy_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data);
4315}
4316
4317static int adm_init_cal_data(void)
4318{
4319 int ret = 0;
4320 struct cal_type_info cal_type_info[] = {
4321 {{ADM_CUST_TOPOLOGY_CAL_TYPE,
4322 {adm_alloc_cal, adm_dealloc_cal, NULL,
4323 adm_set_cal, NULL, NULL} },
4324 {adm_map_cal_data, adm_unmap_cal_data,
4325 cal_utils_match_buf_num} },
4326
4327 {{ADM_AUDPROC_CAL_TYPE,
4328 {adm_alloc_cal, adm_dealloc_cal, NULL,
4329 adm_set_cal, NULL, NULL} },
4330 {adm_map_cal_data, adm_unmap_cal_data,
4331 cal_utils_match_buf_num} },
4332
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304333 {{ADM_LSM_AUDPROC_CAL_TYPE,
4334 {adm_alloc_cal, adm_dealloc_cal, NULL,
4335 adm_set_cal, NULL, NULL} },
4336 {adm_map_cal_data, adm_unmap_cal_data,
4337 cal_utils_match_buf_num} },
4338
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304339 {{ADM_AUDVOL_CAL_TYPE,
4340 {adm_alloc_cal, adm_dealloc_cal, NULL,
4341 adm_set_cal, NULL, NULL} },
4342 {adm_map_cal_data, adm_unmap_cal_data,
4343 cal_utils_match_buf_num} },
4344
4345 {{ADM_RTAC_INFO_CAL_TYPE,
4346 {NULL, NULL, NULL, NULL, NULL, NULL} },
4347 {NULL, NULL, cal_utils_match_buf_num} },
4348
4349 {{ADM_RTAC_APR_CAL_TYPE,
4350 {NULL, NULL, NULL, NULL, NULL, NULL} },
4351 {NULL, NULL, cal_utils_match_buf_num} },
4352
4353 {{SRS_TRUMEDIA_CAL_TYPE,
4354 {NULL, NULL, NULL, NULL, NULL, NULL} },
4355 {NULL, NULL, cal_utils_match_buf_num} },
4356
4357 {{ADM_RTAC_AUDVOL_CAL_TYPE,
4358 {adm_alloc_cal, adm_dealloc_cal, NULL,
4359 adm_set_cal, NULL, NULL} },
4360 {adm_map_cal_data, adm_unmap_cal_data,
4361 cal_utils_match_buf_num} },
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004362
4363 {{ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE,
4364 {adm_alloc_cal, adm_dealloc_cal, NULL,
4365 adm_set_cal, NULL, NULL} },
4366 {adm_map_cal_data, adm_unmap_cal_data,
4367 cal_utils_match_buf_num} },
Ramlal Karra471fe912020-04-13 13:47:07 +05304368
4369 {{ADM_AUDPROC_PERSISTENT_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} },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304374 };
4375 pr_debug("%s:\n", __func__);
4376
4377 ret = cal_utils_create_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data,
4378 cal_type_info);
4379 if (ret < 0) {
4380 pr_err("%s: could not create cal type! ret %d\n",
4381 __func__, ret);
4382 ret = -EINVAL;
4383 goto err;
4384 }
4385
4386 return ret;
4387err:
4388 adm_delete_cal_data();
4389 return ret;
4390}
4391
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304392/**
4393 * adm_set_volume -
4394 * command to set volume on ADM copp
4395 *
4396 * @port_id: Port ID number
4397 * @copp_idx: copp index assigned
4398 * @volume: gain value to set
4399 *
4400 * Returns 0 on success or error on failure
4401 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304402int adm_set_volume(int port_id, int copp_idx, int volume)
4403{
4404 struct audproc_volume_ctrl_master_gain audproc_vol;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004405 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304406 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304407
4408 pr_debug("%s: port_id %d, volume %d\n", __func__, port_id, volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304409
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004410 memset(&audproc_vol, 0, sizeof(audproc_vol));
4411 memset(&param_hdr, 0, sizeof(param_hdr));
4412 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
4413 param_hdr.instance_id = INSTANCE_ID_0;
4414 param_hdr.param_id = AUDPROC_PARAM_ID_VOL_CTRL_MASTER_GAIN;
4415 param_hdr.param_size = sizeof(audproc_vol);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304416
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304417 audproc_vol.master_gain = volume;
4418
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004419 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4420 (uint8_t *) &audproc_vol);
4421 if (rc)
4422 pr_err("%s: Failed to set volume, err %d\n", __func__, rc);
4423
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304424 return rc;
4425}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304426EXPORT_SYMBOL(adm_set_volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304427
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304428/**
4429 * adm_set_softvolume -
4430 * command to set softvolume
4431 *
4432 * @port_id: Port ID number
4433 * @copp_idx: copp index assigned
4434 * @softvol_param: Params to set for softvolume
4435 *
4436 * Returns 0 on success or error on failure
4437 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304438int adm_set_softvolume(int port_id, int copp_idx,
4439 struct audproc_softvolume_params *softvol_param)
4440{
4441 struct audproc_soft_step_volume_params audproc_softvol;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004442 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304443 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304444
4445 pr_debug("%s: period %d step %d curve %d\n", __func__,
4446 softvol_param->period, softvol_param->step,
4447 softvol_param->rampingcurve);
4448
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004449 memset(&audproc_softvol, 0, sizeof(audproc_softvol));
4450 memset(&param_hdr, 0, sizeof(param_hdr));
4451 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
4452 param_hdr.instance_id = INSTANCE_ID_0;
4453 param_hdr.param_id = AUDPROC_PARAM_ID_SOFT_VOL_STEPPING_PARAMETERS;
4454 param_hdr.param_size = sizeof(audproc_softvol);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304455
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304456 audproc_softvol.period = softvol_param->period;
4457 audproc_softvol.step = softvol_param->step;
4458 audproc_softvol.ramping_curve = softvol_param->rampingcurve;
4459
4460 pr_debug("%s: period %d, step %d, curve %d\n", __func__,
4461 audproc_softvol.period, audproc_softvol.step,
4462 audproc_softvol.ramping_curve);
4463
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004464 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4465 (uint8_t *) &audproc_softvol);
4466 if (rc)
4467 pr_err("%s: Failed to set soft volume, err %d\n", __func__, rc);
4468
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304469 return rc;
4470}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304471EXPORT_SYMBOL(adm_set_softvolume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304472
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304473/**
4474 * adm_set_mic_gain -
4475 * command to set MIC gain
4476 *
4477 * @port_id: Port ID number
4478 * @copp_idx: copp index assigned
4479 * @volume: gain value to set
4480 *
4481 * Returns 0 on success or error on failure
4482 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304483int adm_set_mic_gain(int port_id, int copp_idx, int volume)
4484{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004485 struct admx_mic_gain mic_gain_params;
4486 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304487 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304488
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004489 pr_debug("%s: Setting mic gain to %d at port_id 0x%x\n", __func__,
4490 volume, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304491
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004492 memset(&mic_gain_params, 0, sizeof(mic_gain_params));
4493 memset(&param_hdr, 0, sizeof(param_hdr));
4494 param_hdr.module_id = ADM_MODULE_IDX_MIC_GAIN_CTRL;
4495 param_hdr.instance_id = INSTANCE_ID_0;
4496 param_hdr.param_id = ADM_PARAM_IDX_MIC_GAIN;
4497 param_hdr.param_size = sizeof(mic_gain_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304498
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004499 mic_gain_params.tx_mic_gain = volume;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304500
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004501 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4502 (uint8_t *) &mic_gain_params);
4503 if (rc)
4504 pr_err("%s: Failed to set mic gain, err %d\n", __func__, rc);
4505
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304506 return rc;
4507}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304508EXPORT_SYMBOL(adm_set_mic_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304509
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304510/**
4511 * adm_send_set_multichannel_ec_primary_mic_ch -
4512 * command to set multi-ch EC primary mic
4513 *
4514 * @port_id: Port ID number
4515 * @copp_idx: copp index assigned
4516 * @primary_mic_ch: channel number of primary mic
4517 *
4518 * Returns 0 on success or error on failure
4519 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304520int adm_send_set_multichannel_ec_primary_mic_ch(int port_id, int copp_idx,
4521 int primary_mic_ch)
4522{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004523 struct admx_sec_primary_mic_ch sec_primary_ch_params;
4524 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304525 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304526
4527 pr_debug("%s port_id 0x%x, copp_idx 0x%x, primary_mic_ch %d\n",
4528 __func__, port_id, copp_idx, primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304529
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004530 memset(&sec_primary_ch_params, 0, sizeof(sec_primary_ch_params));
4531 memset(&param_hdr, 0, sizeof(param_hdr));
4532 param_hdr.module_id = AUDPROC_MODULE_ID_VOICE_TX_SECNS;
4533 param_hdr.instance_id = INSTANCE_ID_0;
4534 param_hdr.param_id = AUDPROC_PARAM_IDX_SEC_PRIMARY_MIC_CH;
4535 param_hdr.param_size = sizeof(sec_primary_ch_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304536
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004537 sec_primary_ch_params.version = 0;
4538 sec_primary_ch_params.sec_primary_mic_ch = primary_mic_ch;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304539
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004540 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4541 (uint8_t *) &sec_primary_ch_params);
4542 if (rc)
4543 pr_err("%s: Failed to set primary mic chanel, err %d\n",
4544 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304545
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304546 return rc;
4547}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304548EXPORT_SYMBOL(adm_send_set_multichannel_ec_primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304549
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304550/**
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08004551 * adm_set_ffecns_effect -
4552 * command to set effect for ffecns module
4553 *
4554 * @effect: effect payload
4555 *
4556 * Returns 0 on success or error on failure
4557 */
4558int adm_set_ffecns_effect(int effect)
4559{
4560 struct ffecns_effect ffecns_params;
4561 struct param_hdr_v3 param_hdr;
4562 int rc = 0;
4563 int copp_idx = 0;
4564
4565 copp_idx = adm_get_default_copp_idx(this_adm.ffecns_port_id);
4566 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
4567 pr_err("%s, no active copp to query rms copp_idx:%d\n",
4568 __func__, copp_idx);
4569 return -EINVAL;
4570 }
4571
4572 memset(&ffecns_params, 0, sizeof(ffecns_params));
4573 memset(&param_hdr, 0, sizeof(param_hdr));
4574
4575 param_hdr.module_id = FFECNS_MODULE_ID;
4576 param_hdr.instance_id = INSTANCE_ID_0;
4577 param_hdr.param_id = FLUENCE_CMN_GLOBAL_EFFECT_PARAM_ID;
4578 param_hdr.param_size = sizeof(ffecns_params);
4579
4580 ffecns_params.payload = effect;
4581
4582 rc = adm_pack_and_set_one_pp_param(this_adm.ffecns_port_id, copp_idx,
4583 param_hdr, (uint8_t *) &ffecns_params);
4584 if (rc)
4585 pr_err("%s: Failed to set ffecns effect, err %d\n",
4586 __func__, rc);
4587
4588 return rc;
4589}
4590EXPORT_SYMBOL(adm_set_ffecns_effect);
4591
4592/**
Ramu Gottipati34dc3622019-12-26 10:50:00 +05304593 * adm_set_ffecns_freeze_event -
4594 * command to set event for ffecns module
4595 *
4596 * @event: send ffecns freeze event true or false
4597 *
4598 * Returns 0 on success or error on failure
4599 */
4600int adm_set_ffecns_freeze_event(bool ffecns_freeze_event)
4601{
4602 struct ffv_spf_freeze_param_t ffv_param;
4603 struct param_hdr_v3 param_hdr;
4604 int rc = 0;
4605 int copp_idx = 0;
4606
4607 memset(&param_hdr, 0, sizeof(param_hdr));
4608 memset(&ffv_param, 0, sizeof(ffv_param));
4609
4610 ffv_param.freeze = ffecns_freeze_event ? 1 : 0;
4611 ffv_param.source_id = 0; /*default value*/
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 param_hdr.module_id = FFECNS_MODULE_ID;
4621 param_hdr.instance_id = INSTANCE_ID_0;
4622 param_hdr.param_id = PARAM_ID_FFV_SPF_FREEZE;
4623 param_hdr.param_size = sizeof(ffv_param);
4624
4625 rc = adm_pack_and_set_one_pp_param(this_adm.ffecns_port_id, copp_idx,
4626 param_hdr, (uint8_t *) &ffv_param);
4627 if (rc)
4628 pr_err("%s: Failed to set ffecns imc event, err %d\n",
4629 __func__, rc);
4630
4631 return rc;
4632}
4633EXPORT_SYMBOL(adm_set_ffecns_freeze_event);
4634
4635/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304636 * adm_param_enable -
4637 * command to send params to ADM for given module
4638 *
4639 * @port_id: Port ID number
4640 * @copp_idx: copp index assigned
4641 * @module_id: ADM module
4642 * @enable: flag to enable or disable module
4643 *
4644 * Returns 0 on success or error on failure
4645 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304646int adm_param_enable(int port_id, int copp_idx, int module_id, int enable)
4647{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004648 struct module_instance_info mod_inst_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304649
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004650 memset(&mod_inst_info, 0, sizeof(mod_inst_info));
4651 mod_inst_info.module_id = module_id;
4652 mod_inst_info.instance_id = INSTANCE_ID_0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304653
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004654 return adm_param_enable_v2(port_id, copp_idx, mod_inst_info, enable);
4655}
Vidyakumar Athota98464a22018-03-15 20:39:37 -07004656EXPORT_SYMBOL(adm_param_enable);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004657
4658/**
4659 * adm_param_enable_v2 -
4660 * command to send params to ADM for given module
4661 *
4662 * @port_id: Port ID number
4663 * @copp_idx: copp index assigned
4664 * @mod_inst_info: module and instance ID info
4665 * @enable: flag to enable or disable module
4666 *
4667 * Returns 0 on success or error on failure
4668 */
4669int adm_param_enable_v2(int port_id, int copp_idx,
4670 struct module_instance_info mod_inst_info, int enable)
4671{
4672 uint32_t enable_param;
4673 struct param_hdr_v3 param_hdr;
4674 int rc = 0;
4675
4676 if (enable < 0 || enable > 1) {
4677 pr_err("%s: Invalid value for enable %d\n", __func__, enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304678 return -EINVAL;
4679 }
4680
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004681 pr_debug("%s port_id %d, module_id 0x%x, instance_id 0x%x, enable %d\n",
4682 __func__, port_id, mod_inst_info.module_id,
4683 mod_inst_info.instance_id, enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304684
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004685 memset(&param_hdr, 0, sizeof(param_hdr));
4686 param_hdr.module_id = mod_inst_info.module_id;
4687 param_hdr.instance_id = mod_inst_info.instance_id;
4688 param_hdr.param_id = AUDPROC_PARAM_ID_ENABLE;
4689 param_hdr.param_size = sizeof(enable_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304690
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004691 enable_param = enable;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304692
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004693 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4694 (uint8_t *) &enable_param);
4695 if (rc)
4696 pr_err("%s: Failed to set enable of module(%d) instance(%d) to %d, err %d\n",
4697 __func__, mod_inst_info.module_id,
4698 mod_inst_info.instance_id, enable, rc);
4699
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304700 return rc;
4701
4702}
Vidyakumar Athota98464a22018-03-15 20:39:37 -07004703EXPORT_SYMBOL(adm_param_enable_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304704
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304705/**
4706 * adm_send_calibration -
4707 * send ADM calibration to DSP
4708 *
4709 * @port_id: Port ID number
4710 * @copp_idx: copp index assigned
4711 * @path: direction or ADM path type
4712 * @perf_mode: performance mode like LL/ULL/..
4713 * @cal_type: calibration type to use
4714 * @params: pointer with cal data
4715 * @size: cal size
4716 *
4717 * Returns 0 on success or error on failure
4718 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304719int adm_send_calibration(int port_id, int copp_idx, int path, int perf_mode,
4720 int cal_type, char *params, int size)
4721{
4722
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004723 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304724
4725 pr_debug("%s:port_id %d, path %d, perf_mode %d, cal_type %d, size %d\n",
4726 __func__, port_id, path, perf_mode, cal_type, size);
4727
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304728 /* Maps audio_dev_ctrl path definition to ACDB definition */
4729 if (get_cal_path(path) != RX_DEVICE) {
4730 pr_err("%s: acdb_path %d\n", __func__, path);
4731 rc = -EINVAL;
4732 goto end;
4733 }
4734
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004735 rc = adm_set_pp_params(port_id, copp_idx, NULL, (u8 *) params, size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304736
4737end:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304738 return rc;
4739}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304740EXPORT_SYMBOL(adm_send_calibration);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304741
4742/*
4743 * adm_update_wait_parameters must be called with routing driver locks.
4744 * adm_reset_wait_parameters must be called with routing driver locks.
4745 * set and reset parmeters are separated to make sure it is always called
4746 * under routing driver lock.
4747 * adm_wait_timeout is to block until timeout or interrupted. Timeout is
4748 * not a an error.
4749 */
4750int adm_set_wait_parameters(int port_id, int copp_idx)
4751{
4752
4753 int ret = 0, port_idx;
4754
4755 pr_debug("%s: port_id 0x%x, copp_idx %d\n", __func__, port_id,
4756 copp_idx);
4757 port_id = afe_convert_virtual_to_portid(port_id);
4758 port_idx = adm_validate_and_get_port_index(port_id);
4759 if (port_idx < 0) {
4760 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4761 ret = -EINVAL;
4762 goto end;
4763 }
4764
4765 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4766 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4767 return -EINVAL;
4768 }
4769
4770 this_adm.copp.adm_delay[port_idx][copp_idx] = 1;
4771 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 0);
4772
4773end:
4774 return ret;
4775
4776}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304777EXPORT_SYMBOL(adm_set_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304778
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304779/**
4780 * adm_reset_wait_parameters -
4781 * reset wait parameters or ADM delay value
4782 *
4783 * @port_id: Port ID number
4784 * @copp_idx: copp index assigned
4785 *
4786 * Returns 0 on success or error on failure
4787 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304788int adm_reset_wait_parameters(int port_id, int copp_idx)
4789{
4790 int ret = 0, port_idx;
4791
4792 pr_debug("%s: port_id 0x%x copp_idx %d\n", __func__, port_id,
4793 copp_idx);
4794 port_id = afe_convert_virtual_to_portid(port_id);
4795 port_idx = adm_validate_and_get_port_index(port_id);
4796 if (port_idx < 0) {
4797 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4798 ret = -EINVAL;
4799 goto end;
4800 }
4801
4802 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4803 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4804 return -EINVAL;
4805 }
4806
4807 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 1);
4808 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
4809
4810end:
4811 return ret;
4812}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304813EXPORT_SYMBOL(adm_reset_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304814
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304815/**
4816 * adm_wait_timeout -
4817 * ADM wait command after command send to DSP
4818 *
4819 * @port_id: Port ID number
4820 * @copp_idx: copp index assigned
4821 * @wait_time: value in ms for command timeout
4822 *
4823 * Returns 0 on success or error on failure
4824 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304825int adm_wait_timeout(int port_id, int copp_idx, int wait_time)
4826{
4827 int ret = 0, port_idx;
4828
4829 pr_debug("%s: port_id 0x%x, copp_idx %d, wait_time %d\n", __func__,
4830 port_id, copp_idx, wait_time);
4831 port_id = afe_convert_virtual_to_portid(port_id);
4832 port_idx = adm_validate_and_get_port_index(port_id);
4833 if (port_idx < 0) {
4834 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4835 ret = -EINVAL;
4836 goto end;
4837 }
4838
4839 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4840 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4841 return -EINVAL;
4842 }
4843
4844 ret = wait_event_timeout(
4845 this_adm.copp.adm_delay_wait[port_idx][copp_idx],
4846 atomic_read(&this_adm.copp.adm_delay_stat[port_idx][copp_idx]),
4847 msecs_to_jiffies(wait_time));
4848 pr_debug("%s: return %d\n", __func__, ret);
4849 if (ret != 0)
4850 ret = -EINTR;
4851end:
4852 pr_debug("%s: return %d--\n", __func__, ret);
4853 return ret;
4854}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304855EXPORT_SYMBOL(adm_wait_timeout);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304856
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304857/**
4858 * adm_store_cal_data -
4859 * Retrieve calibration data for ADM copp device
4860 *
4861 * @port_id: Port ID number
4862 * @copp_idx: copp index assigned
4863 * @path: direction or copp type
4864 * @perf_mode: performance mode like LL/ULL/..
4865 * @cal_index: calibration index to use
4866 * @params: pointer to store cal data
4867 * @size: pointer to fill with cal size
4868 *
4869 * Returns 0 on success or error on failure
4870 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304871int adm_store_cal_data(int port_id, int copp_idx, int path, int perf_mode,
4872 int cal_index, char *params, int *size)
4873{
4874 int rc = 0;
4875 struct cal_block_data *cal_block = NULL;
4876 int app_type, acdb_id, port_idx, sample_rate;
4877
4878 if (this_adm.cal_data[cal_index] == NULL) {
4879 pr_debug("%s: cal_index %d not allocated!\n",
4880 __func__, cal_index);
4881 goto end;
4882 }
4883
4884 if (get_cal_path(path) != RX_DEVICE) {
4885 pr_debug("%s: Invalid path to store calibration %d\n",
4886 __func__, path);
4887 rc = -EINVAL;
4888 goto end;
4889 }
4890
4891 port_id = afe_convert_virtual_to_portid(port_id);
4892 port_idx = adm_validate_and_get_port_index(port_id);
4893 if (port_idx < 0) {
4894 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
4895 rc = -EINVAL;
4896 goto end;
4897 }
4898
4899 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4900 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4901 return -EINVAL;
4902 }
4903
4904 acdb_id = atomic_read(&this_adm.copp.acdb_id[port_idx][copp_idx]);
4905 app_type = atomic_read(&this_adm.copp.app_type[port_idx][copp_idx]);
4906 sample_rate = atomic_read(&this_adm.copp.rate[port_idx][copp_idx]);
4907
4908 mutex_lock(&this_adm.cal_data[cal_index]->lock);
4909 cal_block = adm_find_cal(cal_index, get_cal_path(path), app_type,
4910 acdb_id, sample_rate);
4911 if (cal_block == NULL)
4912 goto unlock;
4913
4914 if (cal_block->cal_data.size <= 0) {
4915 pr_debug("%s: No ADM cal send for port_id = 0x%x!\n",
4916 __func__, port_id);
4917 rc = -EINVAL;
4918 goto unlock;
4919 }
4920
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304921 if (cal_index == ADM_AUDPROC_CAL || cal_index == ADM_LSM_AUDPROC_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304922 if (cal_block->cal_data.size > AUD_PROC_BLOCK_SIZE) {
4923 pr_err("%s:audproc:invalid size exp/actual[%zd, %d]\n",
4924 __func__, cal_block->cal_data.size, *size);
4925 rc = -ENOMEM;
4926 goto unlock;
4927 }
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004928 } else if (cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
4929 if (cal_block->cal_data.size > AUD_PROC_PERSIST_BLOCK_SIZE) {
4930 pr_err("%s:persist invalid size exp/actual[%zd, %d]\n",
4931 __func__, cal_block->cal_data.size, *size);
4932 rc = -ENOMEM;
4933 goto unlock;
4934 }
Ramlal Karra471fe912020-04-13 13:47:07 +05304935 } else if (cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
4936 if (cal_block->cal_data.size > AUD_PROC_PERSIST_BLOCK_SIZE) {
4937 pr_err("%s:persist invalid size exp/actual[%zd, %d]\n",
4938 __func__, cal_block->cal_data.size, *size);
4939 rc = -ENOMEM;
4940 goto unlock;
4941 }
4942 }
4943 else if (cal_index == ADM_AUDVOL_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304944 if (cal_block->cal_data.size > AUD_VOL_BLOCK_SIZE) {
4945 pr_err("%s:aud_vol:invalid size exp/actual[%zd, %d]\n",
4946 __func__, cal_block->cal_data.size, *size);
4947 rc = -ENOMEM;
4948 goto unlock;
4949 }
4950 } else {
4951 pr_debug("%s: Not valid calibration for dolby topolgy\n",
4952 __func__);
4953 rc = -EINVAL;
4954 goto unlock;
4955 }
4956 memcpy(params, cal_block->cal_data.kvaddr, cal_block->cal_data.size);
4957 *size = cal_block->cal_data.size;
4958
4959 pr_debug("%s:port_id %d, copp_idx %d, path %d",
4960 __func__, port_id, copp_idx, path);
4961 pr_debug("perf_mode %d, cal_type %d, size %d\n",
4962 perf_mode, cal_index, *size);
4963
4964unlock:
4965 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
4966end:
4967 return rc;
4968}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304969EXPORT_SYMBOL(adm_store_cal_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304970
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304971/**
4972 * adm_send_compressed_device_mute -
4973 * command to send mute for compressed device
4974 *
4975 * @port_id: Port ID number
4976 * @copp_idx: copp index assigned
4977 * @mute_on: flag to indicate mute or unmute
4978 *
4979 * Returns 0 on success or error on failure
4980 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304981int adm_send_compressed_device_mute(int port_id, int copp_idx, bool mute_on)
4982{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004983 u32 mute_param = mute_on ? 1 : 0;
4984 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304985 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304986
4987 pr_debug("%s port_id: 0x%x, copp_idx %d, mute_on: %d\n",
4988 __func__, port_id, copp_idx, mute_on);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304989
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004990 memset(&param_hdr, 0, sizeof(param_hdr));
4991 param_hdr.module_id = AUDPROC_MODULE_ID_COMPRESSED_MUTE;
4992 param_hdr.instance_id = INSTANCE_ID_0;
4993 param_hdr.param_id = AUDPROC_PARAM_ID_COMPRESSED_MUTE;
4994 param_hdr.param_size = sizeof(mute_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304995
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004996 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4997 (uint8_t *) &mute_param);
4998 if (ret)
4999 pr_err("%s: Failed to set mute, err %d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305000
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305001 return ret;
5002}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305003EXPORT_SYMBOL(adm_send_compressed_device_mute);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305004
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305005/**
5006 * adm_send_compressed_device_latency -
5007 * command to send latency for compressed device
5008 *
5009 * @port_id: Port ID number
5010 * @copp_idx: copp index assigned
5011 * @latency: latency value to pass
5012 *
5013 * Returns 0 on success or error on failure
5014 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305015int adm_send_compressed_device_latency(int port_id, int copp_idx, int latency)
5016{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005017 u32 latency_param;
5018 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305019 int ret = 0;
5020
5021 pr_debug("%s port_id: 0x%x, copp_idx %d latency: %d\n", __func__,
5022 port_id, copp_idx, latency);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005023
5024 if (latency < 0) {
5025 pr_err("%s: Invalid value for latency %d", __func__, latency);
5026 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305027 }
5028
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005029 memset(&param_hdr, 0, sizeof(param_hdr));
5030 param_hdr.module_id = AUDPROC_MODULE_ID_COMPRESSED_LATENCY;
5031 param_hdr.instance_id = INSTANCE_ID_0;
5032 param_hdr.param_id = AUDPROC_PARAM_ID_COMPRESSED_LATENCY;
5033 param_hdr.param_size = sizeof(latency_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305034
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005035 latency_param = latency;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305036
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005037 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
5038 (uint8_t *) &latency_param);
5039 if (ret)
5040 pr_err("%s: Failed to set latency, err %d\n", __func__, ret);
5041
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305042 return ret;
5043}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305044EXPORT_SYMBOL(adm_send_compressed_device_latency);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305045
5046/**
5047 * adm_swap_speaker_channels
5048 *
5049 * Receives port_id, copp_idx, sample rate, spk_swap and
5050 * send MFC command to swap speaker channel.
5051 * Return zero on success. On failure returns nonzero.
5052 *
5053 * port_id - Passed value, port_id for which channels swap is wanted
5054 * copp_idx - Passed value, copp_idx for which channels swap is wanted
5055 * sample_rate - Passed value, sample rate used by app type config
5056 * spk_swap - Passed value, spk_swap for check if swap flag is set
5057 */
5058int adm_swap_speaker_channels(int port_id, int copp_idx,
5059 int sample_rate, bool spk_swap)
5060{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005061 struct audproc_mfc_param_media_fmt mfc_cfg;
5062 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305063 uint16_t num_channels;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005064 int port_idx = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305065 int ret = 0;
5066
5067 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5068 __func__, port_id, copp_idx);
5069 port_id = q6audio_convert_virtual_to_portid(port_id);
5070 port_idx = adm_validate_and_get_port_index(port_id);
5071 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
5072 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005073 return -EINVAL;
5074 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
5075 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
5076 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305077 }
5078
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005079 num_channels = atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305080 if (num_channels != 2) {
5081 pr_debug("%s: Invalid number of channels: %d\n",
5082 __func__, num_channels);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005083 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305084 }
5085
5086 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005087 memset(&param_hdr, 0, sizeof(param_hdr));
5088
5089 param_hdr.module_id = AUDPROC_MODULE_ID_MFC;
5090 param_hdr.instance_id = INSTANCE_ID_0;
5091 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
5092 param_hdr.param_size = sizeof(mfc_cfg);
5093
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305094 mfc_cfg.sampling_rate = sample_rate;
5095 mfc_cfg.bits_per_sample =
5096 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
5097 mfc_cfg.num_channels = num_channels;
5098
5099 /* Currently applying speaker swap for only 2 channel use case */
5100 if (spk_swap) {
5101 mfc_cfg.channel_type[0] =
5102 (uint16_t) PCM_CHANNEL_FR;
5103 mfc_cfg.channel_type[1] =
5104 (uint16_t) PCM_CHANNEL_FL;
5105 } else {
5106 mfc_cfg.channel_type[0] =
5107 (uint16_t) PCM_CHANNEL_FL;
5108 mfc_cfg.channel_type[1] =
5109 (uint16_t) PCM_CHANNEL_FR;
5110 }
5111
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005112 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
5113 (u8 *) &mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305114 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005115 pr_err("%s: Failed to set swap speaker channels on port[0x%x] failed %d\n",
5116 __func__, port_id, ret);
5117 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305118 }
5119
5120 pr_debug("%s: mfc_cfg Set params returned success", __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005121 return 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305122}
5123EXPORT_SYMBOL(adm_swap_speaker_channels);
5124
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305125/**
5126 * adm_set_sound_focus -
5127 * Update sound focus info
5128 *
5129 * @port_id: Port ID number
5130 * @copp_idx: copp index assigned
5131 * @soundFocusData: sound focus data to pass
5132 *
5133 * Returns 0 on success or error on failure
5134 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305135int adm_set_sound_focus(int port_id, int copp_idx,
5136 struct sound_focus_param soundFocusData)
5137{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005138 struct adm_param_fluence_soundfocus_t soundfocus_params;
5139 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305140 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305141 int i;
5142
5143 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5144 __func__, port_id, copp_idx);
5145
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005146 memset(&param_hdr, 0, sizeof(param_hdr));
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005147 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005148 param_hdr.instance_id = INSTANCE_ID_0;
5149 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
5150 param_hdr.param_size = sizeof(soundfocus_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305151
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005152 memset(&(soundfocus_params), 0xFF, sizeof(soundfocus_params));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305153 for (i = 0; i < MAX_SECTORS; i++) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005154 soundfocus_params.start_angles[i] =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305155 soundFocusData.start_angle[i];
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005156 soundfocus_params.enables[i] = soundFocusData.enable[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305157 pr_debug("%s: start_angle[%d] = %d\n",
5158 __func__, i, soundFocusData.start_angle[i]);
5159 pr_debug("%s: enable[%d] = %d\n",
5160 __func__, i, soundFocusData.enable[i]);
5161 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005162 soundfocus_params.gain_step = soundFocusData.gain_step;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305163 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData.gain_step);
5164
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005165 soundfocus_params.reserved = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305166
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005167 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
5168 (uint8_t *) &soundfocus_params);
5169 if (ret)
5170 pr_err("%s: Failed to set sound focus params, err %d\n",
5171 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305172
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305173 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
5174
5175 return ret;
5176}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305177EXPORT_SYMBOL(adm_set_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305178
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305179/**
5180 * adm_get_sound_focus -
5181 * Retrieve sound focus info
5182 *
5183 * @port_id: Port ID number
5184 * @copp_idx: copp index assigned
5185 * @soundFocusData: pointer for sound focus data to be updated with
5186 *
5187 * Returns 0 on success or error on failure
5188 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305189int adm_get_sound_focus(int port_id, int copp_idx,
5190 struct sound_focus_param *soundFocusData)
5191{
5192 int ret = 0, i;
5193 char *params_value;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005194 uint32_t max_param_size = 0;
5195 struct adm_param_fluence_soundfocus_t *soundfocus_params = NULL;
5196 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305197
5198 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5199 __func__, port_id, copp_idx);
5200
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005201 max_param_size = sizeof(struct adm_param_fluence_soundfocus_t) +
5202 sizeof(union param_hdrs);
5203 params_value = kzalloc(max_param_size, GFP_KERNEL);
5204 if (!params_value)
5205 return -ENOMEM;
5206
5207 memset(&param_hdr, 0, sizeof(param_hdr));
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005208 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005209 param_hdr.instance_id = INSTANCE_ID_0;
5210 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
5211 param_hdr.param_size = max_param_size;
5212 ret = adm_get_pp_params(port_id, copp_idx,
5213 ADM_CLIENT_ID_SOURCE_TRACKING, NULL, &param_hdr,
5214 params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305215 if (ret) {
5216 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305217 ret = -EINVAL;
5218 goto done;
5219 }
5220
5221 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
5222 pr_err("%s - get params returned error [%s]\n",
5223 __func__, adsp_err_get_err_str(
5224 this_adm.sourceTrackingData.apr_cmd_status));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305225 ret = adsp_err_get_lnx_err_code(
5226 this_adm.sourceTrackingData.apr_cmd_status);
5227 goto done;
5228 }
5229
5230 soundfocus_params = (struct adm_param_fluence_soundfocus_t *)
5231 params_value;
5232 for (i = 0; i < MAX_SECTORS; i++) {
5233 soundFocusData->start_angle[i] =
5234 soundfocus_params->start_angles[i];
5235 soundFocusData->enable[i] = soundfocus_params->enables[i];
5236 pr_debug("%s: start_angle[%d] = %d\n",
5237 __func__, i, soundFocusData->start_angle[i]);
5238 pr_debug("%s: enable[%d] = %d\n",
5239 __func__, i, soundFocusData->enable[i]);
5240 }
5241 soundFocusData->gain_step = soundfocus_params->gain_step;
5242 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData->gain_step);
5243
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305244done:
5245 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5246
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005247 kfree(params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305248 return ret;
5249}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305250EXPORT_SYMBOL(adm_get_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305251
5252static int adm_source_tracking_alloc_map_memory(void)
5253{
5254 int ret;
5255
5256 pr_debug("%s: Enter\n", __func__);
5257
Banajit Goswami08bb7362017-11-03 22:48:23 -07005258 ret = msm_audio_ion_alloc(&this_adm.sourceTrackingData.dma_buf,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305259 AUD_PROC_BLOCK_SIZE,
5260 &this_adm.sourceTrackingData.memmap.paddr,
5261 &this_adm.sourceTrackingData.memmap.size,
5262 &this_adm.sourceTrackingData.memmap.kvaddr);
5263 if (ret) {
5264 pr_err("%s: failed to allocate memory\n", __func__);
5265
5266 ret = -EINVAL;
5267 goto done;
5268 }
5269
5270 atomic_set(&this_adm.mem_map_index, ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
5271 ret = adm_memory_map_regions(&this_adm.sourceTrackingData.memmap.paddr,
5272 0,
5273 (uint32_t *)&this_adm.sourceTrackingData.memmap.size,
5274 1);
5275 if (ret < 0) {
5276 pr_err("%s: failed to map memory, paddr = 0x%pK, size = %d\n",
5277 __func__,
5278 (void *)this_adm.sourceTrackingData.memmap.paddr,
5279 (uint32_t)this_adm.sourceTrackingData.memmap.size);
5280
Banajit Goswami08bb7362017-11-03 22:48:23 -07005281 msm_audio_ion_free(this_adm.sourceTrackingData.dma_buf);
5282 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305283 this_adm.sourceTrackingData.memmap.size = 0;
5284 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5285 this_adm.sourceTrackingData.memmap.paddr = 0;
5286 this_adm.sourceTrackingData.apr_cmd_status = -1;
5287 atomic_set(&this_adm.mem_map_handles
5288 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
5289
5290 ret = -EINVAL;
5291 goto done;
5292 }
5293 ret = 0;
5294 pr_debug("%s: paddr = 0x%pK, size = %d, mem_map_handle = 0x%x\n",
5295 __func__, (void *)this_adm.sourceTrackingData.memmap.paddr,
5296 (uint32_t)this_adm.sourceTrackingData.memmap.size,
5297 atomic_read(&this_adm.mem_map_handles
5298 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING]));
5299
5300done:
5301 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5302
5303 return ret;
5304}
5305
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305306/**
5307 * adm_get_source_tracking -
5308 * Retrieve source tracking info
5309 *
5310 * @port_id: Port ID number
5311 * @copp_idx: copp index assigned
5312 * @sourceTrackingData: pointer for source track data to be updated with
5313 *
5314 * Returns 0 on success or error on failure
5315 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305316int adm_get_source_tracking(int port_id, int copp_idx,
5317 struct source_tracking_param *sourceTrackingData)
5318{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005319 struct adm_param_fluence_sourcetracking_t *source_tracking_params =
5320 NULL;
5321 struct mem_mapping_hdr mem_hdr;
5322 struct param_hdr_v3 param_hdr;
5323 int i = 0;
5324 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305325
5326 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5327 __func__, port_id, copp_idx);
5328
5329 if (!this_adm.sourceTrackingData.memmap.paddr) {
5330 /* Allocate and map shared memory for out of band usage */
5331 ret = adm_source_tracking_alloc_map_memory();
5332 if (ret != 0) {
5333 ret = -EINVAL;
5334 goto done;
5335 }
5336 }
5337
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005338 memset(&mem_hdr, 0, sizeof(mem_hdr));
5339 memset(&param_hdr, 0, sizeof(param_hdr));
5340 mem_hdr.data_payload_addr_lsw =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305341 lower_32_bits(this_adm.sourceTrackingData.memmap.paddr);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005342 mem_hdr.data_payload_addr_msw = msm_audio_populate_upper_32_bits(
5343 this_adm.sourceTrackingData.memmap.paddr);
5344 mem_hdr.mem_map_handle = atomic_read(
5345 &this_adm.mem_map_handles[ADM_MEM_MAP_INDEX_SOURCE_TRACKING]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305346
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005347 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005348 param_hdr.instance_id = INSTANCE_ID_0;
5349 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOURCETRACKING;
5350 /*
5351 * This size should be the max size of the calibration data + header.
5352 * Use the union size to ensure max size is used.
5353 */
5354 param_hdr.param_size =
5355 sizeof(struct adm_param_fluence_sourcetracking_t) +
Avinash Chandra13d9c562020-04-27 19:23:49 +05305356 sizeof(struct param_hdr_v3);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305357
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005358 /*
5359 * Retrieving parameters out of band, so no need to provide a buffer for
5360 * the returned parameter data as it will be at the memory location
5361 * provided.
5362 */
5363 ret = adm_get_pp_params(port_id, copp_idx,
5364 ADM_CLIENT_ID_SOURCE_TRACKING, &mem_hdr,
5365 &param_hdr, NULL);
5366 if (ret) {
5367 pr_err("%s: Failed to get params, error %d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305368 goto done;
5369 }
5370
5371 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
5372 pr_err("%s - get params returned error [%s]\n",
5373 __func__, adsp_err_get_err_str(
5374 this_adm.sourceTrackingData.apr_cmd_status));
5375
5376 ret = adsp_err_get_lnx_err_code(
5377 this_adm.sourceTrackingData.apr_cmd_status);
5378 goto done;
5379 }
5380
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005381 /* How do we know what the param data was retrieved with for hdr size */
5382 source_tracking_params =
5383 (struct adm_param_fluence_sourcetracking_t
5384 *) (this_adm.sourceTrackingData.memmap.kvaddr +
Avinash Chandra13d9c562020-04-27 19:23:49 +05305385 sizeof(struct param_hdr_v3));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305386 for (i = 0; i < MAX_SECTORS; i++) {
5387 sourceTrackingData->vad[i] = source_tracking_params->vad[i];
5388 pr_debug("%s: vad[%d] = %d\n",
5389 __func__, i, sourceTrackingData->vad[i]);
5390 }
5391 sourceTrackingData->doa_speech = source_tracking_params->doa_speech;
5392 pr_debug("%s: doa_speech = %d\n",
5393 __func__, sourceTrackingData->doa_speech);
5394
5395 for (i = 0; i < MAX_NOISE_SOURCE_INDICATORS; i++) {
5396 sourceTrackingData->doa_noise[i] =
5397 source_tracking_params->doa_noise[i];
5398 pr_debug("%s: doa_noise[%d] = %d\n",
5399 __func__, i, sourceTrackingData->doa_noise[i]);
5400 }
5401 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
5402 sourceTrackingData->polar_activity[i] =
5403 source_tracking_params->polar_activity[i];
5404 pr_debug("%s: polar_activity[%d] = %d\n",
5405 __func__, i, sourceTrackingData->polar_activity[i]);
5406 }
5407
5408 ret = 0;
5409
5410done:
5411 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
5412
5413 return ret;
5414}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305415EXPORT_SYMBOL(adm_get_source_tracking);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305416
Chaithanya Krishna Bacharaju8c6a1842018-11-16 15:02:39 +05305417/**
5418 * adm_get_doa_tracking_mon -
5419 * Retrieve doa tracking monitor info
5420 *
5421 * @port_id: Port ID number
5422 * @copp_idx: copp index assigned
5423 * @doa_tracking_data: pointer for doa data to be updated with
5424 *
5425 * Returns 0 on success or error on failure
5426 */
5427int adm_get_doa_tracking_mon(int port_id, int copp_idx,
5428 struct doa_tracking_mon_param *doa_tracking_data)
5429{
5430 int ret = 0, i;
5431 char *params_value;
5432 uint32_t max_param_size = 0;
5433 struct adm_param_doa_tracking_mon_t *doa_tracking_params = NULL;
5434 struct param_hdr_v3 param_hdr;
5435
5436 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5437 __func__, port_id, copp_idx);
5438
5439 if (doa_tracking_data == NULL) {
5440 pr_err("%s: Received NULL pointer for doa tracking data\n",
5441 __func__);
5442 return -EINVAL;
5443 }
5444
5445 max_param_size = sizeof(struct adm_param_doa_tracking_mon_t) +
5446 sizeof(union param_hdrs);
5447 params_value = kzalloc(max_param_size, GFP_KERNEL);
5448 if (!params_value)
5449 return -ENOMEM;
5450
5451 memset(&param_hdr, 0, sizeof(param_hdr));
5452 param_hdr.module_id = AUDPROC_MODULE_ID_FFECNS;
5453 param_hdr.instance_id = INSTANCE_ID_0;
5454 param_hdr.param_id = AUDPROC_PARAM_ID_FFV_DOA_TRACKING_MONITOR;
5455 param_hdr.param_size = max_param_size;
5456 ret = adm_get_pp_params(port_id, copp_idx,
5457 ADM_CLIENT_ID_DEFAULT, NULL, &param_hdr,
5458 params_value);
5459 if (ret) {
5460 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
5461 goto done;
5462 }
5463
5464 doa_tracking_params =
5465 (struct adm_param_doa_tracking_mon_t *)params_value;
5466 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
5467 doa_tracking_data->target_angle_L16[i] =
5468 doa_tracking_params->target_angle_L16[i];
5469 pr_debug("%s: target angle[%d] = %d\n",
5470 __func__, i, doa_tracking_data->target_angle_L16[i]);
5471 }
5472
5473 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
5474 doa_tracking_data->interf_angle_L16[i] =
5475 doa_tracking_params->interf_angle_L16[i];
5476 pr_debug("%s: interference angle[%d] = %d\n",
5477 __func__, i, doa_tracking_data->interf_angle_L16[i]);
5478 }
5479
5480 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
5481 doa_tracking_data->polar_activity[i] =
5482 doa_tracking_params->polar_activity[i];
5483 }
5484
5485done:
5486 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5487 kfree(params_value);
5488 return ret;
5489}
5490EXPORT_SYMBOL(adm_get_doa_tracking_mon);
5491
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305492int __init adm_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305493{
5494 int i = 0, j;
5495
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305496 this_adm.ec_ref_rx = -1;
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08005497 this_adm.ffecns_port_id = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305498 init_waitqueue_head(&this_adm.matrix_map_wait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305499 init_waitqueue_head(&this_adm.adm_wait);
Soumya Managoli97f90ea2020-04-28 09:16:55 +05305500 mutex_init(&this_adm.adm_apr_lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305501
5502 for (i = 0; i < AFE_MAX_PORTS; i++) {
5503 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
5504 atomic_set(&this_adm.copp.id[i][j], RESET_COPP_ID);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305505 init_waitqueue_head(&this_adm.copp.wait[i][j]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305506 init_waitqueue_head(
5507 &this_adm.copp.adm_delay_wait[i][j]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305508 }
5509 }
5510
5511 if (adm_init_cal_data())
5512 pr_err("%s: could not init cal data!\n", __func__);
5513
Banajit Goswami08bb7362017-11-03 22:48:23 -07005514 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305515 this_adm.sourceTrackingData.memmap.size = 0;
5516 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5517 this_adm.sourceTrackingData.memmap.paddr = 0;
5518 this_adm.sourceTrackingData.apr_cmd_status = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305519
5520 return 0;
5521}
5522
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05305523void adm_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305524{
Soumya Managoli97f90ea2020-04-28 09:16:55 +05305525 mutex_destroy(&this_adm.adm_apr_lock);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05305526 if (this_adm.apr)
5527 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305528 adm_delete_cal_data();
5529}