blob: 9a4a7f914a350f5285069986fed649ab3b4e29f8 [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
98 int set_custom_topology;
99 int ec_ref_rx;
100 int num_ec_ref_rx_chans;
101 int ec_ref_rx_bit_width;
102 int ec_ref_rx_sampling_rate;
Dhananjay Kumar43034392019-01-16 21:57:58 +0530103 int num_ec_ref_rx_chans_downmixed;
104 uint16_t ec_ref_chmixer_weights[PCM_FORMAT_MAX_NUM_CHANNEL_V8]
105 [PCM_FORMAT_MAX_NUM_CHANNEL_V8];
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +0800106 int ffecns_port_id;
Dieter Luecking50c55352018-09-28 14:29:17 +0200107 int native_mode;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530108};
109
110static struct adm_ctl this_adm;
111
112struct adm_multi_ch_map {
113 bool set_channel_map;
Dieter Luecking50c55352018-09-28 14:29:17 +0200114 char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530115};
116
117#define ADM_MCH_MAP_IDX_PLAYBACK 0
118#define ADM_MCH_MAP_IDX_REC 1
119static struct adm_multi_ch_map multi_ch_maps[2] = {
Dieter Luecking50c55352018-09-28 14:29:17 +0200120 { false,
121 {0, 0, 0, 0, 0, 0, 0, 0,
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 },
126 { false,
127 {0, 0, 0, 0, 0, 0, 0, 0,
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 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530132};
133
Rohit kumar2054b692019-02-01 18:01:12 +0530134static struct adm_multi_ch_map port_channel_map[AFE_MAX_PORTS];
135
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530136static int adm_get_parameters[MAX_COPPS_PER_PORT * ADM_GET_PARAMETER_LENGTH];
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800137static int adm_module_topo_list[MAX_COPPS_PER_PORT *
138 ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH];
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530139static struct mutex dts_srs_lock;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530140
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530141void msm_dts_srs_acquire_lock(void)
142{
143 mutex_lock(&dts_srs_lock);
144}
145
146void msm_dts_srs_release_lock(void)
147{
148 mutex_unlock(&dts_srs_lock);
149}
150
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530151static int adm_arrange_mch_map_v8(
152 struct adm_device_endpoint_payload *ep_payload,
153 int path,
Rohit kumar2054b692019-02-01 18:01:12 +0530154 int channel_mode,
155 int port_idx);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530156
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530157/**
158 * adm_validate_and_get_port_index -
159 * validate given port id
160 *
161 * @port_id: Port ID number
162 *
163 * Returns valid index on success or error on failure
164 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530165int adm_validate_and_get_port_index(int port_id)
166{
167 int index;
168 int ret;
169
170 ret = q6audio_validate_port(port_id);
171 if (ret < 0) {
172 pr_err("%s: port validation failed id 0x%x ret %d\n",
173 __func__, port_id, ret);
174 return -EINVAL;
175 }
176
177 index = afe_get_port_index(port_id);
178 if (index < 0 || index >= AFE_MAX_PORTS) {
179 pr_err("%s: Invalid port idx %d port_id 0x%x\n",
180 __func__, index,
181 port_id);
182 return -EINVAL;
183 }
184 pr_debug("%s: port_idx- %d\n", __func__, index);
185 return index;
186}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530187EXPORT_SYMBOL(adm_validate_and_get_port_index);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530188
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530189/**
190 * adm_get_default_copp_idx -
191 * retrieve default copp_idx for given port
192 *
193 * @port_id: Port ID number
194 *
195 * Returns valid value on success or error on failure
196 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530197int adm_get_default_copp_idx(int port_id)
198{
199 int port_idx = adm_validate_and_get_port_index(port_id), idx;
200
201 if (port_idx < 0) {
202 pr_err("%s: Invalid port id: 0x%x", __func__, port_id);
203 return -EINVAL;
204 }
205 pr_debug("%s: port_idx:%d\n", __func__, port_idx);
206 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
207 if (atomic_read(&this_adm.copp.id[port_idx][idx]) !=
208 RESET_COPP_ID)
209 return idx;
210 }
211 return -EINVAL;
212}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530213EXPORT_SYMBOL(adm_get_default_copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530214
215int adm_get_topology_for_port_from_copp_id(int port_id, int copp_id)
216{
217 int port_idx = adm_validate_and_get_port_index(port_id), idx;
218
219 if (port_idx < 0) {
220 pr_err("%s: Invalid port id: 0x%x", __func__, port_id);
221 return 0;
222 }
223 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
224 if (atomic_read(&this_adm.copp.id[port_idx][idx]) == copp_id)
225 return atomic_read(&this_adm.copp.topology[port_idx]
226 [idx]);
227 pr_err("%s: Invalid copp_id %d port_id 0x%x\n",
228 __func__, copp_id, port_id);
229 return 0;
230}
231
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530232/**
233 * adm_get_topology_for_port_copp_idx -
234 * retrieve topology of given port/copp_idx
235 *
236 * @port_id: Port ID number
237 * @copp_idx: copp index of ADM copp
238 *
239 * Returns valid value on success or 0 on failure
240 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530241int adm_get_topology_for_port_copp_idx(int port_id, int copp_idx)
242{
243 int port_idx = adm_validate_and_get_port_index(port_id);
244
245 if (port_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
246 pr_err("%s: Invalid port: 0x%x copp id: 0x%x",
247 __func__, port_id, copp_idx);
248 return 0;
249 }
250 return atomic_read(&this_adm.copp.topology[port_idx][copp_idx]);
251}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530252EXPORT_SYMBOL(adm_get_topology_for_port_copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530253
254int adm_get_indexes_from_copp_id(int copp_id, int *copp_idx, int *port_idx)
255{
256 int p_idx, c_idx;
257
258 for (p_idx = 0; p_idx < AFE_MAX_PORTS; p_idx++) {
259 for (c_idx = 0; c_idx < MAX_COPPS_PER_PORT; c_idx++) {
260 if (atomic_read(&this_adm.copp.id[p_idx][c_idx])
261 == copp_id) {
262 if (copp_idx != NULL)
263 *copp_idx = c_idx;
264 if (port_idx != NULL)
265 *port_idx = p_idx;
266 return 0;
267 }
268 }
269 }
270 return -EINVAL;
271}
272
273static int adm_get_copp_id(int port_idx, int copp_idx)
274{
275 pr_debug("%s: port_idx:%d copp_idx:%d\n", __func__, port_idx, copp_idx);
276
277 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
278 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
279 return -EINVAL;
280 }
281 return atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
282}
283
284static int adm_get_idx_if_copp_exists(int port_idx, int topology, int mode,
Surendar Karkae7507512018-07-20 15:46:54 +0530285 int rate, int bit_width, int app_type,
286 int session_type)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530287{
288 int idx;
289
290 pr_debug("%s: port_idx-%d, topology-0x%x, mode-%d, rate-%d, bit_width-%d\n",
291 __func__, port_idx, topology, mode, rate, bit_width);
292
293 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
294 if ((topology ==
295 atomic_read(&this_adm.copp.topology[port_idx][idx])) &&
296 (mode == atomic_read(&this_adm.copp.mode[port_idx][idx])) &&
297 (rate == atomic_read(&this_adm.copp.rate[port_idx][idx])) &&
298 (bit_width ==
299 atomic_read(&this_adm.copp.bit_width[port_idx][idx])) &&
Surendar Karkae7507512018-07-20 15:46:54 +0530300 (session_type ==
301 atomic_read(
302 &this_adm.copp.session_type[port_idx][idx])) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530303 (app_type ==
304 atomic_read(&this_adm.copp.app_type[port_idx][idx])))
305 return idx;
306 return -EINVAL;
307}
308
309static int adm_get_next_available_copp(int port_idx)
310{
311 int idx;
312
313 pr_debug("%s:\n", __func__);
314 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
315 pr_debug("%s: copp_id:0x%x port_idx:%d idx:%d\n", __func__,
316 atomic_read(&this_adm.copp.id[port_idx][idx]),
317 port_idx, idx);
318 if (atomic_read(&this_adm.copp.id[port_idx][idx]) ==
319 RESET_COPP_ID)
320 break;
321 }
322 return idx;
323}
324
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530325/**
326 * srs_trumedia_open -
327 * command to set SRS trumedia open
328 *
329 * @port_id: Port ID number
330 * @copp_idx: copp index of ADM copp
331 * @srs_tech_id: SRS tech index
332 * @srs_params: params pointer
333 *
334 * Returns 0 on success or error on failure
335 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530336int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id,
337 void *srs_params)
338{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800339 struct param_hdr_v3 param_hdr;
340 struct mem_mapping_hdr mem_hdr;
341 u32 total_param_size = 0;
342 bool outband = false;
343 int port_idx;
344 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530345
346 pr_debug("SRS - %s", __func__);
347
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800348 memset(&param_hdr, 0, sizeof(param_hdr));
349 memset(&mem_hdr, 0, sizeof(mem_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530350 port_id = afe_convert_virtual_to_portid(port_id);
351 port_idx = adm_validate_and_get_port_index(port_id);
352 if (port_idx < 0) {
353 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
354 return -EINVAL;
355 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800356
357 param_hdr.module_id = SRS_TRUMEDIA_MODULE_ID;
358 param_hdr.instance_id = INSTANCE_ID_0;
359
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530360 switch (srs_tech_id) {
361 case SRS_ID_GLOBAL: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800362 param_hdr.param_id = SRS_TRUMEDIA_PARAMS;
363 param_hdr.param_size =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530364 sizeof(struct srs_trumedia_params_GLOBAL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530365 break;
366 }
367 case SRS_ID_WOWHD: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800368 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_WOWHD;
369 param_hdr.param_size = sizeof(struct srs_trumedia_params_WOWHD);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530370 break;
371 }
372 case SRS_ID_CSHP: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800373 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_CSHP;
374 param_hdr.param_size = sizeof(struct srs_trumedia_params_CSHP);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530375 break;
376 }
377 case SRS_ID_HPF: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800378 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_HPF;
379 param_hdr.param_size = sizeof(struct srs_trumedia_params_HPF);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530380 break;
381 }
382 case SRS_ID_AEQ: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800383 u8 *update_params_ptr = (u8 *) this_adm.outband_memmap.kvaddr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530384
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800385 outband = true;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530386
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530387 if (update_params_ptr == NULL) {
388 pr_err("ADM_SRS_TRUMEDIA - %s: null memmap for AEQ params\n",
389 __func__);
390 ret = -EINVAL;
391 goto fail_cmd;
392 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530393
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800394 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_AEQ;
395 param_hdr.param_size = sizeof(struct srs_trumedia_params_AEQ);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530396
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800397 ret = q6common_pack_pp_params(update_params_ptr, &param_hdr,
398 srs_params, &total_param_size);
399 if (ret) {
400 pr_err("%s: Failed to pack param header and data, error %d\n",
401 __func__, ret);
402 goto fail_cmd;
403 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530404 break;
405 }
406 case SRS_ID_HL: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800407 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_HL;
408 param_hdr.param_size = sizeof(struct srs_trumedia_params_HL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530409 break;
410 }
411 case SRS_ID_GEQ: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800412 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_GEQ;
413 param_hdr.param_size = sizeof(struct srs_trumedia_params_GEQ);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530414 break;
415 }
416 default:
417 goto fail_cmd;
418 }
419
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530420 if (outband && this_adm.outband_memmap.paddr) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800421 mem_hdr.data_payload_addr_lsw =
422 lower_32_bits(this_adm.outband_memmap.paddr);
423 mem_hdr.data_payload_addr_msw =
424 msm_audio_populate_upper_32_bits(
425 this_adm.outband_memmap.paddr);
426 mem_hdr.mem_map_handle = atomic_read(
427 &this_adm.mem_map_handles[ADM_SRS_TRUMEDIA]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530428
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800429 ret = adm_set_pp_params(port_id, copp_idx, &mem_hdr, NULL,
430 total_param_size);
431 } else {
432 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx,
433 param_hdr,
434 (u8 *) srs_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530435 }
436
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800437 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530438 pr_err("SRS - %s: ADM enable for port %d failed\n", __func__,
439 port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530440
441fail_cmd:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530442 return ret;
443}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530444EXPORT_SYMBOL(srs_trumedia_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530445
446static int adm_populate_channel_weight(u16 *ptr,
447 struct msm_pcm_channel_mixer *ch_mixer,
448 int channel_index)
449{
450 u16 i, j, start_index = 0;
451
452 if (channel_index > ch_mixer->output_channel) {
453 pr_err("%s: channel index %d is larger than output_channel %d\n",
454 __func__, channel_index, ch_mixer->output_channel);
455 return -EINVAL;
456 }
457
458 for (i = 0; i < ch_mixer->output_channel; i++) {
459 pr_debug("%s: weight for output %d:", __func__, i);
460 for (j = 0; j < ADM_MAX_CHANNELS; j++)
461 pr_debug(" %d",
462 ch_mixer->channel_weight[i][j]);
463 pr_debug("\n");
464 }
465
466 for (i = 0; i < channel_index; ++i)
467 start_index += ch_mixer->input_channels[i];
468
469 for (i = 0; i < ch_mixer->output_channel; ++i) {
470 for (j = start_index;
471 j < start_index +
472 ch_mixer->input_channels[channel_index]; j++) {
473 *ptr = ch_mixer->channel_weight[i][j];
474 pr_debug("%s: ptr[%d][%d] = %d\n",
475 __func__, i, j, *ptr);
476 ptr++;
477 }
478 }
479
480 return 0;
481}
482
483/*
484 * adm_programable_channel_mixer
485 *
486 * Receives port_id, copp_idx, session_id, session_type, ch_mixer
487 * and channel_index to send ADM command to mix COPP data.
488 *
489 * port_id - Passed value, port_id for which backend is wanted
490 * copp_idx - Passed value, copp_idx for which COPP is wanted
491 * session_id - Passed value, session_id for which session is needed
492 * session_type - Passed value, session_type for RX or TX
493 * ch_mixer - Passed value, ch_mixer for which channel mixer config is needed
494 * channel_index - Passed value, channel_index for which channel is needed
495 */
496int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
497 int session_type,
498 struct msm_pcm_channel_mixer *ch_mixer,
499 int channel_index)
500{
501 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700502 struct param_hdr_v1 data_v5;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530503 int ret = 0, port_idx, sz = 0, param_size = 0;
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530504 struct adm_device_endpoint_payload ep_params = {0, 0, 0, {0}};
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530505 u16 *adm_pspd_params;
506 u16 *ptr;
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530507 int index = 0, i = 0, path_type = ADM_PATH_PLAYBACK;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530508
509 pr_debug("%s: port_id = %d\n", __func__, port_id);
510 port_id = afe_convert_virtual_to_portid(port_id);
511 port_idx = adm_validate_and_get_port_index(port_id);
512 if (port_idx < 0) {
513 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
514 return -EINVAL;
515 }
Ramu Gottipatife399492020-01-09 10:57:33 +0530516
517 /*
518 * check if PSPD is already configured
519 * if it is configured already, return 0 without applying PSPD.
520 */
521 if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) > 1) {
522 pr_debug("%s: copp.cnt:%#x\n", __func__,
523 atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]));
524 return 0;
525 }
526
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530527 /*
528 * First 8 bytes are 4 bytes as rule number, 2 bytes as output
529 * channel and 2 bytes as input channel.
530 * 2 * ch_mixer->output_channel means output channel mapping.
531 * 2 * ch_mixer->input_channels[channel_index]) means input
532 * channel mapping.
533 * 2 * ch_mixer->input_channels[channel_index] *
534 * ch_mixer->output_channel) means the channel mixer weighting
535 * coefficients.
536 * param_size needs to be a multiple of 4 bytes.
537 */
538
539 param_size = 2 * (4 + ch_mixer->output_channel +
540 ch_mixer->input_channels[channel_index] +
541 ch_mixer->input_channels[channel_index] *
542 ch_mixer->output_channel);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530543 param_size = roundup(param_size, 4);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530544
545 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800546 sizeof(struct default_chmixer_param_id_coeff) +
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700547 sizeof(struct param_hdr_v1) + param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530548 pr_debug("%s: sz = %d\n", __func__, sz);
549 adm_params = kzalloc(sz, GFP_KERNEL);
550 if (!adm_params)
551 return -ENOMEM;
552
553 adm_params->payload_addr_lsw = 0;
554 adm_params->payload_addr_msw = 0;
555 adm_params->mem_map_handle = 0;
556 adm_params->direction = session_type;
557 adm_params->sessionid = session_id;
558 pr_debug("%s: copp_id = %d, session id %d\n", __func__,
559 atomic_read(&this_adm.copp.id[port_idx][copp_idx]),
560 session_id);
561 adm_params->deviceid = atomic_read(
562 &this_adm.copp.id[port_idx][copp_idx]);
563 adm_params->reserved = 0;
564
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800565 /*
566 * This module is internal to ADSP and cannot be configured with
567 * an instance id
568 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530569 data_v5.module_id = MTMX_MODULE_ID_DEFAULT_CHMIXER;
570 data_v5.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
571 data_v5.reserved = 0;
572 data_v5.param_size = param_size;
573 adm_params->payload_size =
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800574 sizeof(struct default_chmixer_param_id_coeff) +
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700575 sizeof(struct param_hdr_v1) + data_v5.param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530576 adm_pspd_params = (u16 *)((u8 *)adm_params +
577 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5));
578 memcpy(adm_pspd_params, &data_v5, sizeof(data_v5));
579
580 adm_pspd_params = (u16 *)((u8 *)adm_params +
581 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)
582 + sizeof(data_v5));
583
584 adm_pspd_params[0] = ch_mixer->rule;
585 adm_pspd_params[2] = ch_mixer->output_channel;
586 adm_pspd_params[3] = ch_mixer->input_channels[channel_index];
587 index = 4;
588
Chaithanya Krishna Bacharaju6bd40882019-07-16 11:07:14 +0530589 path_type = (session_type == SESSION_TYPE_RX) ?
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530590 ADM_PATH_PLAYBACK : ADM_PATH_LIVE_REC;
591
592 if (ch_mixer->override_out_ch_map) {
593 memcpy(&adm_pspd_params[index], &ch_mixer->out_ch_map,
594 ch_mixer->output_channel * sizeof(uint16_t));
595 index += ch_mixer->output_channel;
596 } else {
597 ep_params.dev_num_channel = ch_mixer->output_channel;
Rohit kumar2054b692019-02-01 18:01:12 +0530598 adm_arrange_mch_map_v8(&ep_params, path_type,
599 ep_params.dev_num_channel, port_idx);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530600 for (i = 0; i < ch_mixer->output_channel; i++)
601 adm_pspd_params[index++] = ep_params.dev_channel_mapping[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530602 }
603
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530604 if (ch_mixer->override_in_ch_map) {
605 memcpy(&adm_pspd_params[index], &ch_mixer->in_ch_map,
606 ch_mixer->input_channel * sizeof(uint16_t));
607 index += ch_mixer->input_channel;
608 } else {
609 ep_params.dev_num_channel = ch_mixer->input_channels[channel_index];
Rohit kumar2054b692019-02-01 18:01:12 +0530610 adm_arrange_mch_map_v8(&ep_params, path_type,
611 ep_params.dev_num_channel, port_idx);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530612 for (i = 0; i < ch_mixer->input_channels[channel_index]; i++)
613 adm_pspd_params[index++] = ep_params.dev_channel_mapping[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530614 }
615
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530616 ret = adm_populate_channel_weight(&adm_pspd_params[index],
617 ch_mixer, channel_index);
Meng Wangd9fa69c2018-01-23 12:42:52 +0800618 if (ret) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530619 pr_err("%s: fail to get channel weight with error %d\n",
620 __func__, ret);
621 goto fail_cmd;
622 }
623
624 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
625 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
626 adm_params->hdr.src_svc = APR_SVC_ADM;
627 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
628 adm_params->hdr.src_port = port_id;
629 adm_params->hdr.dest_svc = APR_SVC_ADM;
630 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
631 adm_params->hdr.dest_port =
632 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
633 adm_params->hdr.token = port_idx << 16 | copp_idx;
634 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
635 adm_params->hdr.pkt_size = sz;
636 adm_params->payload_addr_lsw = 0;
637 adm_params->payload_addr_msw = 0;
638 adm_params->mem_map_handle = 0;
639 adm_params->reserved = 0;
640
641 ptr = (u16 *)adm_params;
642 for (index = 0; index < (sz / 2); index++)
643 pr_debug("%s: adm_params[%d] = 0x%x\n",
644 __func__, index, (unsigned int)ptr[index]);
645
646 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], 0);
647 ret = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
648 if (ret < 0) {
649 pr_err("%s: Set params failed port %d rc %d\n", __func__,
650 port_id, ret);
651 ret = -EINVAL;
652 goto fail_cmd;
653 }
654
655 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
656 atomic_read(
657 &this_adm.copp.stat[port_idx][copp_idx]) >= 0,
658 msecs_to_jiffies(TIMEOUT_MS));
659 if (!ret) {
660 pr_err("%s: set params timed out port = %d\n",
661 __func__, port_id);
662 ret = -ETIMEDOUT;
663 goto fail_cmd;
664 }
665 ret = 0;
666fail_cmd:
667 kfree(adm_params);
668
669 return ret;
670}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530671EXPORT_SYMBOL(adm_programable_channel_mixer);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530672
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530673/**
674 * adm_set_stereo_to_custom_stereo -
675 * command to update custom stereo
676 *
677 * @port_id: Port ID number
678 * @copp_idx: copp index of ADM copp
679 * @session_id: session id to be updated
680 * @params: params pointer
681 * @param_length: length of params
682 *
683 * Returns 0 on success or error on failure
684 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530685int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx,
686 unsigned int session_id, char *params,
687 uint32_t params_length)
688{
689 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
690 int sz, rc = 0, port_idx;
691
692 pr_debug("%s:\n", __func__);
693 port_id = afe_convert_virtual_to_portid(port_id);
694 port_idx = adm_validate_and_get_port_index(port_id);
695 if (port_idx < 0) {
696 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
697 return -EINVAL;
698 }
699
700 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
701 params_length;
702 adm_params = kzalloc(sz, GFP_KERNEL);
703 if (!adm_params) {
704 pr_err("%s, adm params memory alloc failed\n", __func__);
705 return -ENOMEM;
706 }
707
708 memcpy(((u8 *)adm_params +
709 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)),
710 params, params_length);
711 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
712 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
713 adm_params->hdr.pkt_size = sz;
714 adm_params->hdr.src_svc = APR_SVC_ADM;
715 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
716 adm_params->hdr.src_port = port_id;
717 adm_params->hdr.dest_svc = APR_SVC_ADM;
718 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
719 adm_params->hdr.dest_port = 0; /* Ignored */;
720 adm_params->hdr.token = port_idx << 16 | copp_idx;
721 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
722 adm_params->payload_addr_lsw = 0;
723 adm_params->payload_addr_msw = 0;
724 adm_params->mem_map_handle = 0;
725 adm_params->payload_size = params_length;
726 /* direction RX as 0 */
727 adm_params->direction = ADM_MATRIX_ID_AUDIO_RX;
728 /* session id for this cmd to be applied on */
729 adm_params->sessionid = session_id;
730 adm_params->deviceid =
731 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
732 adm_params->reserved = 0;
733 pr_debug("%s: deviceid %d, session_id %d, src_port %d, dest_port %d\n",
734 __func__, adm_params->deviceid, adm_params->sessionid,
735 adm_params->hdr.src_port, adm_params->hdr.dest_port);
736 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
737 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
738 if (rc < 0) {
739 pr_err("%s: Set params failed port = 0x%x rc %d\n",
740 __func__, port_id, rc);
741 rc = -EINVAL;
742 goto set_stereo_to_custom_stereo_return;
743 }
744 /* Wait for the callback */
745 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
746 atomic_read(&this_adm.copp.stat
747 [port_idx][copp_idx]) >= 0,
748 msecs_to_jiffies(TIMEOUT_MS));
749 if (!rc) {
750 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
751 port_id);
752 rc = -EINVAL;
753 goto set_stereo_to_custom_stereo_return;
754 } else if (atomic_read(&this_adm.copp.stat
755 [port_idx][copp_idx]) > 0) {
756 pr_err("%s: DSP returned error[%s]\n", __func__,
757 adsp_err_get_err_str(atomic_read(
758 &this_adm.copp.stat
759 [port_idx][copp_idx])));
760 rc = adsp_err_get_lnx_err_code(
761 atomic_read(&this_adm.copp.stat
762 [port_idx][copp_idx]));
763 goto set_stereo_to_custom_stereo_return;
764 }
765 rc = 0;
766set_stereo_to_custom_stereo_return:
767 kfree(adm_params);
768 return rc;
769}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530770EXPORT_SYMBOL(adm_set_stereo_to_custom_stereo);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530771
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800772/*
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -0700773 * adm_set_custom_chmix_cfg:
774 * Set the custom channel mixer configuration for ADM
775 *
776 * @port_id: Backend port id
777 * @copp_idx: ADM copp index
778 * @session_id: ID of the requesting session
779 * @params: Expected packaged params for channel mixer
780 * @params_length: Length of the params to be set
781 * @direction: RX or TX direction
782 * @stream_type: Audio or Listen stream type
783 */
784int adm_set_custom_chmix_cfg(int port_id, int copp_idx,
785 unsigned int session_id, char *params,
786 uint32_t params_length, int direction,
787 int stream_type)
788{
789 struct adm_cmd_set_pspd_mtmx_strtr_params_v6 *adm_params = NULL;
790 int sz, rc = 0, port_idx;
791
792 port_id = afe_convert_virtual_to_portid(port_id);
793 port_idx = adm_validate_and_get_port_index(port_id);
794 if (port_idx < 0) {
795 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
796 return -EINVAL;
797 }
798
799 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v6) +
800 params_length;
801 adm_params = kzalloc(sz, GFP_KERNEL);
802 if (!adm_params) {
803 pr_err("%s, adm params memory alloc failed\n", __func__);
804 return -ENOMEM;
805 }
806
807 memcpy(((u8 *)adm_params +
808 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v6)),
809 params, params_length);
810 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
811 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
812 adm_params->hdr.pkt_size = sz;
813 adm_params->hdr.src_svc = APR_SVC_ADM;
814 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
815 adm_params->hdr.src_port = port_id;
816 adm_params->hdr.dest_svc = APR_SVC_ADM;
817 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
818 adm_params->hdr.dest_port = 0; /* Ignored */;
819 adm_params->hdr.token = port_idx << 16 | copp_idx;
820 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6;
821 adm_params->payload_addr_lsw = 0;
822 adm_params->payload_addr_msw = 0;
823 adm_params->mem_map_handle = 0;
824 adm_params->payload_size = params_length;
825 adm_params->direction = direction;
826 /* session id for this cmd to be applied on */
827 adm_params->sessionid = session_id;
828 adm_params->deviceid =
829 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
830 /* connecting stream type i.e. lsm or asm */
831 adm_params->stream_type = stream_type;
832 pr_debug("%s: deviceid %d, session_id %d, src_port %d, dest_port %d\n",
833 __func__, adm_params->deviceid, adm_params->sessionid,
834 adm_params->hdr.src_port, adm_params->hdr.dest_port);
835 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
836 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
837 if (rc < 0) {
838 pr_err("%s: Set params failed port = 0x%x rc %d\n",
839 __func__, port_id, rc);
840 rc = -EINVAL;
841 goto exit;
842 }
843 /* Wait for the callback */
844 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
845 atomic_read(&this_adm.copp.stat
846 [port_idx][copp_idx]),
847 msecs_to_jiffies(TIMEOUT_MS));
848 if (!rc) {
849 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
850 port_id);
851 rc = -EINVAL;
852 goto exit;
853 } else if (atomic_read(&this_adm.copp.stat
854 [port_idx][copp_idx]) > 0) {
855 pr_err("%s: DSP returned error[%s]\n", __func__,
856 adsp_err_get_err_str(atomic_read(
857 &this_adm.copp.stat
858 [port_idx][copp_idx])));
859 rc = adsp_err_get_lnx_err_code(
860 atomic_read(&this_adm.copp.stat
861 [port_idx][copp_idx]));
862 goto exit;
863 }
864
865 rc = 0;
866exit:
867 kfree(adm_params);
868 return rc;
869}
870EXPORT_SYMBOL(adm_set_custom_chmix_cfg);
871
872/*
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800873 * With pre-packed data, only the opcode differes from V5 and V6.
874 * Use q6common_pack_pp_params to pack the data correctly.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530875 */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800876int adm_set_pp_params(int port_id, int copp_idx,
877 struct mem_mapping_hdr *mem_hdr, u8 *param_data,
878 u32 param_size)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530879{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800880 struct adm_cmd_set_pp_params *adm_set_params = NULL;
881 int size = 0;
882 int port_idx = 0;
883 atomic_t *copp_stat = NULL;
884 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530885
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530886 port_id = afe_convert_virtual_to_portid(port_id);
887 port_idx = adm_validate_and_get_port_index(port_id);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800888 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
889 pr_err("%s: Invalid port_idx 0x%x\n", __func__, port_idx);
890 return -EINVAL;
891 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
892 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530893 return -EINVAL;
894 }
895
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800896 /* Only add params_size in inband case */
897 size = sizeof(struct adm_cmd_set_pp_params);
898 if (param_data != NULL)
899 size += param_size;
900 adm_set_params = kzalloc(size, GFP_KERNEL);
901 if (!adm_set_params)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530902 return -ENOMEM;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800903
904 adm_set_params->apr_hdr.hdr_field =
905 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
906 APR_PKT_VER);
907 adm_set_params->apr_hdr.pkt_size = size;
908 adm_set_params->apr_hdr.src_svc = APR_SVC_ADM;
909 adm_set_params->apr_hdr.src_domain = APR_DOMAIN_APPS;
910 adm_set_params->apr_hdr.src_port = port_id;
911 adm_set_params->apr_hdr.dest_svc = APR_SVC_ADM;
912 adm_set_params->apr_hdr.dest_domain = APR_DOMAIN_ADSP;
913 adm_set_params->apr_hdr.dest_port =
914 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
915 adm_set_params->apr_hdr.token = port_idx << 16 | copp_idx;
916
917 if (q6common_is_instance_id_supported())
918 adm_set_params->apr_hdr.opcode = ADM_CMD_SET_PP_PARAMS_V6;
919 else
920 adm_set_params->apr_hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
921
922 adm_set_params->payload_size = param_size;
923
924 if (mem_hdr != NULL) {
925 /* Out of Band Case */
926 adm_set_params->mem_hdr = *mem_hdr;
927 } else if (param_data != NULL) {
928 /*
929 * In band case. Parameter data must be pre-packed with its
930 * header before calling this function. Use
931 * q6common_pack_pp_params to pack parameter data and header
932 * correctly.
933 */
934 memcpy(&adm_set_params->param_data, param_data, param_size);
935 } else {
936 pr_err("%s: Received NULL pointers for both memory header and param data\n",
937 __func__);
938 ret = -EINVAL;
939 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530940 }
941
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800942 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
943 atomic_set(copp_stat, -1);
944 ret = apr_send_pkt(this_adm.apr, (uint32_t *) adm_set_params);
945 if (ret < 0) {
946 pr_err("%s: Set params APR send failed port = 0x%x ret %d\n",
947 __func__, port_id, ret);
948 goto done;
949 }
950 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
951 atomic_read(copp_stat) >= 0,
952 msecs_to_jiffies(TIMEOUT_MS));
953 if (!ret) {
954 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
955 port_id);
956 ret = -ETIMEDOUT;
957 goto done;
958 }
959 if (atomic_read(copp_stat) > 0) {
960 pr_err("%s: DSP returned error[%s]\n", __func__,
961 adsp_err_get_err_str(atomic_read(copp_stat)));
962 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
963 goto done;
964 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530965
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800966 ret = 0;
967done:
968 kfree(adm_set_params);
969 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530970}
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800971EXPORT_SYMBOL(adm_set_pp_params);
972
973int adm_pack_and_set_one_pp_param(int port_id, int copp_idx,
974 struct param_hdr_v3 param_hdr, u8 *param_data)
975{
976 u8 *packed_data = NULL;
977 u32 total_size = 0;
978 int ret = 0;
979
980 total_size = sizeof(union param_hdrs) + param_hdr.param_size;
981 packed_data = kzalloc(total_size, GFP_KERNEL);
982 if (!packed_data)
983 return -ENOMEM;
984
985 ret = q6common_pack_pp_params(packed_data, &param_hdr, param_data,
986 &total_size);
987 if (ret) {
988 pr_err("%s: Failed to pack parameter data, error %d\n",
989 __func__, ret);
990 goto done;
991 }
992
993 ret = adm_set_pp_params(port_id, copp_idx, NULL, packed_data,
994 total_size);
995 if (ret)
996 pr_err("%s: Failed to set parameter data, error %d\n", __func__,
997 ret);
998done:
999 kfree(packed_data);
1000 return ret;
1001}
1002EXPORT_SYMBOL(adm_pack_and_set_one_pp_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301003
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001004/*
1005 * Only one parameter can be requested at a time. Therefore, packing and sending
1006 * the request can be handled locally.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301007 */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001008int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id,
1009 struct mem_mapping_hdr *mem_hdr,
1010 struct param_hdr_v3 *param_hdr, u8 *returned_param_data)
1011{
1012 struct adm_cmd_get_pp_params adm_get_params;
1013 int total_size = 0;
1014 int get_param_array_sz = ARRAY_SIZE(adm_get_parameters);
1015 int returned_param_size = 0;
1016 int returned_param_size_in_bytes = 0;
1017 int port_idx = 0;
1018 int idx = 0;
1019 atomic_t *copp_stat = NULL;
1020 int ret = 0;
1021
1022 if (param_hdr == NULL) {
1023 pr_err("%s: Received NULL pointer for parameter header\n",
1024 __func__);
1025 return -EINVAL;
1026 }
1027
1028 port_id = afe_convert_virtual_to_portid(port_id);
1029 port_idx = adm_validate_and_get_port_index(port_id);
1030 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1031 pr_err("%s: Invalid port_idx 0x%x\n", __func__, port_idx);
1032 return -EINVAL;
1033 }
1034 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1035 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
1036 return -EINVAL;
1037 }
1038
1039 memset(&adm_get_params, 0, sizeof(adm_get_params));
1040
1041 if (mem_hdr != NULL)
1042 adm_get_params.mem_hdr = *mem_hdr;
1043
1044 q6common_pack_pp_params((u8 *) &adm_get_params.param_hdr, param_hdr,
1045 NULL, &total_size);
1046
1047 /* Pack APR header after filling body so total_size has correct value */
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001048 adm_get_params.apr_hdr.hdr_field =
1049 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1050 APR_PKT_VER);
1051 adm_get_params.apr_hdr.pkt_size = sizeof(adm_get_params);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001052 adm_get_params.apr_hdr.src_svc = APR_SVC_ADM;
1053 adm_get_params.apr_hdr.src_domain = APR_DOMAIN_APPS;
1054 adm_get_params.apr_hdr.src_port = port_id;
1055 adm_get_params.apr_hdr.dest_svc = APR_SVC_ADM;
1056 adm_get_params.apr_hdr.dest_domain = APR_DOMAIN_ADSP;
1057 adm_get_params.apr_hdr.dest_port =
1058 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1059 adm_get_params.apr_hdr.token =
1060 port_idx << 16 | client_id << 8 | copp_idx;
1061
1062 if (q6common_is_instance_id_supported())
1063 adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V6;
1064 else
1065 adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
1066
1067 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
1068 atomic_set(copp_stat, -1);
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001069
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001070 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_params);
Vidyakumar Athotae427c412018-06-16 00:02:46 -07001071 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001072 pr_err("%s: Get params APR send failed port = 0x%x ret %d\n",
1073 __func__, port_id, ret);
1074 ret = -EINVAL;
1075 goto done;
1076 }
1077 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1078 atomic_read(copp_stat) >= 0,
1079 msecs_to_jiffies(TIMEOUT_MS));
1080 if (!ret) {
1081 pr_err("%s: Get params timed out port = 0x%x\n", __func__,
1082 port_id);
1083 ret = -ETIMEDOUT;
1084 goto done;
1085 }
1086 if (atomic_read(copp_stat) > 0) {
1087 pr_err("%s: DSP returned error[%s]\n", __func__,
1088 adsp_err_get_err_str(atomic_read(copp_stat)));
1089 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
1090 goto done;
1091 }
1092
1093 ret = 0;
1094
1095 /* Copy data to caller if sent in band */
1096 if (!returned_param_data) {
1097 pr_debug("%s: Received NULL pointer for param destination, not copying payload\n",
1098 __func__);
1099 return 0;
1100 }
1101
1102 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
1103 returned_param_size = adm_get_parameters[idx];
1104 if (returned_param_size < 0 ||
1105 returned_param_size + idx + 1 > get_param_array_sz) {
1106 pr_err("%s: Invalid parameter size %d\n", __func__,
1107 returned_param_size);
1108 return -EINVAL;
1109 }
1110
1111 returned_param_size_in_bytes = returned_param_size * sizeof(uint32_t);
1112 if (param_hdr->param_size < returned_param_size_in_bytes) {
1113 pr_err("%s: Provided buffer is not big enough, provided buffer size(%d) size needed(%d)\n",
1114 __func__, param_hdr->param_size,
1115 returned_param_size_in_bytes);
1116 return -EINVAL;
1117 }
1118
1119 memcpy(returned_param_data, &adm_get_parameters[idx + 1],
1120 returned_param_size_in_bytes);
1121done:
1122 return ret;
1123}
1124EXPORT_SYMBOL(adm_get_pp_params);
1125
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001126int adm_get_pp_topo_module_list_v2(int port_id, int copp_idx,
1127 int32_t param_length,
1128 int32_t *returned_params)
1129{
1130 struct adm_cmd_get_pp_topo_module_list adm_get_module_list;
1131 bool iid_supported = q6common_is_instance_id_supported();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301132 int *topo_list;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001133 int num_modules = 0;
1134 int list_size = 0;
1135 int port_idx, idx;
1136 int i = 0;
1137 atomic_t *copp_stat = NULL;
1138 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301139
1140 pr_debug("%s : port_id %x", __func__, port_id);
1141 port_id = afe_convert_virtual_to_portid(port_id);
1142 port_idx = adm_validate_and_get_port_index(port_id);
1143 if (port_idx < 0) {
1144 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1145 return -EINVAL;
1146 }
1147
1148 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1149 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
1150 return -EINVAL;
1151 }
1152
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001153 memset(&adm_get_module_list, 0, sizeof(adm_get_module_list));
1154
1155 adm_get_module_list.apr_hdr.pkt_size = sizeof(adm_get_module_list);
1156 adm_get_module_list.apr_hdr.src_svc = APR_SVC_ADM;
1157 adm_get_module_list.apr_hdr.src_domain = APR_DOMAIN_APPS;
1158 adm_get_module_list.apr_hdr.src_port = port_id;
1159 adm_get_module_list.apr_hdr.dest_svc = APR_SVC_ADM;
1160 adm_get_module_list.apr_hdr.dest_domain = APR_DOMAIN_ADSP;
1161 adm_get_module_list.apr_hdr.dest_port =
1162 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1163 adm_get_module_list.apr_hdr.token = port_idx << 16 | copp_idx;
1164 /*
1165 * Out of band functionality is not currently utilized.
1166 * Assume in band.
1167 */
1168 if (iid_supported) {
1169 adm_get_module_list.apr_hdr.opcode =
1170 ADM_CMD_GET_PP_TOPO_MODULE_LIST_V2;
1171 adm_get_module_list.param_max_size = param_length;
1172 } else {
1173 adm_get_module_list.apr_hdr.opcode =
1174 ADM_CMD_GET_PP_TOPO_MODULE_LIST;
1175
1176 if (param_length > U16_MAX) {
1177 pr_err("%s: Invalid param length for V1 %d\n", __func__,
1178 param_length);
1179 return -EINVAL;
1180 }
1181 adm_get_module_list.param_max_size = param_length << 16;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301182 }
1183
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001184 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
1185 atomic_set(copp_stat, -1);
1186 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_module_list);
Vidyakumar Athotae427c412018-06-16 00:02:46 -07001187 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001188 pr_err("%s: APR send pkt failed for port_id: 0x%x failed ret %d\n",
1189 __func__, port_id, ret);
1190 ret = -EINVAL;
1191 goto done;
1192 }
1193 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1194 atomic_read(copp_stat) >= 0,
1195 msecs_to_jiffies(TIMEOUT_MS));
1196 if (!ret) {
1197 pr_err("%s: Timeout for port_id: 0x%x\n", __func__, port_id);
1198 ret = -ETIMEDOUT;
1199 goto done;
1200 }
1201 if (atomic_read(copp_stat) > 0) {
1202 pr_err("%s: DSP returned error[%s]\n", __func__,
1203 adsp_err_get_err_str(atomic_read(copp_stat)));
1204 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
1205 goto done;
1206 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301207
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001208 ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301209
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001210 if (returned_params) {
1211 /*
1212 * When processing ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST IID is
1213 * added since it is not present. Therefore, there is no need to
1214 * do anything different if IID is not supported here as it is
1215 * already taken care of.
1216 */
1217 idx = ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH * copp_idx;
1218 num_modules = adm_module_topo_list[idx];
1219 if (num_modules < 0 || num_modules > MAX_MODULES_IN_TOPO) {
1220 pr_err("%s: Invalid number of modules returned %d\n",
1221 __func__, num_modules);
1222 return -EINVAL;
1223 }
1224
1225 list_size = num_modules * sizeof(struct module_instance_info);
1226 if (param_length < list_size) {
1227 pr_err("%s: Provided buffer not big enough to hold module-instance list, provided size %d, needed size %d\n",
1228 __func__, param_length, list_size);
1229 return -EINVAL;
1230 }
1231
1232 topo_list = (int32_t *) (&adm_module_topo_list[idx]);
1233 memcpy(returned_params, topo_list, list_size);
1234 for (i = 1; i <= num_modules; i += 2) {
1235 pr_debug("module = 0x%x instance = 0x%x\n",
1236 returned_params[i], returned_params[i + 1]);
1237 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301238 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001239done:
1240 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301241}
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001242EXPORT_SYMBOL(adm_get_pp_topo_module_list_v2);
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301243
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301244static void adm_callback_debug_print(struct apr_client_data *data)
1245{
1246 uint32_t *payload;
1247
1248 payload = data->payload;
1249
1250 if (data->payload_size >= 8)
1251 pr_debug("%s: code = 0x%x PL#0[0x%x], PL#1[0x%x], size = %d\n",
1252 __func__, data->opcode, payload[0], payload[1],
1253 data->payload_size);
1254 else if (data->payload_size >= 4)
1255 pr_debug("%s: code = 0x%x PL#0[0x%x], size = %d\n",
1256 __func__, data->opcode, payload[0],
1257 data->payload_size);
1258 else
1259 pr_debug("%s: code = 0x%x, size = %d\n",
1260 __func__, data->opcode, data->payload_size);
1261}
1262
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301263/**
1264 * adm_set_multi_ch_map -
1265 * Update multi channel map info
1266 *
1267 * @channel_map: pointer with channel map info
1268 * @path: direction or ADM path type
1269 *
1270 * Returns 0 on success or error on failure
1271 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301272int adm_set_multi_ch_map(char *channel_map, int path)
1273{
1274 int idx;
1275
1276 if (path == ADM_PATH_PLAYBACK) {
1277 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1278 } else if (path == ADM_PATH_LIVE_REC) {
1279 idx = ADM_MCH_MAP_IDX_REC;
1280 } else {
1281 pr_err("%s: invalid attempt to set path %d\n", __func__, path);
1282 return -EINVAL;
1283 }
1284
1285 memcpy(multi_ch_maps[idx].channel_mapping, channel_map,
Dieter Luecking50c55352018-09-28 14:29:17 +02001286 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301287 multi_ch_maps[idx].set_channel_map = true;
1288
1289 return 0;
1290}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301291EXPORT_SYMBOL(adm_set_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301292
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301293/**
1294 * adm_get_multi_ch_map -
1295 * Retrieves multi channel map info
1296 *
1297 * @channel_map: pointer to be updated with channel map
1298 * @path: direction or ADM path type
1299 *
1300 * Returns 0 on success or error on failure
1301 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301302int adm_get_multi_ch_map(char *channel_map, int path)
1303{
1304 int idx;
1305
1306 if (path == ADM_PATH_PLAYBACK) {
1307 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1308 } else if (path == ADM_PATH_LIVE_REC) {
1309 idx = ADM_MCH_MAP_IDX_REC;
1310 } else {
1311 pr_err("%s: invalid attempt to get path %d\n", __func__, path);
1312 return -EINVAL;
1313 }
1314
1315 if (multi_ch_maps[idx].set_channel_map) {
1316 memcpy(channel_map, multi_ch_maps[idx].channel_mapping,
Dieter Luecking50c55352018-09-28 14:29:17 +02001317 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301318 }
1319
1320 return 0;
1321}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301322EXPORT_SYMBOL(adm_get_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301323
Rohit kumar2054b692019-02-01 18:01:12 +05301324/**
1325 * adm_set_port_multi_ch_map -
1326 * Update port specific channel map info
1327 *
1328 * @channel_map: pointer with channel map info
1329 * @port_id: port for which chmap is set
1330 */
1331void adm_set_port_multi_ch_map(char *channel_map, int port_id)
1332{
1333 int port_idx;
1334
1335 port_id = q6audio_convert_virtual_to_portid(port_id);
1336 port_idx = adm_validate_and_get_port_index(port_id);
1337
1338 if (port_idx < 0) {
1339 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1340 return;
1341 }
1342
1343 memcpy(port_channel_map[port_idx].channel_mapping, channel_map,
1344 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
1345 port_channel_map[port_idx].set_channel_map = true;
1346}
1347EXPORT_SYMBOL(adm_set_port_multi_ch_map);
1348
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001349static int adm_process_get_param_response(u32 opcode, u32 idx, u32 *payload,
1350 u32 payload_size)
1351{
1352 struct adm_cmd_rsp_get_pp_params_v5 *v5_rsp = NULL;
1353 struct adm_cmd_rsp_get_pp_params_v6 *v6_rsp = NULL;
1354 u32 *param_data = NULL;
1355 int data_size = 0;
1356 int struct_size = 0;
1357
1358 if (payload == NULL) {
1359 pr_err("%s: Payload is NULL\n", __func__);
1360 return -EINVAL;
1361 }
1362
1363 switch (opcode) {
1364 case ADM_CMDRSP_GET_PP_PARAMS_V5:
1365 struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v5);
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001366 if (payload_size < struct_size) {
1367 pr_err("%s: payload size %d < expected size %d\n",
1368 __func__, payload_size, struct_size);
1369 break;
1370 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001371 v5_rsp = (struct adm_cmd_rsp_get_pp_params_v5 *) payload;
1372 data_size = v5_rsp->param_hdr.param_size;
1373 param_data = v5_rsp->param_data;
1374 break;
1375 case ADM_CMDRSP_GET_PP_PARAMS_V6:
1376 struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v6);
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001377 if (payload_size < struct_size) {
1378 pr_err("%s: payload size %d < expected size %d\n",
1379 __func__, payload_size, struct_size);
1380 break;
1381 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001382 v6_rsp = (struct adm_cmd_rsp_get_pp_params_v6 *) payload;
1383 data_size = v6_rsp->param_hdr.param_size;
1384 param_data = v6_rsp->param_data;
1385 break;
1386 default:
1387 pr_err("%s: Invalid opcode %d\n", __func__, opcode);
1388 return -EINVAL;
1389 }
1390
1391 /*
1392 * Just store the returned parameter data, not the header. The calling
1393 * function is expected to know what it asked for. Therefore, there is
1394 * no difference between V5 and V6.
1395 */
1396 if ((payload_size >= struct_size + data_size) &&
1397 (ARRAY_SIZE(adm_get_parameters) > idx) &&
Karthikeyan Mani95be5b12018-11-09 14:57:32 -08001398 (ARRAY_SIZE(adm_get_parameters) > idx + 1 + data_size)) {
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001399 pr_debug("%s: Received parameter data in band\n",
1400 __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001401 /*
1402 * data_size is expressed in number of bytes, store in number of
1403 * ints
1404 */
1405 adm_get_parameters[idx] =
1406 data_size / sizeof(*adm_get_parameters);
1407 pr_debug("%s: GET_PP PARAM: received parameter length: 0x%x\n",
1408 __func__, adm_get_parameters[idx]);
1409 /* store params after param_size */
1410 memcpy(&adm_get_parameters[idx + 1], param_data, data_size);
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001411 } else if (payload_size == sizeof(uint32_t)) {
1412 adm_get_parameters[idx] = -1;
1413 pr_debug("%s: Out of band case, setting size to %d\n",
1414 __func__, adm_get_parameters[idx]);
1415 } else {
1416 pr_err("%s: Invalid parameter combination, payload_size %d, idx %d\n",
1417 __func__, payload_size, idx);
1418 return -EINVAL;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001419 }
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001420 return 0;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001421}
1422
1423static int adm_process_get_topo_list_response(u32 opcode, int copp_idx,
1424 u32 num_modules, u32 *payload,
1425 u32 payload_size)
1426{
1427 u32 *fill_list = NULL;
1428 int idx = 0;
1429 int i = 0;
1430 int j = 0;
1431
1432 if (payload == NULL) {
1433 pr_err("%s: Payload is NULL\n", __func__);
1434 return -EINVAL;
1435 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1436 pr_err("%s: Invalid COPP index %d\n", __func__, copp_idx);
1437 return -EINVAL;
1438 }
1439
1440 idx = ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH * copp_idx;
1441 fill_list = adm_module_topo_list + idx;
1442 *fill_list++ = num_modules;
1443 for (i = 0; i < num_modules; i++) {
1444 if (j > payload_size / sizeof(u32)) {
1445 pr_err("%s: Invalid number of modules specified %d\n",
1446 __func__, num_modules);
1447 return -EINVAL;
1448 }
1449
1450 /* store module ID */
1451 *fill_list++ = payload[j];
1452 j++;
1453
1454 switch (opcode) {
1455 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
1456 /* store instance ID */
1457 *fill_list++ = payload[j];
1458 j++;
1459 break;
1460 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
1461 /* Insert IID 0 when repacking */
1462 *fill_list++ = INSTANCE_ID_0;
1463 break;
1464 default:
1465 pr_err("%s: Invalid opcode %d\n", __func__, opcode);
1466 return -EINVAL;
1467 }
1468 }
1469
1470 return 0;
1471}
1472
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301473static void adm_reset_data(void)
1474{
1475 int i, j;
1476
1477 apr_reset(this_adm.apr);
1478 for (i = 0; i < AFE_MAX_PORTS; i++) {
1479 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
1480 atomic_set(&this_adm.copp.id[i][j],
1481 RESET_COPP_ID);
1482 atomic_set(&this_adm.copp.cnt[i][j], 0);
1483 atomic_set(
1484 &this_adm.copp.topology[i][j], 0);
1485 atomic_set(&this_adm.copp.mode[i][j],
1486 0);
1487 atomic_set(&this_adm.copp.stat[i][j],
1488 0);
1489 atomic_set(&this_adm.copp.rate[i][j],
1490 0);
1491 atomic_set(
1492 &this_adm.copp.channels[i][j],
1493 0);
1494 atomic_set(
1495 &this_adm.copp.bit_width[i][j], 0);
1496 atomic_set(
1497 &this_adm.copp.app_type[i][j], 0);
1498 atomic_set(
1499 &this_adm.copp.acdb_id[i][j], 0);
Surendar Karkae7507512018-07-20 15:46:54 +05301500 atomic_set(
1501 &this_adm.copp.session_type[i][j], 0);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301502 this_adm.copp.adm_status[i][j] =
1503 ADM_STATUS_CALIBRATION_REQUIRED;
1504 }
1505 }
1506 this_adm.apr = NULL;
1507 cal_utils_clear_cal_block_q6maps(ADM_MAX_CAL_TYPES,
1508 this_adm.cal_data);
1509 mutex_lock(&this_adm.cal_data
1510 [ADM_CUSTOM_TOP_CAL]->lock);
1511 this_adm.set_custom_topology = 1;
1512 mutex_unlock(&this_adm.cal_data[
1513 ADM_CUSTOM_TOP_CAL]->lock);
1514 rtac_clear_mapping(ADM_RTAC_CAL);
1515 /*
1516 * Free the ION memory and clear the map handles
1517 * for Source Tracking
1518 */
1519 if (this_adm.sourceTrackingData.memmap.paddr != 0) {
1520 msm_audio_ion_free(
1521 this_adm.sourceTrackingData.dma_buf);
1522 this_adm.sourceTrackingData.dma_buf = NULL;
1523 this_adm.sourceTrackingData.memmap.size = 0;
1524 this_adm.sourceTrackingData.memmap.kvaddr =
1525 NULL;
1526 this_adm.sourceTrackingData.memmap.paddr = 0;
1527 this_adm.sourceTrackingData.apr_cmd_status = -1;
1528 atomic_set(&this_adm.mem_map_handles[
1529 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
1530 }
1531}
1532
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301533static int32_t adm_callback(struct apr_client_data *data, void *priv)
1534{
1535 uint32_t *payload;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001536 int port_idx, copp_idx, idx, client_id;
1537 int num_modules;
1538 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301539
1540 if (data == NULL) {
1541 pr_err("%s: data parameter is null\n", __func__);
1542 return -EINVAL;
1543 }
1544
1545 payload = data->payload;
1546
1547 if (data->opcode == RESET_EVENTS) {
1548 pr_debug("%s: Reset event is received: %d %d apr[%pK]\n",
1549 __func__,
1550 data->reset_event, data->reset_proc, this_adm.apr);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301551 if (this_adm.apr)
1552 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301553 return 0;
1554 }
1555
1556 adm_callback_debug_print(data);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001557 if (data->payload_size >= sizeof(uint32_t)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301558 copp_idx = (data->token) & 0XFF;
1559 port_idx = ((data->token) >> 16) & 0xFF;
1560 client_id = ((data->token) >> 8) & 0xFF;
1561 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1562 pr_err("%s: Invalid port idx %d token %d\n",
1563 __func__, port_idx, data->token);
1564 return 0;
1565 }
1566 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1567 pr_err("%s: Invalid copp idx %d token %d\n",
1568 __func__, copp_idx, data->token);
1569 return 0;
1570 }
1571 if (client_id < 0 || client_id >= ADM_CLIENT_ID_MAX) {
1572 pr_err("%s: Invalid client id %d\n", __func__,
1573 client_id);
1574 return 0;
1575 }
1576 if (data->opcode == APR_BASIC_RSP_RESULT) {
1577 pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
1578 __func__, payload[0]);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001579
1580 if (!((client_id != ADM_CLIENT_ID_SOURCE_TRACKING) &&
1581 ((payload[0] == ADM_CMD_SET_PP_PARAMS_V5) ||
1582 (payload[0] == ADM_CMD_SET_PP_PARAMS_V6)))) {
1583 if (data->payload_size <
1584 (2 * sizeof(uint32_t))) {
1585 pr_err("%s: Invalid payload size %d\n",
1586 __func__, data->payload_size);
1587 return 0;
1588 }
1589 }
1590
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301591 if (payload[1] != 0) {
1592 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
1593 __func__, payload[0], payload[1]);
1594 }
1595 switch (payload[0]) {
1596 case ADM_CMD_SET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001597 case ADM_CMD_SET_PP_PARAMS_V6:
1598 pr_debug("%s: ADM_CMD_SET_PP_PARAMS\n",
1599 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301600 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1601 this_adm.sourceTrackingData.
1602 apr_cmd_status = payload[1];
1603 else if (rtac_make_adm_callback(payload,
1604 data->payload_size))
1605 break;
1606 /*
1607 * if soft volume is called and already
1608 * interrupted break out of the sequence here
1609 */
1610 case ADM_CMD_DEVICE_OPEN_V5:
1611 case ADM_CMD_DEVICE_CLOSE_V5:
1612 case ADM_CMD_DEVICE_OPEN_V6:
Dieter Luecking50c55352018-09-28 14:29:17 +02001613 case ADM_CMD_DEVICE_OPEN_V8:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301614 pr_debug("%s: Basic callback received, wake up.\n",
1615 __func__);
1616 atomic_set(&this_adm.copp.stat[port_idx]
1617 [copp_idx], payload[1]);
1618 wake_up(
1619 &this_adm.copp.wait[port_idx][copp_idx]);
1620 break;
1621 case ADM_CMD_ADD_TOPOLOGIES:
1622 pr_debug("%s: callback received, ADM_CMD_ADD_TOPOLOGIES.\n",
1623 __func__);
1624 atomic_set(&this_adm.adm_stat, payload[1]);
1625 wake_up(&this_adm.adm_wait);
1626 break;
1627 case ADM_CMD_MATRIX_MAP_ROUTINGS_V5:
1628 case ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5:
1629 pr_debug("%s: Basic callback received, wake up.\n",
1630 __func__);
1631 atomic_set(&this_adm.matrix_map_stat,
1632 payload[1]);
1633 wake_up(&this_adm.matrix_map_wait);
1634 break;
1635 case ADM_CMD_SHARED_MEM_UNMAP_REGIONS:
1636 pr_debug("%s: ADM_CMD_SHARED_MEM_UNMAP_REGIONS\n",
1637 __func__);
1638 atomic_set(&this_adm.adm_stat, payload[1]);
1639 wake_up(&this_adm.adm_wait);
1640 break;
1641 case ADM_CMD_SHARED_MEM_MAP_REGIONS:
1642 pr_debug("%s: ADM_CMD_SHARED_MEM_MAP_REGIONS\n",
1643 __func__);
1644 /* Should only come here if there is an APR */
1645 /* error or malformed APR packet. Otherwise */
1646 /* response will be returned as */
1647 if (payload[1] != 0) {
1648 pr_err("%s: ADM map error, resuming\n",
1649 __func__);
1650 atomic_set(&this_adm.adm_stat,
1651 payload[1]);
1652 wake_up(&this_adm.adm_wait);
1653 }
1654 break;
1655 case ADM_CMD_GET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001656 case ADM_CMD_GET_PP_PARAMS_V6:
1657 pr_debug("%s: ADM_CMD_GET_PP_PARAMS\n",
1658 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301659 /* Should only come here if there is an APR */
1660 /* error or malformed APR packet. Otherwise */
1661 /* response will be returned as */
1662 /* ADM_CMDRSP_GET_PP_PARAMS_V5 */
1663 if (client_id ==
1664 ADM_CLIENT_ID_SOURCE_TRACKING) {
1665 this_adm.sourceTrackingData.
1666 apr_cmd_status = payload[1];
1667 if (payload[1] != 0)
1668 pr_err("%s: ADM get param error = %d\n",
1669 __func__, payload[1]);
1670
1671 atomic_set(&this_adm.copp.stat
1672 [port_idx][copp_idx],
1673 payload[1]);
1674 wake_up(&this_adm.copp.wait
1675 [port_idx][copp_idx]);
1676 } else {
1677 if (payload[1] != 0) {
1678 pr_err("%s: ADM get param error = %d, resuming\n",
1679 __func__, payload[1]);
1680
1681 rtac_make_adm_callback(payload,
1682 data->payload_size);
1683 }
1684 }
1685 break;
1686 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5:
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -07001687 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6:
1688 pr_debug("%s:callback received PSPD MTMX, wake up\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301689 __func__);
1690 atomic_set(&this_adm.copp.stat[port_idx]
1691 [copp_idx], payload[1]);
1692 wake_up(
1693 &this_adm.copp.wait[port_idx][copp_idx]);
1694 break;
1695 case ADM_CMD_GET_PP_TOPO_MODULE_LIST:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001696 case ADM_CMD_GET_PP_TOPO_MODULE_LIST_V2:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301697 pr_debug("%s:ADM_CMD_GET_PP_TOPO_MODULE_LIST\n",
1698 __func__);
1699 if (payload[1] != 0)
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001700 pr_err("%s: ADM get topo list error = %d\n",
1701 __func__, payload[1]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301702 break;
1703 default:
1704 pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
1705 payload[0]);
1706 break;
1707 }
1708 return 0;
1709 }
1710
1711 switch (data->opcode) {
1712 case ADM_CMDRSP_DEVICE_OPEN_V5:
Dieter Luecking50c55352018-09-28 14:29:17 +02001713 case ADM_CMDRSP_DEVICE_OPEN_V6:
1714 case ADM_CMDRSP_DEVICE_OPEN_V8: {
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001715 struct adm_cmd_rsp_device_open_v5 *open = NULL;
1716 if (data->payload_size <
1717 sizeof(struct adm_cmd_rsp_device_open_v5)) {
1718 pr_err("%s: Invalid payload size %d\n", __func__,
1719 data->payload_size);
1720 return 0;
1721 }
1722 open = (struct adm_cmd_rsp_device_open_v5 *)data->payload;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301723 if (open->copp_id == INVALID_COPP_ID) {
1724 pr_err("%s: invalid coppid rxed %d\n",
1725 __func__, open->copp_id);
1726 atomic_set(&this_adm.copp.stat[port_idx]
1727 [copp_idx], ADSP_EBADPARAM);
1728 wake_up(
1729 &this_adm.copp.wait[port_idx][copp_idx]);
1730 break;
1731 }
1732 atomic_set(&this_adm.copp.stat
1733 [port_idx][copp_idx], payload[0]);
1734 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
1735 open->copp_id);
1736 pr_debug("%s: coppid rxed=%d\n", __func__,
1737 open->copp_id);
1738 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1739 }
1740 break;
1741 case ADM_CMDRSP_GET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001742 case ADM_CMDRSP_GET_PP_PARAMS_V6:
1743 pr_debug("%s: ADM_CMDRSP_GET_PP_PARAMS\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301744 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1745 this_adm.sourceTrackingData.apr_cmd_status =
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001746 payload[0];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301747 else if (rtac_make_adm_callback(payload,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001748 data->payload_size))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301749 break;
1750
1751 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001752 if (payload[0] == 0 && data->payload_size > 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001753 ret = adm_process_get_param_response(
1754 data->opcode, idx, payload,
1755 data->payload_size);
1756 if (ret)
1757 pr_err("%s: Failed to process get param response, error %d\n",
1758 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301759 } else {
1760 adm_get_parameters[idx] = -1;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001761 pr_err("%s: ADM_CMDRSP_GET_PP_PARAMS returned error 0x%x\n",
1762 __func__, payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301763 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001764 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1765 payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301766 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1767 break;
1768 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001769 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301770 pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n",
1771 __func__);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001772 if (data->payload_size >= (2 * sizeof(uint32_t))) {
1773 num_modules = payload[1];
1774 pr_debug("%s: Num modules %d\n", __func__,
1775 num_modules);
1776 if (payload[0]) {
1777 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
1778 __func__, payload[0]);
1779 } else if (num_modules > MAX_MODULES_IN_TOPO) {
1780 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n",
1781 __func__, num_modules);
1782 } else {
1783 ret = adm_process_get_topo_list_response(
1784 data->opcode, copp_idx,
1785 num_modules, payload,
1786 data->payload_size);
1787 if (ret)
1788 pr_err("%s: Failed to process get topo modules list response, error %d\n",
1789 __func__, ret);
1790 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301791 } else {
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001792 pr_err("%s: Invalid payload size %d\n",
1793 __func__, data->payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301794 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001795 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1796 payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301797 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1798 break;
1799 case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
1800 pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
1801 __func__);
1802 atomic_set(&this_adm.mem_map_handles[
1803 atomic_read(&this_adm.mem_map_index)],
1804 *payload);
1805 atomic_set(&this_adm.adm_stat, 0);
1806 wake_up(&this_adm.adm_wait);
1807 break;
1808 default:
1809 pr_err("%s: Unknown cmd:0x%x\n", __func__,
1810 data->opcode);
1811 break;
1812 }
1813 }
1814 return 0;
1815}
1816
1817static int adm_memory_map_regions(phys_addr_t *buf_add, uint32_t mempool_id,
1818 uint32_t *bufsz, uint32_t bufcnt)
1819{
1820 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
1821 struct avs_shared_map_region_payload *mregions = NULL;
1822 void *mmap_region_cmd = NULL;
1823 void *payload = NULL;
1824 int ret = 0;
1825 int i = 0;
1826 int cmd_size = 0;
1827
1828 pr_debug("%s:\n", __func__);
1829 if (this_adm.apr == NULL) {
1830 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
1831 0xFFFFFFFF, &this_adm);
1832 if (this_adm.apr == NULL) {
1833 pr_err("%s: Unable to register ADM\n", __func__);
1834 ret = -ENODEV;
1835 return ret;
1836 }
1837 rtac_set_adm_handle(this_adm.apr);
1838 }
1839
1840 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
1841 + sizeof(struct avs_shared_map_region_payload)
1842 * bufcnt;
1843
1844 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1845 if (!mmap_region_cmd)
1846 return -ENOMEM;
1847
1848 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)mmap_region_cmd;
1849 mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1850 APR_HDR_LEN(APR_HDR_SIZE),
1851 APR_PKT_VER);
1852 mmap_regions->hdr.pkt_size = cmd_size;
1853 mmap_regions->hdr.src_port = 0;
1854
1855 mmap_regions->hdr.dest_port = 0;
1856 mmap_regions->hdr.token = 0;
1857 mmap_regions->hdr.opcode = ADM_CMD_SHARED_MEM_MAP_REGIONS;
1858 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL & 0x00ff;
1859 mmap_regions->num_regions = bufcnt & 0x00ff;
1860 mmap_regions->property_flag = 0x00;
1861
1862 pr_debug("%s: map_regions->num_regions = %d\n", __func__,
1863 mmap_regions->num_regions);
1864 payload = ((u8 *) mmap_region_cmd +
1865 sizeof(struct avs_cmd_shared_mem_map_regions));
1866 mregions = (struct avs_shared_map_region_payload *)payload;
1867
1868 for (i = 0; i < bufcnt; i++) {
1869 mregions->shm_addr_lsw = lower_32_bits(buf_add[i]);
1870 mregions->shm_addr_msw =
1871 msm_audio_populate_upper_32_bits(buf_add[i]);
1872 mregions->mem_size_bytes = bufsz[i];
1873 ++mregions;
1874 }
1875
1876 atomic_set(&this_adm.adm_stat, -1);
1877 ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
1878 if (ret < 0) {
1879 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1880 mmap_regions->hdr.opcode, ret);
1881 ret = -EINVAL;
1882 goto fail_cmd;
1883 }
1884
1885 ret = wait_event_timeout(this_adm.adm_wait,
1886 atomic_read(&this_adm.adm_stat) >= 0,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001887 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301888 if (!ret) {
1889 pr_err("%s: timeout. waited for memory_map\n", __func__);
1890 ret = -EINVAL;
1891 goto fail_cmd;
1892 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1893 pr_err("%s: DSP returned error[%s]\n",
1894 __func__, adsp_err_get_err_str(
1895 atomic_read(&this_adm.adm_stat)));
1896 ret = adsp_err_get_lnx_err_code(
1897 atomic_read(&this_adm.adm_stat));
1898 goto fail_cmd;
1899 }
1900fail_cmd:
1901 kfree(mmap_region_cmd);
1902 return ret;
1903}
1904
1905static int adm_memory_unmap_regions(void)
1906{
1907 struct avs_cmd_shared_mem_unmap_regions unmap_regions;
1908 int ret = 0;
1909
1910 pr_debug("%s:\n", __func__);
1911 if (this_adm.apr == NULL) {
1912 pr_err("%s: APR handle NULL\n", __func__);
1913 return -EINVAL;
1914 }
1915
1916 unmap_regions.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1917 APR_HDR_LEN(APR_HDR_SIZE),
1918 APR_PKT_VER);
1919 unmap_regions.hdr.pkt_size = sizeof(unmap_regions);
1920 unmap_regions.hdr.src_port = 0;
1921 unmap_regions.hdr.dest_port = 0;
1922 unmap_regions.hdr.token = 0;
1923 unmap_regions.hdr.opcode = ADM_CMD_SHARED_MEM_UNMAP_REGIONS;
1924 unmap_regions.mem_map_handle = atomic_read(&this_adm.
1925 mem_map_handles[atomic_read(&this_adm.mem_map_index)]);
1926 atomic_set(&this_adm.adm_stat, -1);
1927 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &unmap_regions);
1928 if (ret < 0) {
1929 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1930 unmap_regions.hdr.opcode, ret);
1931 ret = -EINVAL;
1932 goto fail_cmd;
1933 }
1934
1935 ret = wait_event_timeout(this_adm.adm_wait,
1936 atomic_read(&this_adm.adm_stat) >= 0,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001937 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301938 if (!ret) {
1939 pr_err("%s: timeout. waited for memory_unmap\n",
1940 __func__);
1941 ret = -EINVAL;
1942 goto fail_cmd;
1943 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1944 pr_err("%s: DSP returned error[%s]\n",
1945 __func__, adsp_err_get_err_str(
1946 atomic_read(&this_adm.adm_stat)));
1947 ret = adsp_err_get_lnx_err_code(
1948 atomic_read(&this_adm.adm_stat));
1949 goto fail_cmd;
1950 } else {
1951 pr_debug("%s: Unmap handle 0x%x succeeded\n", __func__,
1952 unmap_regions.mem_map_handle);
1953 }
1954fail_cmd:
1955 return ret;
1956}
1957
1958static int remap_cal_data(struct cal_block_data *cal_block, int cal_index)
1959{
1960 int ret = 0;
1961
Banajit Goswami08bb7362017-11-03 22:48:23 -07001962 if (cal_block->map_data.dma_buf == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301963 pr_err("%s: No ION allocation for cal index %d!\n",
1964 __func__, cal_index);
1965 ret = -EINVAL;
1966 goto done;
1967 }
1968
1969 if ((cal_block->map_data.map_size > 0) &&
1970 (cal_block->map_data.q6map_handle == 0)) {
1971 atomic_set(&this_adm.mem_map_index, cal_index);
1972 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
1973 (uint32_t *)&cal_block->map_data.map_size, 1);
1974 if (ret < 0) {
1975 pr_err("%s: ADM mmap did not work! size = %zd ret %d\n",
1976 __func__,
1977 cal_block->map_data.map_size, ret);
1978 pr_debug("%s: ADM mmap did not work! addr = 0x%pK, size = %zd ret %d\n",
1979 __func__,
1980 &cal_block->cal_data.paddr,
1981 cal_block->map_data.map_size, ret);
1982 goto done;
1983 }
1984 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
1985 mem_map_handles[cal_index]);
1986 }
1987done:
1988 return ret;
1989}
1990
1991static void send_adm_custom_topology(void)
1992{
1993 struct cal_block_data *cal_block = NULL;
1994 struct cmd_set_topologies adm_top;
1995 int cal_index = ADM_CUSTOM_TOP_CAL;
1996 int result;
1997
1998 if (this_adm.cal_data[cal_index] == NULL)
1999 goto done;
2000
2001 mutex_lock(&this_adm.cal_data[cal_index]->lock);
2002 if (!this_adm.set_custom_topology)
2003 goto unlock;
2004 this_adm.set_custom_topology = 0;
2005
2006 cal_block = cal_utils_get_only_cal_block(this_adm.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002007 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302008 goto unlock;
2009
2010 pr_debug("%s: Sending cal_index %d\n", __func__, cal_index);
2011
2012 result = remap_cal_data(cal_block, cal_index);
2013 if (result) {
2014 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2015 __func__, cal_index);
2016 goto unlock;
2017 }
2018 atomic_set(&this_adm.mem_map_index, cal_index);
2019 atomic_set(&this_adm.mem_map_handles[cal_index],
2020 cal_block->map_data.q6map_handle);
2021
2022 if (cal_block->cal_data.size == 0) {
2023 pr_debug("%s: No ADM cal to send\n", __func__);
2024 goto unlock;
2025 }
2026
2027 adm_top.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2028 APR_HDR_LEN(20), APR_PKT_VER);
2029 adm_top.hdr.pkt_size = sizeof(adm_top);
2030 adm_top.hdr.src_svc = APR_SVC_ADM;
2031 adm_top.hdr.src_domain = APR_DOMAIN_APPS;
2032 adm_top.hdr.src_port = 0;
2033 adm_top.hdr.dest_svc = APR_SVC_ADM;
2034 adm_top.hdr.dest_domain = APR_DOMAIN_ADSP;
2035 adm_top.hdr.dest_port = 0;
2036 adm_top.hdr.token = 0;
2037 adm_top.hdr.opcode = ADM_CMD_ADD_TOPOLOGIES;
2038 adm_top.payload_addr_lsw = lower_32_bits(cal_block->cal_data.paddr);
2039 adm_top.payload_addr_msw = msm_audio_populate_upper_32_bits(
2040 cal_block->cal_data.paddr);
2041 adm_top.mem_map_handle = cal_block->map_data.q6map_handle;
2042 adm_top.payload_size = cal_block->cal_data.size;
2043
2044 atomic_set(&this_adm.adm_stat, -1);
2045 pr_debug("%s: Sending ADM_CMD_ADD_TOPOLOGIES payload = 0x%pK, size = %d\n",
2046 __func__, &cal_block->cal_data.paddr,
2047 adm_top.payload_size);
2048 result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_top);
2049 if (result < 0) {
2050 pr_err("%s: Set topologies failed payload size = %zd result %d\n",
2051 __func__, cal_block->cal_data.size, result);
2052 goto unlock;
2053 }
2054 /* Wait for the callback */
2055 result = wait_event_timeout(this_adm.adm_wait,
2056 atomic_read(&this_adm.adm_stat) >= 0,
2057 msecs_to_jiffies(TIMEOUT_MS));
2058 if (!result) {
2059 pr_err("%s: Set topologies timed out payload size = %zd\n",
2060 __func__, cal_block->cal_data.size);
2061 goto unlock;
2062 } else if (atomic_read(&this_adm.adm_stat) > 0) {
2063 pr_err("%s: DSP returned error[%s]\n",
2064 __func__, adsp_err_get_err_str(
2065 atomic_read(&this_adm.adm_stat)));
2066 result = adsp_err_get_lnx_err_code(
2067 atomic_read(&this_adm.adm_stat));
2068 goto unlock;
2069 }
2070unlock:
2071 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2072done:
2073 return;
2074}
2075
2076static int send_adm_cal_block(int port_id, int copp_idx,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002077 struct cal_block_data *cal_block, int perf_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302078{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002079 struct mem_mapping_hdr mem_hdr;
2080 int payload_size = 0;
2081 int port_idx = 0;
2082 int topology = 0;
2083 int result = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302084
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002085 pr_debug("%s: Port id 0x%x,\n", __func__, port_id);
2086
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302087 if (!cal_block) {
2088 pr_debug("%s: No ADM cal to send for port_id = 0x%x!\n",
2089 __func__, port_id);
2090 result = -EINVAL;
2091 goto done;
2092 }
2093 if (cal_block->cal_data.size <= 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002094 pr_debug("%s: No ADM cal sent for port_id = 0x%x!\n", __func__,
2095 port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302096 result = -EINVAL;
2097 goto done;
2098 }
2099
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002100 memset(&mem_hdr, 0, sizeof(mem_hdr));
2101 port_id = afe_convert_virtual_to_portid(port_id);
2102 port_idx = adm_validate_and_get_port_index(port_id);
2103 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
2104 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2105 return -EINVAL;
2106 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
2107 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
2108 return -EINVAL;
2109 }
2110
2111 topology = atomic_read(&this_adm.copp.topology[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302112 if (perf_mode == LEGACY_PCM_MODE &&
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002113 topology == DS2_ADM_COPP_TOPOLOGY_ID) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302114 pr_err("%s: perf_mode %d, topology 0x%x\n", __func__, perf_mode,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002115 topology);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302116 goto done;
2117 }
2118
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002119 mem_hdr.data_payload_addr_lsw =
2120 lower_32_bits(cal_block->cal_data.paddr);
2121 mem_hdr.data_payload_addr_msw =
2122 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
2123 mem_hdr.mem_map_handle = cal_block->map_data.q6map_handle;
2124 payload_size = cal_block->cal_data.size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302125
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002126 adm_set_pp_params(port_id, copp_idx, &mem_hdr, NULL, payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302127
2128done:
2129 return result;
2130}
2131
2132static struct cal_block_data *adm_find_cal_by_path(int cal_index, int path)
2133{
2134 struct list_head *ptr, *next;
2135 struct cal_block_data *cal_block = NULL;
2136 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2137 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2138
2139 pr_debug("%s:\n", __func__);
2140
2141 list_for_each_safe(ptr, next,
2142 &this_adm.cal_data[cal_index]->cal_blocks) {
2143
2144 cal_block = list_entry(ptr,
2145 struct cal_block_data, list);
2146
Vikram Panduranga770b8382017-09-27 12:17:36 -07002147 if (cal_utils_is_cal_stale(cal_block))
2148 continue;
2149
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302150 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002151 cal_index == ADM_LSM_AUDPROC_CAL ||
2152 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302153 audproc_cal_info = cal_block->cal_info;
2154 if ((audproc_cal_info->path == path) &&
2155 (cal_block->cal_data.size > 0))
2156 return cal_block;
2157 } else if (cal_index == ADM_AUDVOL_CAL) {
2158 audvol_cal_info = cal_block->cal_info;
2159 if ((audvol_cal_info->path == path) &&
2160 (cal_block->cal_data.size > 0))
2161 return cal_block;
2162 }
2163 }
2164 pr_debug("%s: Can't find ADM cal for cal_index %d, path %d\n",
2165 __func__, cal_index, path);
2166 return NULL;
2167}
2168
2169static struct cal_block_data *adm_find_cal_by_app_type(int cal_index, int path,
2170 int app_type)
2171{
2172 struct list_head *ptr, *next;
2173 struct cal_block_data *cal_block = NULL;
2174 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2175 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2176
2177 pr_debug("%s\n", __func__);
2178
2179 list_for_each_safe(ptr, next,
2180 &this_adm.cal_data[cal_index]->cal_blocks) {
2181
2182 cal_block = list_entry(ptr,
2183 struct cal_block_data, list);
2184
Vikram Panduranga770b8382017-09-27 12:17:36 -07002185 if (cal_utils_is_cal_stale(cal_block))
2186 continue;
2187
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302188 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002189 cal_index == ADM_LSM_AUDPROC_CAL ||
2190 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302191 audproc_cal_info = cal_block->cal_info;
2192 if ((audproc_cal_info->path == path) &&
2193 (audproc_cal_info->app_type == app_type) &&
2194 (cal_block->cal_data.size > 0))
2195 return cal_block;
2196 } else if (cal_index == ADM_AUDVOL_CAL) {
2197 audvol_cal_info = cal_block->cal_info;
2198 if ((audvol_cal_info->path == path) &&
2199 (audvol_cal_info->app_type == app_type) &&
2200 (cal_block->cal_data.size > 0))
2201 return cal_block;
2202 }
2203 }
2204 pr_debug("%s: Can't find ADM cali for cal_index %d, path %d, app %d, defaulting to search by path\n",
2205 __func__, cal_index, path, app_type);
2206 return adm_find_cal_by_path(cal_index, path);
2207}
2208
2209
2210static struct cal_block_data *adm_find_cal(int cal_index, int path,
2211 int app_type, int acdb_id,
2212 int sample_rate)
2213{
2214 struct list_head *ptr, *next;
2215 struct cal_block_data *cal_block = NULL;
2216 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2217 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2218
2219 pr_debug("%s:\n", __func__);
2220
2221 list_for_each_safe(ptr, next,
2222 &this_adm.cal_data[cal_index]->cal_blocks) {
2223
2224 cal_block = list_entry(ptr,
2225 struct cal_block_data, list);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002226 if (cal_utils_is_cal_stale(cal_block))
2227 continue;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302228
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302229 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002230 cal_index == ADM_LSM_AUDPROC_CAL ||
2231 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302232 audproc_cal_info = cal_block->cal_info;
2233 if ((audproc_cal_info->path == path) &&
2234 (audproc_cal_info->app_type == app_type) &&
2235 (audproc_cal_info->acdb_id == acdb_id) &&
2236 (audproc_cal_info->sample_rate == sample_rate) &&
2237 (cal_block->cal_data.size > 0))
2238 return cal_block;
2239 } else if (cal_index == ADM_AUDVOL_CAL) {
2240 audvol_cal_info = cal_block->cal_info;
2241 if ((audvol_cal_info->path == path) &&
2242 (audvol_cal_info->app_type == app_type) &&
2243 (audvol_cal_info->acdb_id == acdb_id) &&
2244 (cal_block->cal_data.size > 0))
2245 return cal_block;
2246 }
2247 }
2248 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",
2249 __func__, cal_index, path, app_type, acdb_id, sample_rate);
2250 return adm_find_cal_by_app_type(cal_index, path, app_type);
2251}
2252
2253static int adm_remap_and_send_cal_block(int cal_index, int port_id,
2254 int copp_idx, struct cal_block_data *cal_block, int perf_mode,
2255 int app_type, int acdb_id, int sample_rate)
2256{
2257 int ret = 0;
2258
2259 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
2260 ret = remap_cal_data(cal_block, cal_index);
2261 if (ret) {
2262 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2263 __func__, cal_index);
2264 goto done;
2265 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002266 ret = send_adm_cal_block(port_id, copp_idx, cal_block, perf_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302267 if (ret < 0)
2268 pr_debug("%s: No cal sent for cal_index %d, port_id = 0x%x! ret %d sample_rate %d\n",
2269 __func__, cal_index, port_id, ret, sample_rate);
2270done:
2271 return ret;
2272}
2273
2274static void send_adm_cal_type(int cal_index, int path, int port_id,
2275 int copp_idx, int perf_mode, int app_type,
2276 int acdb_id, int sample_rate)
2277{
2278 struct cal_block_data *cal_block = NULL;
2279 int ret;
2280
2281 pr_debug("%s: cal index %d\n", __func__, cal_index);
2282
2283 if (this_adm.cal_data[cal_index] == NULL) {
2284 pr_debug("%s: cal_index %d not allocated!\n",
2285 __func__, cal_index);
2286 goto done;
2287 }
2288
2289 mutex_lock(&this_adm.cal_data[cal_index]->lock);
2290 cal_block = adm_find_cal(cal_index, path, app_type, acdb_id,
2291 sample_rate);
2292 if (cal_block == NULL)
2293 goto unlock;
2294
2295 ret = adm_remap_and_send_cal_block(cal_index, port_id, copp_idx,
2296 cal_block, perf_mode, app_type, acdb_id, sample_rate);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002297
2298 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302299unlock:
2300 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2301done:
2302 return;
2303}
2304
2305static int get_cal_path(int path)
2306{
2307 if (path == 0x1)
2308 return RX_DEVICE;
2309 else
2310 return TX_DEVICE;
2311}
2312
2313static void send_adm_cal(int port_id, int copp_idx, int path, int perf_mode,
Aditya Bavanari5106b562018-01-08 13:16:32 +05302314 int app_type, int acdb_id, int sample_rate,
2315 int passthr_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302316{
2317 pr_debug("%s: port id 0x%x copp_idx %d\n", __func__, port_id, copp_idx);
2318
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002319 if (passthr_mode != LISTEN) {
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302320 send_adm_cal_type(ADM_AUDPROC_CAL, path, port_id, copp_idx,
2321 perf_mode, app_type, acdb_id, sample_rate);
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002322 } else {
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302323 send_adm_cal_type(ADM_LSM_AUDPROC_CAL, path, port_id, copp_idx,
2324 perf_mode, app_type, acdb_id, sample_rate);
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002325
2326 send_adm_cal_type(ADM_LSM_AUDPROC_PERSISTENT_CAL, path,
2327 port_id, copp_idx, perf_mode, app_type,
2328 acdb_id, sample_rate);
2329 }
2330
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302331 send_adm_cal_type(ADM_AUDVOL_CAL, path, port_id, copp_idx, perf_mode,
2332 app_type, acdb_id, sample_rate);
2333}
2334
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302335/**
2336 * adm_connect_afe_port -
2337 * command to send ADM connect AFE port
2338 *
2339 * @mode: value of mode for ADM connect AFE
2340 * @session_id: session active to connect
2341 * @port_id: Port ID number
2342 *
2343 * Returns 0 on success or error on failure
2344 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302345int adm_connect_afe_port(int mode, int session_id, int port_id)
2346{
2347 struct adm_cmd_connect_afe_port_v5 cmd;
2348 int ret = 0;
2349 int port_idx, copp_idx = 0;
2350
2351 pr_debug("%s: port_id: 0x%x session id:%d mode:%d\n", __func__,
2352 port_id, session_id, mode);
2353
2354 port_id = afe_convert_virtual_to_portid(port_id);
2355 port_idx = adm_validate_and_get_port_index(port_id);
2356 if (port_idx < 0) {
2357 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2358 return -EINVAL;
2359 }
2360
2361 if (this_adm.apr == NULL) {
2362 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
2363 0xFFFFFFFF, &this_adm);
2364 if (this_adm.apr == NULL) {
2365 pr_err("%s: Unable to register ADM\n", __func__);
2366 ret = -ENODEV;
2367 return ret;
2368 }
2369 rtac_set_adm_handle(this_adm.apr);
2370 }
2371 pr_debug("%s: Port ID 0x%x, index %d\n", __func__, port_id, port_idx);
2372
2373 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2374 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2375 cmd.hdr.pkt_size = sizeof(cmd);
2376 cmd.hdr.src_svc = APR_SVC_ADM;
2377 cmd.hdr.src_domain = APR_DOMAIN_APPS;
2378 cmd.hdr.src_port = port_id;
2379 cmd.hdr.dest_svc = APR_SVC_ADM;
2380 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
2381 cmd.hdr.dest_port = 0; /* Ignored */
2382 cmd.hdr.token = port_idx << 16 | copp_idx;
2383 cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V5;
2384
2385 cmd.mode = mode;
2386 cmd.session_id = session_id;
2387 cmd.afe_port_id = port_id;
2388
2389 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
2390 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
2391 if (ret < 0) {
2392 pr_err("%s: ADM enable for port_id: 0x%x failed ret %d\n",
2393 __func__, port_id, ret);
2394 ret = -EINVAL;
2395 goto fail_cmd;
2396 }
2397 /* Wait for the callback with copp id */
2398 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
2399 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
2400 msecs_to_jiffies(TIMEOUT_MS));
2401 if (!ret) {
2402 pr_err("%s: ADM connect timedout for port_id: 0x%x\n",
2403 __func__, port_id);
2404 ret = -EINVAL;
2405 goto fail_cmd;
2406 } else if (atomic_read(&this_adm.copp.stat
2407 [port_idx][copp_idx]) > 0) {
2408 pr_err("%s: DSP returned error[%s]\n",
2409 __func__, adsp_err_get_err_str(
2410 atomic_read(&this_adm.copp.stat
2411 [port_idx][copp_idx])));
2412 ret = adsp_err_get_lnx_err_code(
2413 atomic_read(&this_adm.copp.stat
2414 [port_idx][copp_idx]));
2415 goto fail_cmd;
2416 }
2417 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
2418 return 0;
2419
2420fail_cmd:
2421
2422 return ret;
2423}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302424EXPORT_SYMBOL(adm_connect_afe_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302425
2426int adm_arrange_mch_map(struct adm_cmd_device_open_v5 *open, int path,
Rohit kumar2054b692019-02-01 18:01:12 +05302427 int channel_mode, int port_idx)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302428{
2429 int rc = 0, idx;
2430
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -07002431 pr_debug("%s: channel mode %d", __func__, channel_mode);
2432
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302433 memset(open->dev_channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
2434 switch (path) {
2435 case ADM_PATH_PLAYBACK:
2436 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2437 break;
2438 case ADM_PATH_LIVE_REC:
2439 case ADM_PATH_NONLIVE_REC:
2440 idx = ADM_MCH_MAP_IDX_REC;
2441 break;
2442 default:
2443 goto non_mch_path;
2444 };
Rohit kumar2054b692019-02-01 18:01:12 +05302445
2446 if ((open->dev_num_channel > 2) &&
2447 (port_channel_map[port_idx].set_channel_map ||
2448 multi_ch_maps[idx].set_channel_map)) {
2449 if (port_channel_map[port_idx].set_channel_map)
2450 memcpy(open->dev_channel_mapping,
2451 port_channel_map[port_idx].channel_mapping,
2452 PCM_FORMAT_MAX_NUM_CHANNEL);
2453 else
2454 memcpy(open->dev_channel_mapping,
2455 multi_ch_maps[idx].channel_mapping,
2456 PCM_FORMAT_MAX_NUM_CHANNEL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302457 } else {
2458 if (channel_mode == 1) {
2459 open->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2460 } else if (channel_mode == 2) {
2461 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2462 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2463 } else if (channel_mode == 3) {
2464 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2465 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2466 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2467 } else if (channel_mode == 4) {
2468 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2469 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2470 open->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2471 open->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2472 } else if (channel_mode == 5) {
2473 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2474 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2475 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2476 open->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2477 open->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2478 } else if (channel_mode == 6) {
2479 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2480 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2481 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2482 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2483 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2484 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2485 } else if (channel_mode == 7) {
2486 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2487 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2488 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2489 open->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
2490 open->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2491 open->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2492 open->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2493 } else if (channel_mode == 8) {
2494 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2495 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2496 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2497 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2498 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2499 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2500 open->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2501 open->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2502 } else {
2503 pr_err("%s: invalid num_chan %d\n", __func__,
2504 channel_mode);
2505 rc = -EINVAL;
2506 goto inval_ch_mod;
2507 }
2508 }
2509
2510non_mch_path:
2511inval_ch_mod:
2512 return rc;
2513}
2514
2515int adm_arrange_mch_ep2_map(struct adm_cmd_device_open_v6 *open_v6,
2516 int channel_mode)
2517{
2518 int rc = 0;
2519
2520 memset(open_v6->dev_channel_mapping_eid2, 0,
2521 PCM_FORMAT_MAX_NUM_CHANNEL);
2522
2523 if (channel_mode == 1) {
2524 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FC;
2525 } else if (channel_mode == 2) {
2526 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2527 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2528 } else if (channel_mode == 3) {
2529 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2530 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2531 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2532 } else if (channel_mode == 4) {
2533 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2534 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2535 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LS;
2536 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_RS;
2537 } else if (channel_mode == 5) {
2538 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2539 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2540 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2541 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_LS;
2542 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_RS;
2543 } else if (channel_mode == 6) {
2544 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2545 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2546 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
2547 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2548 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2549 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2550 } else if (channel_mode == 8) {
2551 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2552 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2553 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
2554 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2555 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2556 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2557 open_v6->dev_channel_mapping_eid2[6] = PCM_CHANNEL_LB;
2558 open_v6->dev_channel_mapping_eid2[7] = PCM_CHANNEL_RB;
2559 } else {
2560 pr_err("%s: invalid num_chan %d\n", __func__,
2561 channel_mode);
2562 rc = -EINVAL;
2563 }
2564
2565 return rc;
2566}
2567
Dieter Luecking50c55352018-09-28 14:29:17 +02002568static int adm_arrange_mch_map_v8(
2569 struct adm_device_endpoint_payload *ep_payload,
Rohit kumar2054b692019-02-01 18:01:12 +05302570 int path, int channel_mode, int port_idx)
Dieter Luecking50c55352018-09-28 14:29:17 +02002571{
2572 int rc = 0, idx;
2573
2574 memset(ep_payload->dev_channel_mapping,
2575 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2576 switch (path) {
2577 case ADM_PATH_PLAYBACK:
2578 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2579 break;
2580 case ADM_PATH_LIVE_REC:
2581 case ADM_PATH_NONLIVE_REC:
2582 idx = ADM_MCH_MAP_IDX_REC;
2583 break;
2584 default:
2585 goto non_mch_path;
2586 };
2587
2588 if ((ep_payload->dev_num_channel > 2) &&
Rohit kumar2054b692019-02-01 18:01:12 +05302589 (port_channel_map[port_idx].set_channel_map ||
2590 multi_ch_maps[idx].set_channel_map)) {
2591 if (port_channel_map[port_idx].set_channel_map)
2592 memcpy(ep_payload->dev_channel_mapping,
2593 port_channel_map[port_idx].channel_mapping,
2594 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2595 else
2596 memcpy(ep_payload->dev_channel_mapping,
2597 multi_ch_maps[idx].channel_mapping,
2598 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Dieter Luecking50c55352018-09-28 14:29:17 +02002599 } else {
2600 if (channel_mode == 1) {
2601 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2602 } else if (channel_mode == 2) {
2603 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2604 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2605 } else if (channel_mode == 3) {
2606 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2607 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2608 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2609 } else if (channel_mode == 4) {
2610 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2611 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2612 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2613 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2614 } else if (channel_mode == 5) {
2615 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2616 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2617 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2618 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2619 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2620 } else if (channel_mode == 6) {
2621 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2622 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2623 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2624 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2625 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2626 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2627 } else if (channel_mode == 7) {
2628 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2629 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2630 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2631 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
2632 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2633 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2634 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2635 } else if (channel_mode == 8) {
2636 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2637 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2638 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2639 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2640 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2641 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2642 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2643 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2644 } else if (channel_mode == 10) {
2645 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2646 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2647 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2648 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2649 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2650 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2651 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2652 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2653 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2654 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2655 } else if (channel_mode == 12) {
2656 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2657 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2658 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2659 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2660 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2661 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2662 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2663 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2664 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2665 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2666 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2667 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
Chaithanya Krishna Bacharaju3dd8fdf2019-05-02 12:14:37 +05302668 } else if (channel_mode == 14) {
2669 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2670 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2671 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2672 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2673 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2674 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2675 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2676 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2677 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2678 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2679 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2680 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2681 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2682 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
Dieter Luecking50c55352018-09-28 14:29:17 +02002683 } else if (channel_mode == 16) {
2684 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2685 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2686 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2687 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2688 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2689 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2690 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2691 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2692 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2693 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2694 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2695 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2696 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2697 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2698 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2699 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
Cong Tang04a6cfa2019-02-26 15:08:55 +08002700 } else if (channel_mode == 32) {
2701 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2702 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2703 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2704 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2705 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2706 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2707 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2708 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2709 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
2710 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
2711 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2712 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2713 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2714 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2715 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2716 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
2717 ep_payload->dev_channel_mapping[16] = PCM_CHANNEL_LFE2;
2718 ep_payload->dev_channel_mapping[17] = PCM_CHANNEL_SL;
2719 ep_payload->dev_channel_mapping[18] = PCM_CHANNEL_SR;
2720 ep_payload->dev_channel_mapping[19] = PCM_CHANNEL_TFL;
2721 ep_payload->dev_channel_mapping[20] = PCM_CHANNEL_TFR;
2722 ep_payload->dev_channel_mapping[21] = PCM_CHANNEL_TC;
2723 ep_payload->dev_channel_mapping[22] = PCM_CHANNEL_TBL;
2724 ep_payload->dev_channel_mapping[23] = PCM_CHANNEL_TBR;
2725 ep_payload->dev_channel_mapping[24] = PCM_CHANNEL_TSL;
2726 ep_payload->dev_channel_mapping[25] = PCM_CHANNEL_TSR;
2727 ep_payload->dev_channel_mapping[26] = PCM_CHANNEL_TBC;
2728 ep_payload->dev_channel_mapping[27] = PCM_CHANNEL_BFC;
2729 ep_payload->dev_channel_mapping[28] = PCM_CHANNEL_BFL;
2730 ep_payload->dev_channel_mapping[29] = PCM_CHANNEL_BFR;
2731 ep_payload->dev_channel_mapping[30] = PCM_CHANNEL_LW;
2732 ep_payload->dev_channel_mapping[31] = PCM_CHANNEL_RW;
Dieter Luecking50c55352018-09-28 14:29:17 +02002733 } else {
2734 pr_err("%s: invalid num_chan %d\n", __func__,
2735 channel_mode);
2736 rc = -EINVAL;
2737 goto inval_ch_mod;
2738 }
2739 }
2740
2741non_mch_path:
2742inval_ch_mod:
2743 return rc;
2744}
2745
2746static int adm_arrange_mch_ep2_map_v8(
2747 struct adm_device_endpoint_payload *ep_payload,
2748 int channel_mode)
2749{
2750 int rc = 0;
2751
2752 memset(ep_payload->dev_channel_mapping, 0,
2753 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2754
2755 if (channel_mode == 1) {
2756 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2757 } else if (channel_mode == 2) {
2758 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2759 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2760 } else if (channel_mode == 3) {
2761 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2762 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2763 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2764 } else if (channel_mode == 4) {
2765 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2766 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2767 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2768 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2769 } else if (channel_mode == 5) {
2770 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2771 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2772 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2773 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2774 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2775 } else if (channel_mode == 6) {
2776 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2777 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2778 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2779 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2780 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2781 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2782 } else if (channel_mode == 8) {
2783 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2784 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2785 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2786 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2787 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2788 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2789 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2790 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2791 } else if (channel_mode == 10) {
2792 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2793 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2794 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2795 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2796 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2797 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2798 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2799 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2800 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
Ralf Herzfb81b6e2018-12-12 10:36:11 +01002801 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
Dieter Luecking50c55352018-09-28 14:29:17 +02002802 } else if (channel_mode == 12) {
2803 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2804 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2805 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2806 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2807 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2808 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2809 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2810 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2811 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2812 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2813 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2814 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2815 } else if (channel_mode == 16) {
2816 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2817 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2818 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2819 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2820 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2821 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2822 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2823 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2824 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
Ralf Herzfb81b6e2018-12-12 10:36:11 +01002825 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
Dieter Luecking50c55352018-09-28 14:29:17 +02002826 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2827 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2828 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2829 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2830 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2831 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
Cong Tang04a6cfa2019-02-26 15:08:55 +08002832 } else if (channel_mode == 32) {
2833 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2834 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2835 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2836 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2837 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2838 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2839 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2840 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2841 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
2842 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
2843 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2844 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2845 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2846 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2847 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2848 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
2849 ep_payload->dev_channel_mapping[16] = PCM_CHANNEL_LFE2;
2850 ep_payload->dev_channel_mapping[17] = PCM_CHANNEL_SL;
2851 ep_payload->dev_channel_mapping[18] = PCM_CHANNEL_SR;
2852 ep_payload->dev_channel_mapping[19] = PCM_CHANNEL_TFL;
2853 ep_payload->dev_channel_mapping[20] = PCM_CHANNEL_TFR;
2854 ep_payload->dev_channel_mapping[21] = PCM_CHANNEL_TC;
2855 ep_payload->dev_channel_mapping[22] = PCM_CHANNEL_TBL;
2856 ep_payload->dev_channel_mapping[23] = PCM_CHANNEL_TBR;
2857 ep_payload->dev_channel_mapping[24] = PCM_CHANNEL_TSL;
2858 ep_payload->dev_channel_mapping[25] = PCM_CHANNEL_TSR;
2859 ep_payload->dev_channel_mapping[26] = PCM_CHANNEL_TBC;
2860 ep_payload->dev_channel_mapping[27] = PCM_CHANNEL_BFC;
2861 ep_payload->dev_channel_mapping[28] = PCM_CHANNEL_BFL;
2862 ep_payload->dev_channel_mapping[29] = PCM_CHANNEL_BFR;
2863 ep_payload->dev_channel_mapping[30] = PCM_CHANNEL_LW;
2864 ep_payload->dev_channel_mapping[31] = PCM_CHANNEL_RW;
Dieter Luecking50c55352018-09-28 14:29:17 +02002865 } else {
2866 pr_err("%s: invalid num_chan %d\n", __func__,
2867 channel_mode);
2868 rc = -EINVAL;
2869 }
2870
2871 return rc;
2872}
Dhananjay Kumar43034392019-01-16 21:57:58 +05302873
2874static int adm_copp_set_ec_ref_mfc_cfg(int port_id, int copp_idx,
2875 int sample_rate, int bps,
2876 int in_channels, int out_channels)
2877{
2878 struct audproc_mfc_param_media_fmt mfc_cfg;
2879 struct param_hdr_v3 param_hdr;
2880 u16 *chmixer_params = NULL;
2881 int rc = 0, i = 0, j = 0, param_index = 0, param_size = 0;
2882 struct adm_device_endpoint_payload ep_payload = {0, 0, 0, {0}};
2883
2884 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
2885 memset(&ep_payload, 0, sizeof(ep_payload));
2886 memset(&param_hdr, 0, sizeof(param_hdr));
2887
2888 param_hdr.module_id = AUDPROC_MODULE_ID_MFC_EC_REF;
2889 param_hdr.instance_id = INSTANCE_ID_0;
2890
2891 pr_debug("%s: port_id %d copp_idx %d SR %d, BW %d in_ch %d out_ch %d\n",
2892 __func__, port_id, copp_idx, sample_rate,
2893 bps, in_channels, out_channels);
2894
Dhananjay Kumar3d61b362019-03-01 15:47:56 +05302895 if (out_channels <= 0 || out_channels > AUDPROC_MFC_OUT_CHANNELS_MAX) {
2896 pr_err("%s: unsupported out channels=%d\n", __func__, out_channels);
2897 return -EINVAL;
2898 }
2899
Dhananjay Kumar43034392019-01-16 21:57:58 +05302900 /* 1. Update Media Format */
2901 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
2902 param_hdr.param_size = sizeof(mfc_cfg);
2903
2904 mfc_cfg.sampling_rate = sample_rate;
2905 mfc_cfg.bits_per_sample = bps;
2906 mfc_cfg.num_channels = out_channels;
2907
2908 ep_payload.dev_num_channel = out_channels;
2909 rc = adm_arrange_mch_ep2_map_v8(&ep_payload, out_channels);
2910 if (rc < 0) {
2911 pr_err("%s: unable to get map for out channels=%d\n",
2912 __func__, out_channels);
2913 return -EINVAL;
2914 }
2915
2916 for (i = 0; i < out_channels; i++)
2917 mfc_cfg.channel_type[i] = (uint16_t) ep_payload.dev_channel_mapping[i];
2918
2919
2920 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx,
2921 param_hdr, (uint8_t *) &mfc_cfg);
2922 if (rc) {
2923 pr_err("%s: Failed to set media format, err %d\n", __func__, rc);
2924 return rc;
2925 }
2926
2927 /* 2. Send Channel Mixer params */
2928 param_size = 2 * (4 + out_channels + in_channels + (out_channels * in_channels));
2929 param_size = round_up(param_size, 4);
2930 param_hdr.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
2931 param_hdr.param_size = param_size;
2932
2933 pr_debug("%s: chmixer param sz = %d\n", __func__, param_size);
2934 chmixer_params = kzalloc(param_size, GFP_KERNEL);
2935 if (!chmixer_params) {
2936 return -ENOMEM;
2937 }
2938 param_index = 2; /* param[0] and [1] represents chmixer rule(always 0) */
2939 chmixer_params[param_index++] = out_channels;
2940 chmixer_params[param_index++] = in_channels;
2941
2942 /* output channel map is same as one set in media format */
2943 for (i = 0; i < out_channels; i++)
2944 chmixer_params[param_index++] = ep_payload.dev_channel_mapping[i];
2945
2946 /* input channel map should be same as one set for ep2 during copp open */
2947 ep_payload.dev_num_channel = in_channels;
2948 rc = adm_arrange_mch_ep2_map_v8(&ep_payload, in_channels);
2949 if (rc < 0) {
2950 pr_err("%s: unable to get in channal map\n", __func__);
2951 goto exit;
2952 }
2953 for (i = 0; i < in_channels; i++)
2954 chmixer_params[param_index++] = ep_payload.dev_channel_mapping[i];
2955
2956 for (i = 0; i < out_channels; i++)
2957 for (j = 0; j < in_channels; j++)
2958 chmixer_params[param_index++] = this_adm.ec_ref_chmixer_weights[i][j];
2959
2960 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx,
2961 param_hdr, (uint8_t *) chmixer_params);
2962 if (rc)
2963 pr_err("%s: Failed to set chmixer params, err %d\n", __func__, rc);
2964
2965exit:
2966 kfree(chmixer_params);
2967 return rc;
2968}
2969
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302970/**
2971 * adm_open -
2972 * command to send ADM open
2973 *
2974 * @port_id: port id number
2975 * @path: direction or ADM path type
2976 * @rate: sample rate of session
2977 * @channel_mode: number of channels set
2978 * @topology: topology active for this session
2979 * @perf_mode: performance mode like LL/ULL/..
2980 * @bit_width: bit width to set for copp
2981 * @app_type: App type used for this session
2982 * @acdb_id: ACDB ID of this device
Surendar Karkae7507512018-07-20 15:46:54 +05302983 * @session_type: type of session
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302984 *
2985 * Returns 0 on success or error on failure
2986 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302987int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
Surendar Karkae7507512018-07-20 15:46:54 +05302988 int perf_mode, uint16_t bit_width, int app_type, int acdb_id,
2989 int session_type)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302990{
2991 struct adm_cmd_device_open_v5 open;
2992 struct adm_cmd_device_open_v6 open_v6;
Dieter Luecking50c55352018-09-28 14:29:17 +02002993 struct adm_cmd_device_open_v8 open_v8;
2994 struct adm_device_endpoint_payload ep1_payload;
2995 struct adm_device_endpoint_payload ep2_payload;
2996 int ep1_payload_size = 0;
2997 int ep2_payload_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302998 int ret = 0;
Asish Bhattacharya34504582017-08-08 12:55:01 +05302999 int port_idx, flags;
3000 int copp_idx = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303001 int tmp_port = q6audio_get_port_id(port_id);
Dieter Luecking50c55352018-09-28 14:29:17 +02003002 void *adm_params = NULL;
3003 int param_size;
Dhananjay Kumar43034392019-01-16 21:57:58 +05303004 int num_ec_ref_rx_chans = this_adm.num_ec_ref_rx_chans;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303005
3006 pr_debug("%s:port %#x path:%d rate:%d mode:%d perf_mode:%d,topo_id %d\n",
3007 __func__, port_id, path, rate, channel_mode, perf_mode,
3008 topology);
3009
3010 port_id = q6audio_convert_virtual_to_portid(port_id);
3011 port_idx = adm_validate_and_get_port_index(port_id);
3012 if (port_idx < 0) {
3013 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
3014 return -EINVAL;
3015 }
Dieter Luecking50c55352018-09-28 14:29:17 +02003016 if (channel_mode < 0 || channel_mode > 32) {
3017 pr_err("%s: Invalid channel number 0x%x\n",
3018 __func__, channel_mode);
3019 return -EINVAL;
3020 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303021
3022 if (this_adm.apr == NULL) {
3023 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
3024 0xFFFFFFFF, &this_adm);
3025 if (this_adm.apr == NULL) {
3026 pr_err("%s: Unable to register ADM\n", __func__);
3027 return -ENODEV;
3028 }
3029 rtac_set_adm_handle(this_adm.apr);
3030 }
3031
3032 if (perf_mode == ULL_POST_PROCESSING_PCM_MODE) {
3033 flags = ADM_ULL_POST_PROCESSING_DEVICE_SESSION;
3034 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
3035 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
3036 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
3037 topology = DEFAULT_COPP_TOPOLOGY;
3038 } else if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
3039 flags = ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
3040 topology = NULL_COPP_TOPOLOGY;
3041 rate = ULL_SUPPORTED_SAMPLE_RATE;
3042 bit_width = ULL_SUPPORTED_BITS_PER_SAMPLE;
3043 } else if (perf_mode == LOW_LATENCY_PCM_MODE) {
3044 flags = ADM_LOW_LATENCY_DEVICE_SESSION;
3045 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
3046 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
3047 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
3048 topology = DEFAULT_COPP_TOPOLOGY;
3049 } else {
3050 if ((path == ADM_PATH_COMPRESSED_RX) ||
3051 (path == ADM_PATH_COMPRESSED_TX))
3052 flags = 0;
3053 else
3054 flags = ADM_LEGACY_DEVICE_SESSION;
3055 }
3056
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05303057 if ((topology == VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY) ||
kunleiz1529b552019-01-24 17:15:49 +08003058 (topology == VPM_TX_DM_FLUENCE_EF_COPP_TOPOLOGY)) {
3059 if ((rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_8K) &&
3060 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_16K) &&
3061 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_32K) &&
3062 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_48K))
Yunfei Zhangaf3faf22019-09-15 15:50:39 +08003063 rate = 16000;
3064 }
3065 if ((topology == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY) ||
3066 (topology == VPM_TX_DM_RFECNS_COPP_TOPOLOGY)) {
3067 if ((rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_8K) &&
3068 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_16K) &&
3069 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_32K))
3070 rate = 16000;
kunleiz1529b552019-01-24 17:15:49 +08003071 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303072
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08003073 if (topology == FFECNS_TOPOLOGY) {
3074 this_adm.ffecns_port_id = port_id;
3075 pr_debug("%s: ffecns port id =%x\n", __func__,
3076 this_adm.ffecns_port_id);
3077 }
3078
kunleizc0cd19e2018-10-18 17:11:35 +08003079 if (topology == VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY)
3080 channel_mode = 1;
3081
Asish Bhattacharya34504582017-08-08 12:55:01 +05303082 /*
3083 * Routing driver reuses the same adm for streams with the same
3084 * app_type, sample_rate etc.
3085 * This isn't allowed for ULL streams as per the DSP interface
3086 */
3087 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE)
3088 copp_idx = adm_get_idx_if_copp_exists(port_idx, topology,
3089 perf_mode,
3090 rate, bit_width,
Surendar Karkae7507512018-07-20 15:46:54 +05303091 app_type, session_type);
Asish Bhattacharya34504582017-08-08 12:55:01 +05303092
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303093 if (copp_idx < 0) {
3094 copp_idx = adm_get_next_available_copp(port_idx);
3095 if (copp_idx >= MAX_COPPS_PER_PORT) {
3096 pr_err("%s: exceeded copp id %d\n",
3097 __func__, copp_idx);
3098 return -EINVAL;
3099 }
3100 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
3101 atomic_set(&this_adm.copp.topology[port_idx][copp_idx],
3102 topology);
3103 atomic_set(&this_adm.copp.mode[port_idx][copp_idx],
3104 perf_mode);
3105 atomic_set(&this_adm.copp.rate[port_idx][copp_idx],
3106 rate);
3107 atomic_set(&this_adm.copp.channels[port_idx][copp_idx],
3108 channel_mode);
3109 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx],
3110 bit_width);
3111 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx],
3112 app_type);
3113 atomic_set(&this_adm.copp.acdb_id[port_idx][copp_idx],
3114 acdb_id);
Surendar Karkae7507512018-07-20 15:46:54 +05303115 atomic_set(&this_adm.copp.session_type[port_idx][copp_idx],
3116 session_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303117 set_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3118 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
3119 if ((path != ADM_PATH_COMPRESSED_RX) &&
3120 (path != ADM_PATH_COMPRESSED_TX))
3121 send_adm_custom_topology();
3122 }
3123
3124 if (this_adm.copp.adm_delay[port_idx][copp_idx] &&
3125 perf_mode == LEGACY_PCM_MODE) {
3126 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
3127 1);
3128 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
3129 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
3130 }
3131
3132 /* Create a COPP if port id are not enabled */
3133 if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) {
3134 pr_debug("%s: open ADM: port_idx: %d, copp_idx: %d\n", __func__,
3135 port_idx, copp_idx);
Dieter Luecking50c55352018-09-28 14:29:17 +02003136 if ((topology == SRS_TRUMEDIA_TOPOLOGY_ID) &&
3137 perf_mode == LEGACY_PCM_MODE) {
3138 int res;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303139
Dieter Luecking50c55352018-09-28 14:29:17 +02003140 atomic_set(&this_adm.mem_map_index, ADM_SRS_TRUMEDIA);
3141 msm_dts_srs_tm_ion_memmap(&this_adm.outband_memmap);
3142 res = adm_memory_map_regions(
3143 &this_adm.outband_memmap.paddr, 0,
3144 (uint32_t *)&this_adm.outband_memmap.size, 1);
3145 if (res < 0) {
3146 pr_err("%s: SRS adm_memory_map_regions failed! addr = 0x%pK, size = %d\n",
3147 __func__,
3148 (void *)this_adm.outband_memmap.paddr,
3149 (uint32_t)this_adm.outband_memmap.size);
3150 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303151 }
3152
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303153
Mangesh Kunchamwar9f295c72018-10-08 18:20:41 +05303154 if ((q6core_get_avcs_api_version_per_service(
Dieter Luecking50c55352018-09-28 14:29:17 +02003155 APRV2_IDS_SERVICE_ID_ADSP_ADM_V) >=
Dieter Luecking9fb7c8c2019-03-06 13:31:09 +01003156 ADSP_ADM_API_VERSION_V3)) {
Dieter Luecking50c55352018-09-28 14:29:17 +02003157 memset(&open_v8, 0, sizeof(open_v8));
3158 memset(&ep1_payload, 0, sizeof(ep1_payload));
3159 memset(&ep2_payload, 0, sizeof(ep2_payload));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303160
Dieter Luecking50c55352018-09-28 14:29:17 +02003161 open_v8.hdr.hdr_field = APR_HDR_FIELD(
3162 APR_MSG_TYPE_SEQ_CMD,
3163 APR_HDR_LEN(APR_HDR_SIZE),
3164 APR_PKT_VER);
3165 open_v8.hdr.src_svc = APR_SVC_ADM;
3166 open_v8.hdr.src_domain = APR_DOMAIN_APPS;
3167 open_v8.hdr.src_port = tmp_port;
3168 open_v8.hdr.dest_svc = APR_SVC_ADM;
3169 open_v8.hdr.dest_domain = APR_DOMAIN_ADSP;
3170 open_v8.hdr.dest_port = tmp_port;
3171 open_v8.hdr.token = port_idx << 16 | copp_idx;
3172 open_v8.hdr.opcode = ADM_CMD_DEVICE_OPEN_V8;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303173
Dieter Luecking50c55352018-09-28 14:29:17 +02003174 if (this_adm.native_mode != 0) {
3175 open_v8.flags = flags |
3176 (this_adm.native_mode << 11);
3177 this_adm.native_mode = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303178 } else {
Dieter Luecking50c55352018-09-28 14:29:17 +02003179 open_v8.flags = flags;
3180 }
3181 open_v8.mode_of_operation = path;
3182 open_v8.endpoint_id_1 = tmp_port;
3183 open_v8.endpoint_id_2 = 0xFFFF;
3184 open_v8.endpoint_id_3 = 0xFFFF;
3185
Chaithanya Krishna Bacharaju8b0abba2019-01-11 19:35:54 +05303186 if (((this_adm.ec_ref_rx & AFE_PORT_INVALID) !=
3187 AFE_PORT_INVALID) &&
3188 (path != ADM_PATH_PLAYBACK)) {
Surendar Karkade79a062018-12-05 14:18:55 +05303189 if (this_adm.num_ec_ref_rx_chans != 0) {
3190 open_v8.endpoint_id_2 =
3191 this_adm.ec_ref_rx;
Chaithanya Krishna Bacharaju757f0d22019-06-21 13:10:22 +05303192 this_adm.ec_ref_rx = AFE_PORT_INVALID;
Surendar Karkade79a062018-12-05 14:18:55 +05303193 } else {
3194 pr_err("%s: EC channels not set %d\n",
3195 __func__,
3196 this_adm.num_ec_ref_rx_chans);
3197 return -EINVAL;
3198 }
Dieter Luecking41620832018-11-14 15:11:47 +01003199 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303200
Dieter Luecking50c55352018-09-28 14:29:17 +02003201 open_v8.topology_id = topology;
3202 open_v8.reserved = 0;
3203
3204 /* variable endpoint payload */
3205 ep1_payload.dev_num_channel = channel_mode & 0x00FF;
3206 ep1_payload.bit_width = bit_width;
3207 ep1_payload.sample_rate = rate;
3208 ret = adm_arrange_mch_map_v8(&ep1_payload, path,
Rohit kumar2054b692019-02-01 18:01:12 +05303209 channel_mode, port_idx);
Dieter Luecking50c55352018-09-28 14:29:17 +02003210 if (ret)
3211 return ret;
3212
3213 pr_debug("%s: port_id=0x%x %x %x topology_id=0x%X flags %x ref_ch %x\n",
3214 __func__, open_v8.endpoint_id_1,
3215 open_v8.endpoint_id_2,
3216 open_v8.endpoint_id_3,
3217 open_v8.topology_id,
3218 open_v8.flags,
3219 this_adm.num_ec_ref_rx_chans);
3220
3221 ep1_payload_size = 8 +
3222 roundup(ep1_payload.dev_num_channel, 4);
3223 param_size = sizeof(struct adm_cmd_device_open_v8)
3224 + ep1_payload_size;
3225 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3226
Dieter Luecking27c57722018-10-05 16:45:41 +02003227 if ((this_adm.num_ec_ref_rx_chans != 0)
3228 && (path != ADM_PATH_PLAYBACK)
Dieter Luecking50c55352018-09-28 14:29:17 +02003229 && (open_v8.endpoint_id_2 != 0xFFFF)) {
3230 ep2_payload.dev_num_channel =
3231 this_adm.num_ec_ref_rx_chans;
Dieter Luecking50c55352018-09-28 14:29:17 +02003232
3233 if (this_adm.ec_ref_rx_bit_width != 0) {
3234 ep2_payload.bit_width =
3235 this_adm.ec_ref_rx_bit_width;
Dieter Luecking50c55352018-09-28 14:29:17 +02003236 } else {
3237 ep2_payload.bit_width = bit_width;
3238 }
3239
3240 if (this_adm.ec_ref_rx_sampling_rate != 0) {
3241 ep2_payload.sample_rate =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303242 this_adm.ec_ref_rx_sampling_rate;
Dieter Luecking50c55352018-09-28 14:29:17 +02003243 } else {
3244 ep2_payload.sample_rate = rate;
3245 }
3246
3247 pr_debug("%s: adm open_v8 eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
3248 __func__,
3249 ep2_payload.dev_num_channel,
3250 ep2_payload.bit_width,
3251 ep2_payload.sample_rate);
3252
3253 ret = adm_arrange_mch_ep2_map_v8(&ep2_payload,
3254 ep2_payload.dev_num_channel);
3255
3256 if (ret)
3257 return ret;
3258 ep2_payload_size = 8 +
3259 roundup(ep2_payload.dev_num_channel, 4);
3260 param_size += ep2_payload_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303261 }
3262
Dieter Luecking27c57722018-10-05 16:45:41 +02003263 open_v8.hdr.pkt_size = param_size;
Dieter Luecking50c55352018-09-28 14:29:17 +02003264 adm_params = kzalloc(param_size, GFP_KERNEL);
3265 if (!adm_params)
3266 return -ENOMEM;
Dieter Luecking50c55352018-09-28 14:29:17 +02003267 memcpy(adm_params, &open_v8, sizeof(open_v8));
3268 memcpy(adm_params + sizeof(open_v8),
3269 (void *)&ep1_payload,
3270 ep1_payload_size);
Dieter Luecking27c57722018-10-05 16:45:41 +02003271
3272 if ((this_adm.num_ec_ref_rx_chans != 0)
3273 && (path != ADM_PATH_PLAYBACK)
3274 && (open_v8.endpoint_id_2 != 0xFFFF)) {
Dieter Luecking41620832018-11-14 15:11:47 +01003275 this_adm.num_ec_ref_rx_chans = 0;
Dieter Luecking27c57722018-10-05 16:45:41 +02003276 memcpy(adm_params + sizeof(open_v8)
3277 + ep1_payload_size,
3278 (void *)&ep2_payload,
3279 ep2_payload_size);
3280 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303281
Dieter Luecking50c55352018-09-28 14:29:17 +02003282 ret = apr_send_pkt(this_adm.apr,
3283 (uint32_t *)adm_params);
3284 if (ret < 0) {
3285 pr_err("%s: port_id: 0x%x for[0x%x] failed %d for open_v8\n",
3286 __func__, tmp_port, port_id, ret);
3287 return -EINVAL;
3288 }
3289 kfree(adm_params);
3290 } else {
3291
3292 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3293 APR_HDR_LEN(APR_HDR_SIZE),
3294 APR_PKT_VER);
3295 open.hdr.pkt_size = sizeof(open);
3296 open.hdr.src_svc = APR_SVC_ADM;
3297 open.hdr.src_domain = APR_DOMAIN_APPS;
3298 open.hdr.src_port = tmp_port;
3299 open.hdr.dest_svc = APR_SVC_ADM;
3300 open.hdr.dest_domain = APR_DOMAIN_ADSP;
3301 open.hdr.dest_port = tmp_port;
3302 open.hdr.token = port_idx << 16 | copp_idx;
3303 open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
3304 open.flags = flags;
3305 open.mode_of_operation = path;
3306 open.endpoint_id_1 = tmp_port;
3307 open.endpoint_id_2 = 0xFFFF;
3308
Surendar Karkae7507512018-07-20 15:46:54 +05303309 if (this_adm.ec_ref_rx && (path != 1) &&
3310 (afe_get_port_type(tmp_port) == MSM_AFE_PORT_TYPE_TX)) {
Dieter Luecking50c55352018-09-28 14:29:17 +02003311 open.endpoint_id_2 = this_adm.ec_ref_rx;
Dieter Luecking50c55352018-09-28 14:29:17 +02003312 }
3313
3314 open.topology_id = topology;
3315
3316 open.dev_num_channel = channel_mode & 0x00FF;
3317 open.bit_width = bit_width;
3318 WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
3319 (rate != ULL_SUPPORTED_SAMPLE_RATE));
3320 open.sample_rate = rate;
3321
Rohit kumar2054b692019-02-01 18:01:12 +05303322 ret = adm_arrange_mch_map(&open, path, channel_mode,
3323 port_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303324 if (ret)
3325 return ret;
3326
Dieter Luecking50c55352018-09-28 14:29:17 +02003327 pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
3328 __func__, open.endpoint_id_1, open.sample_rate,
3329 open.topology_id);
3330
3331 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3332
3333 if ((this_adm.num_ec_ref_rx_chans != 0) &&
3334 (path != 1) && (open.endpoint_id_2 != 0xFFFF)) {
3335 memset(&open_v6, 0,
3336 sizeof(struct adm_cmd_device_open_v6));
3337 memcpy(&open_v6, &open,
3338 sizeof(struct adm_cmd_device_open_v5));
3339 open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
3340 open_v6.hdr.pkt_size = sizeof(open_v6);
3341 open_v6.dev_num_channel_eid2 =
3342 this_adm.num_ec_ref_rx_chans;
Dieter Luecking50c55352018-09-28 14:29:17 +02003343
3344 if (this_adm.ec_ref_rx_bit_width != 0) {
3345 open_v6.bit_width_eid2 =
3346 this_adm.ec_ref_rx_bit_width;
Dieter Luecking50c55352018-09-28 14:29:17 +02003347 } else {
3348 open_v6.bit_width_eid2 = bit_width;
3349 }
3350
3351 if (this_adm.ec_ref_rx_sampling_rate != 0) {
3352 open_v6.sample_rate_eid2 =
3353 this_adm.ec_ref_rx_sampling_rate;
Dieter Luecking50c55352018-09-28 14:29:17 +02003354 } else {
3355 open_v6.sample_rate_eid2 = rate;
3356 }
3357
3358 pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
3359 __func__, open_v6.dev_num_channel_eid2,
3360 open_v6.bit_width_eid2,
3361 open_v6.sample_rate_eid2);
3362
3363 ret = adm_arrange_mch_ep2_map(&open_v6,
3364 open_v6.dev_num_channel_eid2);
3365
3366 if (ret)
3367 return ret;
3368
3369 ret = apr_send_pkt(this_adm.apr,
3370 (uint32_t *)&open_v6);
3371 } else {
3372 ret = apr_send_pkt(this_adm.apr,
3373 (uint32_t *)&open);
3374 }
3375 if (ret < 0) {
3376 pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
3377 __func__, tmp_port, port_id, ret);
3378 return -EINVAL;
3379 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303380 }
Dieter Luecking50c55352018-09-28 14:29:17 +02003381
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303382 /* Wait for the callback with copp id */
3383 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3384 atomic_read(&this_adm.copp.stat
3385 [port_idx][copp_idx]) >= 0,
Xiaoyu Yec7d47162019-12-18 16:33:23 -08003386 msecs_to_jiffies(2 * TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303387 if (!ret) {
3388 pr_err("%s: ADM open timedout for port_id: 0x%x for [0x%x]\n",
3389 __func__, tmp_port, port_id);
3390 return -EINVAL;
3391 } else if (atomic_read(&this_adm.copp.stat
3392 [port_idx][copp_idx]) > 0) {
3393 pr_err("%s: DSP returned error[%s]\n",
3394 __func__, adsp_err_get_err_str(
3395 atomic_read(&this_adm.copp.stat
3396 [port_idx][copp_idx])));
3397 return adsp_err_get_lnx_err_code(
3398 atomic_read(&this_adm.copp.stat
3399 [port_idx][copp_idx]));
3400 }
3401 }
3402 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
Dhananjay Kumar43034392019-01-16 21:57:58 +05303403
3404 /*
3405 * Configure MFC(in ec_ref path) if chmixing param is applicable and set.
3406 * Except channels and channel maps the media format config for this module
3407 * should match with the COPP(EP1) config values.
3408 */
3409 if (path != ADM_PATH_PLAYBACK &&
3410 this_adm.num_ec_ref_rx_chans_downmixed != 0 &&
3411 num_ec_ref_rx_chans != this_adm.num_ec_ref_rx_chans_downmixed) {
3412 ret = adm_copp_set_ec_ref_mfc_cfg(port_id, copp_idx,
3413 rate, bit_width, num_ec_ref_rx_chans,
3414 this_adm.num_ec_ref_rx_chans_downmixed);
3415 this_adm.num_ec_ref_rx_chans_downmixed = 0;
3416 if (ret)
3417 pr_err("%s: set EC REF MFC cfg failed, err %d\n", __func__, ret);
3418 }
3419
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303420 return copp_idx;
3421}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303422EXPORT_SYMBOL(adm_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303423
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303424/**
3425 * adm_copp_mfc_cfg -
3426 * command to send ADM MFC config
3427 *
3428 * @port_id: Port ID number
3429 * @copp_idx: copp index assigned
3430 * @dst_sample_rate: sink sample rate
3431 *
3432 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303433void adm_copp_mfc_cfg(int port_id, int copp_idx, int dst_sample_rate)
3434{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003435 struct audproc_mfc_param_media_fmt mfc_cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303436 struct adm_cmd_device_open_v5 open;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003437 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303438 int port_idx;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303439 int rc = 0;
3440 int i = 0;
3441
3442 port_id = q6audio_convert_virtual_to_portid(port_id);
3443 port_idx = adm_validate_and_get_port_index(port_id);
3444
3445 if (port_idx < 0) {
3446 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
3447 goto fail_cmd;
3448 }
3449
3450 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
3451 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
3452 goto fail_cmd;
3453 }
3454
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003455 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
3456 memset(&open, 0, sizeof(open));
3457 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303458
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003459 param_hdr.module_id = AUDPROC_MODULE_ID_MFC;
3460 param_hdr.instance_id = INSTANCE_ID_0;
3461 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
3462 param_hdr.param_size = sizeof(mfc_cfg);
3463
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303464 mfc_cfg.sampling_rate = dst_sample_rate;
3465 mfc_cfg.bits_per_sample =
3466 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
3467 open.dev_num_channel = mfc_cfg.num_channels =
3468 atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
3469
3470 rc = adm_arrange_mch_map(&open, ADM_PATH_PLAYBACK,
Rohit kumar2054b692019-02-01 18:01:12 +05303471 mfc_cfg.num_channels, port_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303472 if (rc < 0) {
3473 pr_err("%s: unable to get channal map\n", __func__);
3474 goto fail_cmd;
3475 }
3476
3477 for (i = 0; i < mfc_cfg.num_channels; i++)
3478 mfc_cfg.channel_type[i] =
3479 (uint16_t) open.dev_channel_mapping[i];
3480
3481 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3482
3483 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",
3484 __func__, port_idx, copp_idx,
3485 atomic_read(&this_adm.copp.rate[port_idx][copp_idx]),
3486 mfc_cfg.bits_per_sample, mfc_cfg.num_channels,
3487 mfc_cfg.sampling_rate);
3488
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003489 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
3490 (uint8_t *) &mfc_cfg);
3491 if (rc)
3492 pr_err("%s: Failed to set media format configuration data, err %d\n",
3493 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303494
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303495fail_cmd:
3496 return;
3497}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303498EXPORT_SYMBOL(adm_copp_mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303499
3500static void route_set_opcode_matrix_id(
3501 struct adm_cmd_matrix_map_routings_v5 **route_addr,
3502 int path, uint32_t passthr_mode)
3503{
3504 struct adm_cmd_matrix_map_routings_v5 *route = *route_addr;
3505
3506 switch (path) {
3507 case ADM_PATH_PLAYBACK:
3508 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
3509 route->matrix_id = ADM_MATRIX_ID_AUDIO_RX;
3510 break;
3511 case ADM_PATH_LIVE_REC:
3512 if (passthr_mode == LISTEN) {
3513 route->hdr.opcode =
3514 ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3515 route->matrix_id = ADM_MATRIX_ID_LISTEN_TX;
3516 break;
3517 }
3518 /* fall through to set matrix id for non-listen case */
3519 case ADM_PATH_NONLIVE_REC:
3520 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
3521 route->matrix_id = ADM_MATRIX_ID_AUDIO_TX;
3522 break;
3523 case ADM_PATH_COMPRESSED_RX:
3524 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3525 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_RX;
3526 break;
3527 case ADM_PATH_COMPRESSED_TX:
3528 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3529 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_TX;
3530 break;
3531 default:
3532 pr_err("%s: Wrong path set[%d]\n", __func__, path);
3533 break;
3534 }
3535 pr_debug("%s: opcode 0x%x, matrix id %d\n",
3536 __func__, route->hdr.opcode, route->matrix_id);
3537}
3538
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303539/**
3540 * adm_matrix_map -
3541 * command to send ADM matrix map for ADM copp list
3542 *
3543 * @path: direction or ADM path type
3544 * @payload_map: have info of session id and associated copp_idx/num_copps
3545 * @perf_mode: performance mode like LL/ULL/..
3546 * @passthr_mode: flag to indicate passthrough mode
3547 *
3548 * Returns 0 on success or error on failure
3549 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303550int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode,
3551 uint32_t passthr_mode)
3552{
3553 struct adm_cmd_matrix_map_routings_v5 *route;
3554 struct adm_session_map_node_v5 *node;
3555 uint16_t *copps_list;
3556 int cmd_size = 0;
3557 int ret = 0, i = 0;
3558 void *payload = NULL;
3559 void *matrix_map = NULL;
3560 int port_idx, copp_idx;
3561
3562 /* Assumes port_ids have already been validated during adm_open */
3563 cmd_size = (sizeof(struct adm_cmd_matrix_map_routings_v5) +
3564 sizeof(struct adm_session_map_node_v5) +
3565 (sizeof(uint32_t) * payload_map.num_copps));
3566 matrix_map = kzalloc(cmd_size, GFP_KERNEL);
3567 if (matrix_map == NULL) {
3568 pr_err("%s: Mem alloc failed\n", __func__);
3569 ret = -EINVAL;
3570 return ret;
3571 }
3572 route = (struct adm_cmd_matrix_map_routings_v5 *)matrix_map;
3573
3574 route->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3575 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3576 route->hdr.pkt_size = cmd_size;
3577 route->hdr.src_svc = 0;
3578 route->hdr.src_domain = APR_DOMAIN_APPS;
3579 route->hdr.src_port = 0; /* Ignored */;
3580 route->hdr.dest_svc = APR_SVC_ADM;
3581 route->hdr.dest_domain = APR_DOMAIN_ADSP;
3582 route->hdr.dest_port = 0; /* Ignored */;
3583 route->hdr.token = 0;
3584 route->num_sessions = 1;
3585 route_set_opcode_matrix_id(&route, path, passthr_mode);
3586
3587 payload = ((u8 *)matrix_map +
3588 sizeof(struct adm_cmd_matrix_map_routings_v5));
3589 node = (struct adm_session_map_node_v5 *)payload;
3590
3591 node->session_id = payload_map.session_id;
3592 node->num_copps = payload_map.num_copps;
3593 payload = (u8 *)node + sizeof(struct adm_session_map_node_v5);
3594 copps_list = (uint16_t *)payload;
3595 for (i = 0; i < payload_map.num_copps; i++) {
3596 port_idx =
3597 adm_validate_and_get_port_index(payload_map.port_id[i]);
3598 if (port_idx < 0) {
3599 pr_err("%s: Invalid port_id 0x%x\n", __func__,
3600 payload_map.port_id[i]);
3601 ret = -EINVAL;
3602 goto fail_cmd;
3603 }
3604 copp_idx = payload_map.copp_idx[i];
3605 copps_list[i] = atomic_read(&this_adm.copp.id[port_idx]
3606 [copp_idx]);
3607 }
3608 atomic_set(&this_adm.matrix_map_stat, -1);
3609
3610 ret = apr_send_pkt(this_adm.apr, (uint32_t *)matrix_map);
3611 if (ret < 0) {
3612 pr_err("%s: routing for syream %d failed ret %d\n",
3613 __func__, payload_map.session_id, ret);
3614 ret = -EINVAL;
3615 goto fail_cmd;
3616 }
3617 ret = wait_event_timeout(this_adm.matrix_map_wait,
3618 atomic_read(&this_adm.matrix_map_stat) >= 0,
3619 msecs_to_jiffies(TIMEOUT_MS));
3620 if (!ret) {
3621 pr_err("%s: routing for syream %d failed\n", __func__,
3622 payload_map.session_id);
3623 ret = -EINVAL;
3624 goto fail_cmd;
3625 } else if (atomic_read(&this_adm.matrix_map_stat) > 0) {
3626 pr_err("%s: DSP returned error[%s]\n", __func__,
3627 adsp_err_get_err_str(atomic_read(
3628 &this_adm.matrix_map_stat)));
3629 ret = adsp_err_get_lnx_err_code(
3630 atomic_read(&this_adm.matrix_map_stat));
3631 goto fail_cmd;
3632 }
3633
3634 if ((perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) &&
3635 (path != ADM_PATH_COMPRESSED_RX)) {
3636 for (i = 0; i < payload_map.num_copps; i++) {
3637 port_idx = afe_get_port_index(payload_map.port_id[i]);
3638 copp_idx = payload_map.copp_idx[i];
3639 if (port_idx < 0 || copp_idx < 0 ||
3640 (copp_idx > MAX_COPPS_PER_PORT - 1)) {
3641 pr_err("%s: Invalid idx port_idx %d copp_idx %d\n",
3642 __func__, port_idx, copp_idx);
3643 continue;
3644 }
3645 rtac_add_adm_device(payload_map.port_id[i],
3646 atomic_read(&this_adm.copp.id
3647 [port_idx][copp_idx]),
3648 get_cal_path(path),
3649 payload_map.session_id,
3650 payload_map.app_type[i],
3651 payload_map.acdb_dev_id[i]);
3652
3653 if (!test_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3654 (void *)&this_adm.copp.adm_status[port_idx]
3655 [copp_idx])) {
3656 pr_debug("%s: adm copp[0x%x][%d] already sent",
3657 __func__, port_idx, copp_idx);
3658 continue;
3659 }
3660 send_adm_cal(payload_map.port_id[i], copp_idx,
3661 get_cal_path(path), perf_mode,
3662 payload_map.app_type[i],
3663 payload_map.acdb_dev_id[i],
Aditya Bavanari5106b562018-01-08 13:16:32 +05303664 payload_map.sample_rate[i],
3665 passthr_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303666 /* ADM COPP calibration is already sent */
3667 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3668 (void *)&this_adm.copp.
3669 adm_status[port_idx][copp_idx]);
3670 pr_debug("%s: copp_id: %d\n", __func__,
3671 atomic_read(&this_adm.copp.id[port_idx]
3672 [copp_idx]));
3673 }
3674 }
3675
3676fail_cmd:
3677 kfree(matrix_map);
3678 return ret;
3679}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303680EXPORT_SYMBOL(adm_matrix_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303681
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303682/**
3683 * adm_ec_ref_rx_id -
3684 * Update EC ref port ID
3685 *
3686 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303687void adm_ec_ref_rx_id(int port_id)
3688{
3689 this_adm.ec_ref_rx = port_id;
3690 pr_debug("%s: ec_ref_rx:%d\n", __func__, this_adm.ec_ref_rx);
3691}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303692EXPORT_SYMBOL(adm_ec_ref_rx_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303693
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303694/**
3695 * adm_num_ec_ref_rx_chans -
3696 * Update EC ref number of channels
3697 *
3698 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303699void adm_num_ec_ref_rx_chans(int num_chans)
3700{
3701 this_adm.num_ec_ref_rx_chans = num_chans;
3702 pr_debug("%s: num_ec_ref_rx_chans:%d\n",
3703 __func__, this_adm.num_ec_ref_rx_chans);
3704}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303705EXPORT_SYMBOL(adm_num_ec_ref_rx_chans);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303706
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303707/**
Dhananjay Kumar43034392019-01-16 21:57:58 +05303708 * adm_num_ec_rx_ref_chans_downmixed -
3709 * Update EC ref num of channels(downmixed) to be fed to EC algo
3710 *
3711 */
3712void adm_num_ec_ref_rx_chans_downmixed(int num_chans)
3713{
3714 this_adm.num_ec_ref_rx_chans_downmixed = num_chans;
3715 pr_debug("%s: num_ec_ref_rx_chans_downmixed:%d\n",
3716 __func__, this_adm.num_ec_ref_rx_chans_downmixed);
3717}
3718EXPORT_SYMBOL(adm_num_ec_ref_rx_chans_downmixed);
3719
3720/**
3721 * adm_ec_ref_chmixer_weights -
3722 * Update MFC(in ec ref) Channel Mixer Weights to be used
3723 * for downmixing rx channels before feeding them to EC algo
3724 * @out_channel_idx: index of output channel to which weightages are applicable
3725 * @weights: pointer to array having input weightages
3726 * @count: array sizeof pointer weights, max supported value is
3727 * PCM_FORMAT_MAX_NUM_CHANNEL_V8
3728 * Returns 0 on success or error on failure
3729 */
3730int adm_ec_ref_chmixer_weights(int out_channel_idx,
3731 uint16_t *weights, int count)
3732{
3733 int i = 0;
3734
3735 if (weights == NULL || count <= 0 || out_channel_idx < 0 ||
3736 count > PCM_FORMAT_MAX_NUM_CHANNEL_V8 ||
3737 out_channel_idx >= PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
3738 pr_err("%s: invalid weightages count(%d) ch_idx(%d)",
3739 __func__, count, out_channel_idx);
3740 return -EINVAL;
3741 }
3742
3743 for (i = 0; i < count; i++) {
3744 this_adm.ec_ref_chmixer_weights[out_channel_idx][i] = weights[i];
3745 pr_debug("%s: out ch idx :%d, weight[%d] = %d\n",
3746 __func__, out_channel_idx, i, weights[i]);
3747 }
3748
3749 return 0;
3750}
3751EXPORT_SYMBOL(adm_ec_ref_chmixer_weights);
3752
3753/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303754 * adm_ec_ref_rx_bit_width -
3755 * Update EC ref bit_width
3756 *
3757 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303758void adm_ec_ref_rx_bit_width(int bit_width)
3759{
3760 this_adm.ec_ref_rx_bit_width = bit_width;
3761 pr_debug("%s: ec_ref_rx_bit_width:%d\n",
3762 __func__, this_adm.ec_ref_rx_bit_width);
3763}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303764EXPORT_SYMBOL(adm_ec_ref_rx_bit_width);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303765
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303766/**
3767 * adm_ec_ref_rx_sampling_rate -
3768 * Update EC ref sample rate
3769 *
3770 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303771void adm_ec_ref_rx_sampling_rate(int sampling_rate)
3772{
3773 this_adm.ec_ref_rx_sampling_rate = sampling_rate;
3774 pr_debug("%s: ec_ref_rx_sampling_rate:%d\n",
3775 __func__, this_adm.ec_ref_rx_sampling_rate);
3776}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303777EXPORT_SYMBOL(adm_ec_ref_rx_sampling_rate);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303778
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303779/**
Dieter Luecking50c55352018-09-28 14:29:17 +02003780 * adm_set_native_mode -
3781 * Set adm channel native mode.
3782 * If enabled matrix mixer will be
3783 * running in native mode for channel
3784 * configuration for this device session.
3785 *
3786 */
3787void adm_set_native_mode(int mode)
3788{
3789 this_adm.native_mode = mode;
3790 pr_debug("%s: enable native_mode :%d\n",
3791 __func__, this_adm.native_mode);
3792}
3793EXPORT_SYMBOL(adm_set_native_mode);
3794
3795/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303796 * adm_close -
3797 * command to close ADM copp
3798 *
3799 * @port_id: Port ID number
3800 * @perf_mode: performance mode like LL/ULL/..
3801 * @copp_idx: copp index assigned
3802 *
3803 * Returns 0 on success or error on failure
3804 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303805int adm_close(int port_id, int perf_mode, int copp_idx)
3806{
3807 struct apr_hdr close;
3808
3809 int ret = 0, port_idx;
3810 int copp_id = RESET_COPP_ID;
3811
3812 pr_debug("%s: port_id=0x%x perf_mode: %d copp_idx: %d\n", __func__,
3813 port_id, perf_mode, copp_idx);
3814
3815 port_id = q6audio_convert_virtual_to_portid(port_id);
3816 port_idx = adm_validate_and_get_port_index(port_id);
3817 if (port_idx < 0) {
3818 pr_err("%s: Invalid port_id 0x%x\n",
3819 __func__, port_id);
3820 return -EINVAL;
3821 }
3822
3823 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
3824 pr_err("%s: Invalid copp idx: %d\n", __func__, copp_idx);
3825 return -EINVAL;
3826 }
3827
Rohit kumar2054b692019-02-01 18:01:12 +05303828 port_channel_map[port_idx].set_channel_map = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303829 if (this_adm.copp.adm_delay[port_idx][copp_idx] && perf_mode
3830 == LEGACY_PCM_MODE) {
3831 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
3832 1);
3833 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
3834 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
3835 }
3836
3837 atomic_dec(&this_adm.copp.cnt[port_idx][copp_idx]);
3838 if (!(atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]))) {
3839 copp_id = adm_get_copp_id(port_idx, copp_idx);
3840 pr_debug("%s: Closing ADM port_idx:%d copp_idx:%d copp_id:0x%x\n",
3841 __func__, port_idx, copp_idx, copp_id);
3842 if ((!perf_mode) && (this_adm.outband_memmap.paddr != 0) &&
3843 (atomic_read(&this_adm.copp.topology[port_idx][copp_idx]) ==
3844 SRS_TRUMEDIA_TOPOLOGY_ID)) {
3845 atomic_set(&this_adm.mem_map_index,
3846 ADM_SRS_TRUMEDIA);
3847 ret = adm_memory_unmap_regions();
3848 if (ret < 0) {
3849 pr_err("%s: adm mem unmmap err %d",
3850 __func__, ret);
3851 } else {
3852 atomic_set(&this_adm.mem_map_handles
3853 [ADM_SRS_TRUMEDIA], 0);
3854 }
3855 }
3856
3857
3858 if ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) &&
3859 this_adm.sourceTrackingData.memmap.paddr) {
3860 atomic_set(&this_adm.mem_map_index,
3861 ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
3862 ret = adm_memory_unmap_regions();
3863 if (ret < 0) {
3864 pr_err("%s: adm mem unmmap err %d",
3865 __func__, ret);
3866 }
3867 msm_audio_ion_free(
Banajit Goswami08bb7362017-11-03 22:48:23 -07003868 this_adm.sourceTrackingData.dma_buf);
3869 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303870 this_adm.sourceTrackingData.memmap.size = 0;
3871 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
3872 this_adm.sourceTrackingData.memmap.paddr = 0;
3873 this_adm.sourceTrackingData.apr_cmd_status = -1;
3874 atomic_set(&this_adm.mem_map_handles[
3875 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
3876 }
3877
3878 close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3879 APR_HDR_LEN(APR_HDR_SIZE),
3880 APR_PKT_VER);
3881 close.pkt_size = sizeof(close);
3882 close.src_svc = APR_SVC_ADM;
3883 close.src_domain = APR_DOMAIN_APPS;
3884 close.src_port = port_id;
3885 close.dest_svc = APR_SVC_ADM;
3886 close.dest_domain = APR_DOMAIN_ADSP;
3887 close.dest_port = copp_id;
3888 close.token = port_idx << 16 | copp_idx;
3889 close.opcode = ADM_CMD_DEVICE_CLOSE_V5;
3890
3891 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
3892 RESET_COPP_ID);
3893 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
3894 atomic_set(&this_adm.copp.topology[port_idx][copp_idx], 0);
3895 atomic_set(&this_adm.copp.mode[port_idx][copp_idx], 0);
3896 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3897 atomic_set(&this_adm.copp.rate[port_idx][copp_idx], 0);
3898 atomic_set(&this_adm.copp.channels[port_idx][copp_idx], 0);
3899 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx], 0);
3900 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx], 0);
Surendar Karkae7507512018-07-20 15:46:54 +05303901 atomic_set(&this_adm.copp.session_type[port_idx][copp_idx], 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303902
3903 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3904 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
3905
3906 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
3907 if (ret < 0) {
3908 pr_err("%s: ADM close failed %d\n", __func__, ret);
3909 return -EINVAL;
3910 }
3911
3912 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3913 atomic_read(&this_adm.copp.stat
3914 [port_idx][copp_idx]) >= 0,
3915 msecs_to_jiffies(TIMEOUT_MS));
3916 if (!ret) {
3917 pr_err("%s: ADM cmd Route timedout for port 0x%x\n",
3918 __func__, port_id);
3919 return -EINVAL;
3920 } else if (atomic_read(&this_adm.copp.stat
3921 [port_idx][copp_idx]) > 0) {
3922 pr_err("%s: DSP returned error[%s]\n",
3923 __func__, adsp_err_get_err_str(
3924 atomic_read(&this_adm.copp.stat
3925 [port_idx][copp_idx])));
3926 return adsp_err_get_lnx_err_code(
3927 atomic_read(&this_adm.copp.stat
3928 [port_idx][copp_idx]));
3929 }
3930 }
3931
3932 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
3933 pr_debug("%s: remove adm device from rtac\n", __func__);
3934 rtac_remove_adm_device(port_id, copp_id);
3935 }
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08003936
3937 if (port_id == this_adm.ffecns_port_id)
3938 this_adm.ffecns_port_id = -1;
3939
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303940 return 0;
3941}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303942EXPORT_SYMBOL(adm_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303943
3944int send_rtac_audvol_cal(void)
3945{
3946 int ret = 0;
3947 int ret2 = 0;
3948 int i = 0;
3949 int copp_idx, port_idx, acdb_id, app_id, path;
3950 struct cal_block_data *cal_block = NULL;
3951 struct audio_cal_info_audvol *audvol_cal_info = NULL;
3952 struct rtac_adm rtac_adm_data;
3953
3954 mutex_lock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
3955
3956 cal_block = cal_utils_get_only_cal_block(
3957 this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07003958 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303959 pr_err("%s: can't find cal block!\n", __func__);
3960 goto unlock;
3961 }
3962
3963 audvol_cal_info = cal_block->cal_info;
3964 if (audvol_cal_info == NULL) {
3965 pr_err("%s: audvol_cal_info is NULL!\n", __func__);
3966 goto unlock;
3967 }
3968
3969 get_rtac_adm_data(&rtac_adm_data);
3970 for (; i < rtac_adm_data.num_of_dev; i++) {
3971
3972 acdb_id = rtac_adm_data.device[i].acdb_dev_id;
3973 if (acdb_id == 0)
3974 acdb_id = audvol_cal_info->acdb_id;
3975
3976 app_id = rtac_adm_data.device[i].app_type;
3977 if (app_id == 0)
3978 app_id = audvol_cal_info->app_type;
3979
3980 path = afe_get_port_type(rtac_adm_data.device[i].afe_port);
3981 if ((acdb_id == audvol_cal_info->acdb_id) &&
3982 (app_id == audvol_cal_info->app_type) &&
3983 (path == audvol_cal_info->path)) {
3984
3985 if (adm_get_indexes_from_copp_id(rtac_adm_data.
3986 device[i].copp, &copp_idx, &port_idx) != 0) {
3987 pr_debug("%s: Copp Id %d is not active\n",
3988 __func__,
3989 rtac_adm_data.device[i].copp);
3990 continue;
3991 }
3992
3993 ret2 = adm_remap_and_send_cal_block(ADM_RTAC_AUDVOL_CAL,
3994 rtac_adm_data.device[i].afe_port,
3995 copp_idx, cal_block,
3996 atomic_read(&this_adm.copp.
3997 mode[port_idx][copp_idx]),
3998 audvol_cal_info->app_type,
3999 audvol_cal_info->acdb_id,
4000 atomic_read(&this_adm.copp.
4001 rate[port_idx][copp_idx]));
4002 if (ret2 < 0) {
4003 pr_debug("%s: remap and send failed for copp Id %d, acdb id %d, app type %d, path %d\n",
4004 __func__, rtac_adm_data.device[i].copp,
4005 audvol_cal_info->acdb_id,
4006 audvol_cal_info->app_type,
4007 audvol_cal_info->path);
4008 ret = ret2;
4009 }
4010 }
4011 }
4012unlock:
4013 mutex_unlock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
4014 return ret;
4015}
4016
4017int adm_map_rtac_block(struct rtac_cal_block_data *cal_block)
4018{
4019 int result = 0;
4020
4021 pr_debug("%s:\n", __func__);
4022
4023 if (cal_block == NULL) {
4024 pr_err("%s: cal_block is NULL!\n",
4025 __func__);
4026 result = -EINVAL;
4027 goto done;
4028 }
4029
4030 if (cal_block->cal_data.paddr == 0) {
4031 pr_debug("%s: No address to map!\n",
4032 __func__);
4033 result = -EINVAL;
4034 goto done;
4035 }
4036
4037 if (cal_block->map_data.map_size == 0) {
4038 pr_debug("%s: map size is 0!\n",
4039 __func__);
4040 result = -EINVAL;
4041 goto done;
4042 }
4043
4044 /* valid port ID needed for callback use primary I2S */
4045 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
4046 result = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
4047 &cal_block->map_data.map_size, 1);
4048 if (result < 0) {
4049 pr_err("%s: RTAC mmap did not work! size = %d result %d\n",
4050 __func__,
4051 cal_block->map_data.map_size, result);
4052 pr_debug("%s: RTAC mmap did not work! addr = 0x%pK, size = %d\n",
4053 __func__,
4054 &cal_block->cal_data.paddr,
4055 cal_block->map_data.map_size);
4056 goto done;
4057 }
4058
4059 cal_block->map_data.map_handle = atomic_read(
4060 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]);
4061done:
4062 return result;
4063}
4064
4065int adm_unmap_rtac_block(uint32_t *mem_map_handle)
4066{
4067 int result = 0;
4068
4069 pr_debug("%s:\n", __func__);
4070
4071 if (mem_map_handle == NULL) {
4072 pr_debug("%s: Map handle is NULL, nothing to unmap\n",
4073 __func__);
4074 goto done;
4075 }
4076
4077 if (*mem_map_handle == 0) {
4078 pr_debug("%s: Map handle is 0, nothing to unmap\n",
4079 __func__);
4080 goto done;
4081 }
4082
4083 if (*mem_map_handle != atomic_read(
4084 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL])) {
4085 pr_err("%s: Map handles do not match! Unmapping RTAC, RTAC map 0x%x, ADM map 0x%x\n",
4086 __func__, *mem_map_handle, atomic_read(
4087 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]));
4088
4089 /* if mismatch use handle passed in to unmap */
4090 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL],
4091 *mem_map_handle);
4092 }
4093
4094 /* valid port ID needed for callback use primary I2S */
4095 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
4096 result = adm_memory_unmap_regions();
4097 if (result < 0) {
4098 pr_debug("%s: adm_memory_unmap_regions failed, error %d\n",
4099 __func__, result);
4100 } else {
4101 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL], 0);
4102 *mem_map_handle = 0;
4103 }
4104done:
4105 return result;
4106}
4107
4108static int get_cal_type_index(int32_t cal_type)
4109{
4110 int ret = -EINVAL;
4111
4112 switch (cal_type) {
4113 case ADM_AUDPROC_CAL_TYPE:
4114 ret = ADM_AUDPROC_CAL;
4115 break;
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304116 case ADM_LSM_AUDPROC_CAL_TYPE:
4117 ret = ADM_LSM_AUDPROC_CAL;
4118 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304119 case ADM_AUDVOL_CAL_TYPE:
4120 ret = ADM_AUDVOL_CAL;
4121 break;
4122 case ADM_CUST_TOPOLOGY_CAL_TYPE:
4123 ret = ADM_CUSTOM_TOP_CAL;
4124 break;
4125 case ADM_RTAC_INFO_CAL_TYPE:
4126 ret = ADM_RTAC_INFO_CAL;
4127 break;
4128 case ADM_RTAC_APR_CAL_TYPE:
4129 ret = ADM_RTAC_APR_CAL;
4130 break;
4131 case ADM_RTAC_AUDVOL_CAL_TYPE:
4132 ret = ADM_RTAC_AUDVOL_CAL;
4133 break;
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004134 case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
4135 ret = ADM_LSM_AUDPROC_PERSISTENT_CAL;
4136 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304137 default:
4138 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
4139 }
4140 return ret;
4141}
4142
4143static int adm_alloc_cal(int32_t cal_type, size_t data_size, void *data)
4144{
4145 int ret = 0;
4146 int cal_index;
4147
4148 pr_debug("%s:\n", __func__);
4149
4150 cal_index = get_cal_type_index(cal_type);
4151 if (cal_index < 0) {
4152 pr_err("%s: could not get cal index %d!\n",
4153 __func__, cal_index);
4154 ret = -EINVAL;
4155 goto done;
4156 }
4157
4158 ret = cal_utils_alloc_cal(data_size, data,
4159 this_adm.cal_data[cal_index], 0, NULL);
4160 if (ret < 0) {
4161 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
4162 __func__, ret, cal_type);
4163 ret = -EINVAL;
4164 goto done;
4165 }
4166done:
4167 return ret;
4168}
4169
4170static int adm_dealloc_cal(int32_t cal_type, size_t data_size, void *data)
4171{
4172 int ret = 0;
4173 int cal_index;
4174
4175 pr_debug("%s:\n", __func__);
4176
4177 cal_index = get_cal_type_index(cal_type);
4178 if (cal_index < 0) {
4179 pr_err("%s: could not get cal index %d!\n",
4180 __func__, cal_index);
4181 ret = -EINVAL;
4182 goto done;
4183 }
4184
4185 ret = cal_utils_dealloc_cal(data_size, data,
4186 this_adm.cal_data[cal_index]);
4187 if (ret < 0) {
4188 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
4189 __func__, ret, cal_type);
4190 ret = -EINVAL;
4191 goto done;
4192 }
4193done:
4194 return ret;
4195}
4196
4197static int adm_set_cal(int32_t cal_type, size_t data_size, void *data)
4198{
4199 int ret = 0;
4200 int cal_index;
4201
4202 pr_debug("%s:\n", __func__);
4203
4204 cal_index = get_cal_type_index(cal_type);
4205 if (cal_index < 0) {
4206 pr_err("%s: could not get cal index %d!\n",
4207 __func__, cal_index);
4208 ret = -EINVAL;
4209 goto done;
4210 }
4211
4212 ret = cal_utils_set_cal(data_size, data,
4213 this_adm.cal_data[cal_index], 0, NULL);
4214 if (ret < 0) {
4215 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
4216 __func__, ret, cal_type);
4217 ret = -EINVAL;
4218 goto done;
4219 }
4220
4221 if (cal_index == ADM_CUSTOM_TOP_CAL) {
4222 mutex_lock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
4223 this_adm.set_custom_topology = 1;
4224 mutex_unlock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
4225 } else if (cal_index == ADM_RTAC_AUDVOL_CAL) {
4226 send_rtac_audvol_cal();
4227 }
4228done:
4229 return ret;
4230}
4231
4232static int adm_map_cal_data(int32_t cal_type,
4233 struct cal_block_data *cal_block)
4234{
4235 int ret = 0;
4236 int cal_index;
4237
4238 pr_debug("%s:\n", __func__);
4239
4240 cal_index = get_cal_type_index(cal_type);
4241 if (cal_index < 0) {
4242 pr_err("%s: could not get cal index %d!\n",
4243 __func__, cal_index);
4244 ret = -EINVAL;
4245 goto done;
4246 }
4247
4248 atomic_set(&this_adm.mem_map_index, cal_index);
4249 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
4250 (uint32_t *)&cal_block->map_data.map_size, 1);
4251 if (ret < 0) {
4252 pr_err("%s: map did not work! cal_type %i ret %d\n",
4253 __func__, cal_index, ret);
4254 ret = -ENODEV;
4255 goto done;
4256 }
4257 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
4258 mem_map_handles[cal_index]);
4259done:
4260 return ret;
4261}
4262
4263static int adm_unmap_cal_data(int32_t cal_type,
4264 struct cal_block_data *cal_block)
4265{
4266 int ret = 0;
4267 int cal_index;
4268
4269 pr_debug("%s:\n", __func__);
4270
4271 cal_index = get_cal_type_index(cal_type);
4272 if (cal_index < 0) {
4273 pr_err("%s: could not get cal index %d!\n",
4274 __func__, cal_index);
4275 ret = -EINVAL;
4276 goto done;
4277 }
4278
4279 if (cal_block == NULL) {
4280 pr_err("%s: Cal block is NULL!\n",
4281 __func__);
4282 goto done;
4283 }
4284
4285 if (cal_block->map_data.q6map_handle == 0) {
4286 pr_err("%s: Map handle is NULL, nothing to unmap\n",
4287 __func__);
4288 goto done;
4289 }
4290
4291 atomic_set(&this_adm.mem_map_handles[cal_index],
4292 cal_block->map_data.q6map_handle);
4293 atomic_set(&this_adm.mem_map_index, cal_index);
4294 ret = adm_memory_unmap_regions();
4295 if (ret < 0) {
4296 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
4297 __func__, cal_index, ret);
4298 ret = -ENODEV;
4299 goto done;
4300 }
4301 cal_block->map_data.q6map_handle = 0;
4302done:
4303 return ret;
4304}
4305
4306static void adm_delete_cal_data(void)
4307{
4308 pr_debug("%s:\n", __func__);
4309
4310 cal_utils_destroy_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data);
4311}
4312
4313static int adm_init_cal_data(void)
4314{
4315 int ret = 0;
4316 struct cal_type_info cal_type_info[] = {
4317 {{ADM_CUST_TOPOLOGY_CAL_TYPE,
4318 {adm_alloc_cal, adm_dealloc_cal, NULL,
4319 adm_set_cal, NULL, NULL} },
4320 {adm_map_cal_data, adm_unmap_cal_data,
4321 cal_utils_match_buf_num} },
4322
4323 {{ADM_AUDPROC_CAL_TYPE,
4324 {adm_alloc_cal, adm_dealloc_cal, NULL,
4325 adm_set_cal, NULL, NULL} },
4326 {adm_map_cal_data, adm_unmap_cal_data,
4327 cal_utils_match_buf_num} },
4328
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304329 {{ADM_LSM_AUDPROC_CAL_TYPE,
4330 {adm_alloc_cal, adm_dealloc_cal, NULL,
4331 adm_set_cal, NULL, NULL} },
4332 {adm_map_cal_data, adm_unmap_cal_data,
4333 cal_utils_match_buf_num} },
4334
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304335 {{ADM_AUDVOL_CAL_TYPE,
4336 {adm_alloc_cal, adm_dealloc_cal, NULL,
4337 adm_set_cal, NULL, NULL} },
4338 {adm_map_cal_data, adm_unmap_cal_data,
4339 cal_utils_match_buf_num} },
4340
4341 {{ADM_RTAC_INFO_CAL_TYPE,
4342 {NULL, NULL, NULL, NULL, NULL, NULL} },
4343 {NULL, NULL, cal_utils_match_buf_num} },
4344
4345 {{ADM_RTAC_APR_CAL_TYPE,
4346 {NULL, NULL, NULL, NULL, NULL, NULL} },
4347 {NULL, NULL, cal_utils_match_buf_num} },
4348
4349 {{SRS_TRUMEDIA_CAL_TYPE,
4350 {NULL, NULL, NULL, NULL, NULL, NULL} },
4351 {NULL, NULL, cal_utils_match_buf_num} },
4352
4353 {{ADM_RTAC_AUDVOL_CAL_TYPE,
4354 {adm_alloc_cal, adm_dealloc_cal, NULL,
4355 adm_set_cal, NULL, NULL} },
4356 {adm_map_cal_data, adm_unmap_cal_data,
4357 cal_utils_match_buf_num} },
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004358
4359 {{ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE,
4360 {adm_alloc_cal, adm_dealloc_cal, NULL,
4361 adm_set_cal, NULL, NULL} },
4362 {adm_map_cal_data, adm_unmap_cal_data,
4363 cal_utils_match_buf_num} },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304364 };
4365 pr_debug("%s:\n", __func__);
4366
4367 ret = cal_utils_create_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data,
4368 cal_type_info);
4369 if (ret < 0) {
4370 pr_err("%s: could not create cal type! ret %d\n",
4371 __func__, ret);
4372 ret = -EINVAL;
4373 goto err;
4374 }
4375
4376 return ret;
4377err:
4378 adm_delete_cal_data();
4379 return ret;
4380}
4381
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304382/**
4383 * adm_set_volume -
4384 * command to set volume on ADM copp
4385 *
4386 * @port_id: Port ID number
4387 * @copp_idx: copp index assigned
4388 * @volume: gain value to set
4389 *
4390 * Returns 0 on success or error on failure
4391 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304392int adm_set_volume(int port_id, int copp_idx, int volume)
4393{
4394 struct audproc_volume_ctrl_master_gain audproc_vol;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004395 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304396 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304397
4398 pr_debug("%s: port_id %d, volume %d\n", __func__, port_id, volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304399
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004400 memset(&audproc_vol, 0, sizeof(audproc_vol));
4401 memset(&param_hdr, 0, sizeof(param_hdr));
4402 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
4403 param_hdr.instance_id = INSTANCE_ID_0;
4404 param_hdr.param_id = AUDPROC_PARAM_ID_VOL_CTRL_MASTER_GAIN;
4405 param_hdr.param_size = sizeof(audproc_vol);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304406
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304407 audproc_vol.master_gain = volume;
4408
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004409 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4410 (uint8_t *) &audproc_vol);
4411 if (rc)
4412 pr_err("%s: Failed to set volume, err %d\n", __func__, rc);
4413
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304414 return rc;
4415}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304416EXPORT_SYMBOL(adm_set_volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304417
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304418/**
4419 * adm_set_softvolume -
4420 * command to set softvolume
4421 *
4422 * @port_id: Port ID number
4423 * @copp_idx: copp index assigned
4424 * @softvol_param: Params to set for softvolume
4425 *
4426 * Returns 0 on success or error on failure
4427 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304428int adm_set_softvolume(int port_id, int copp_idx,
4429 struct audproc_softvolume_params *softvol_param)
4430{
4431 struct audproc_soft_step_volume_params audproc_softvol;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004432 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304433 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304434
4435 pr_debug("%s: period %d step %d curve %d\n", __func__,
4436 softvol_param->period, softvol_param->step,
4437 softvol_param->rampingcurve);
4438
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004439 memset(&audproc_softvol, 0, sizeof(audproc_softvol));
4440 memset(&param_hdr, 0, sizeof(param_hdr));
4441 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
4442 param_hdr.instance_id = INSTANCE_ID_0;
4443 param_hdr.param_id = AUDPROC_PARAM_ID_SOFT_VOL_STEPPING_PARAMETERS;
4444 param_hdr.param_size = sizeof(audproc_softvol);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304445
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304446 audproc_softvol.period = softvol_param->period;
4447 audproc_softvol.step = softvol_param->step;
4448 audproc_softvol.ramping_curve = softvol_param->rampingcurve;
4449
4450 pr_debug("%s: period %d, step %d, curve %d\n", __func__,
4451 audproc_softvol.period, audproc_softvol.step,
4452 audproc_softvol.ramping_curve);
4453
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004454 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4455 (uint8_t *) &audproc_softvol);
4456 if (rc)
4457 pr_err("%s: Failed to set soft volume, err %d\n", __func__, rc);
4458
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304459 return rc;
4460}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304461EXPORT_SYMBOL(adm_set_softvolume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304462
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304463/**
4464 * adm_set_mic_gain -
4465 * command to set MIC gain
4466 *
4467 * @port_id: Port ID number
4468 * @copp_idx: copp index assigned
4469 * @volume: gain value to set
4470 *
4471 * Returns 0 on success or error on failure
4472 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304473int adm_set_mic_gain(int port_id, int copp_idx, int volume)
4474{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004475 struct admx_mic_gain mic_gain_params;
4476 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304477 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304478
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004479 pr_debug("%s: Setting mic gain to %d at port_id 0x%x\n", __func__,
4480 volume, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304481
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004482 memset(&mic_gain_params, 0, sizeof(mic_gain_params));
4483 memset(&param_hdr, 0, sizeof(param_hdr));
4484 param_hdr.module_id = ADM_MODULE_IDX_MIC_GAIN_CTRL;
4485 param_hdr.instance_id = INSTANCE_ID_0;
4486 param_hdr.param_id = ADM_PARAM_IDX_MIC_GAIN;
4487 param_hdr.param_size = sizeof(mic_gain_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304488
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004489 mic_gain_params.tx_mic_gain = volume;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304490
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004491 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4492 (uint8_t *) &mic_gain_params);
4493 if (rc)
4494 pr_err("%s: Failed to set mic gain, err %d\n", __func__, rc);
4495
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304496 return rc;
4497}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304498EXPORT_SYMBOL(adm_set_mic_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304499
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304500/**
4501 * adm_send_set_multichannel_ec_primary_mic_ch -
4502 * command to set multi-ch EC primary mic
4503 *
4504 * @port_id: Port ID number
4505 * @copp_idx: copp index assigned
4506 * @primary_mic_ch: channel number of primary mic
4507 *
4508 * Returns 0 on success or error on failure
4509 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304510int adm_send_set_multichannel_ec_primary_mic_ch(int port_id, int copp_idx,
4511 int primary_mic_ch)
4512{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004513 struct admx_sec_primary_mic_ch sec_primary_ch_params;
4514 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304515 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304516
4517 pr_debug("%s port_id 0x%x, copp_idx 0x%x, primary_mic_ch %d\n",
4518 __func__, port_id, copp_idx, primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304519
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004520 memset(&sec_primary_ch_params, 0, sizeof(sec_primary_ch_params));
4521 memset(&param_hdr, 0, sizeof(param_hdr));
4522 param_hdr.module_id = AUDPROC_MODULE_ID_VOICE_TX_SECNS;
4523 param_hdr.instance_id = INSTANCE_ID_0;
4524 param_hdr.param_id = AUDPROC_PARAM_IDX_SEC_PRIMARY_MIC_CH;
4525 param_hdr.param_size = sizeof(sec_primary_ch_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304526
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004527 sec_primary_ch_params.version = 0;
4528 sec_primary_ch_params.sec_primary_mic_ch = primary_mic_ch;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304529
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004530 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4531 (uint8_t *) &sec_primary_ch_params);
4532 if (rc)
4533 pr_err("%s: Failed to set primary mic chanel, err %d\n",
4534 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304535
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304536 return rc;
4537}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304538EXPORT_SYMBOL(adm_send_set_multichannel_ec_primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304539
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304540/**
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08004541 * adm_set_ffecns_effect -
4542 * command to set effect for ffecns module
4543 *
4544 * @effect: effect payload
4545 *
4546 * Returns 0 on success or error on failure
4547 */
4548int adm_set_ffecns_effect(int effect)
4549{
4550 struct ffecns_effect ffecns_params;
4551 struct param_hdr_v3 param_hdr;
4552 int rc = 0;
4553 int copp_idx = 0;
4554
4555 copp_idx = adm_get_default_copp_idx(this_adm.ffecns_port_id);
4556 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
4557 pr_err("%s, no active copp to query rms copp_idx:%d\n",
4558 __func__, copp_idx);
4559 return -EINVAL;
4560 }
4561
4562 memset(&ffecns_params, 0, sizeof(ffecns_params));
4563 memset(&param_hdr, 0, sizeof(param_hdr));
4564
4565 param_hdr.module_id = FFECNS_MODULE_ID;
4566 param_hdr.instance_id = INSTANCE_ID_0;
4567 param_hdr.param_id = FLUENCE_CMN_GLOBAL_EFFECT_PARAM_ID;
4568 param_hdr.param_size = sizeof(ffecns_params);
4569
4570 ffecns_params.payload = effect;
4571
4572 rc = adm_pack_and_set_one_pp_param(this_adm.ffecns_port_id, copp_idx,
4573 param_hdr, (uint8_t *) &ffecns_params);
4574 if (rc)
4575 pr_err("%s: Failed to set ffecns effect, err %d\n",
4576 __func__, rc);
4577
4578 return rc;
4579}
4580EXPORT_SYMBOL(adm_set_ffecns_effect);
4581
4582/**
Ramu Gottipati34dc3622019-12-26 10:50:00 +05304583 * adm_set_ffecns_freeze_event -
4584 * command to set event for ffecns module
4585 *
4586 * @event: send ffecns freeze event true or false
4587 *
4588 * Returns 0 on success or error on failure
4589 */
4590int adm_set_ffecns_freeze_event(bool ffecns_freeze_event)
4591{
4592 struct ffv_spf_freeze_param_t ffv_param;
4593 struct param_hdr_v3 param_hdr;
4594 int rc = 0;
4595 int copp_idx = 0;
4596
4597 memset(&param_hdr, 0, sizeof(param_hdr));
4598 memset(&ffv_param, 0, sizeof(ffv_param));
4599
4600 ffv_param.freeze = ffecns_freeze_event ? 1 : 0;
4601 ffv_param.source_id = 0; /*default value*/
4602
4603 copp_idx = adm_get_default_copp_idx(this_adm.ffecns_port_id);
4604 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
4605 pr_err("%s, no active copp to query rms copp_idx:%d\n",
4606 __func__, copp_idx);
4607 return -EINVAL;
4608 }
4609
4610 param_hdr.module_id = FFECNS_MODULE_ID;
4611 param_hdr.instance_id = INSTANCE_ID_0;
4612 param_hdr.param_id = PARAM_ID_FFV_SPF_FREEZE;
4613 param_hdr.param_size = sizeof(ffv_param);
4614
4615 rc = adm_pack_and_set_one_pp_param(this_adm.ffecns_port_id, copp_idx,
4616 param_hdr, (uint8_t *) &ffv_param);
4617 if (rc)
4618 pr_err("%s: Failed to set ffecns imc event, err %d\n",
4619 __func__, rc);
4620
4621 return rc;
4622}
4623EXPORT_SYMBOL(adm_set_ffecns_freeze_event);
4624
4625/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304626 * adm_param_enable -
4627 * command to send params to ADM for given module
4628 *
4629 * @port_id: Port ID number
4630 * @copp_idx: copp index assigned
4631 * @module_id: ADM module
4632 * @enable: flag to enable or disable module
4633 *
4634 * Returns 0 on success or error on failure
4635 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304636int adm_param_enable(int port_id, int copp_idx, int module_id, int enable)
4637{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004638 struct module_instance_info mod_inst_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304639
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004640 memset(&mod_inst_info, 0, sizeof(mod_inst_info));
4641 mod_inst_info.module_id = module_id;
4642 mod_inst_info.instance_id = INSTANCE_ID_0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304643
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004644 return adm_param_enable_v2(port_id, copp_idx, mod_inst_info, enable);
4645}
Vidyakumar Athota98464a22018-03-15 20:39:37 -07004646EXPORT_SYMBOL(adm_param_enable);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004647
4648/**
4649 * adm_param_enable_v2 -
4650 * command to send params to ADM for given module
4651 *
4652 * @port_id: Port ID number
4653 * @copp_idx: copp index assigned
4654 * @mod_inst_info: module and instance ID info
4655 * @enable: flag to enable or disable module
4656 *
4657 * Returns 0 on success or error on failure
4658 */
4659int adm_param_enable_v2(int port_id, int copp_idx,
4660 struct module_instance_info mod_inst_info, int enable)
4661{
4662 uint32_t enable_param;
4663 struct param_hdr_v3 param_hdr;
4664 int rc = 0;
4665
4666 if (enable < 0 || enable > 1) {
4667 pr_err("%s: Invalid value for enable %d\n", __func__, enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304668 return -EINVAL;
4669 }
4670
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004671 pr_debug("%s port_id %d, module_id 0x%x, instance_id 0x%x, enable %d\n",
4672 __func__, port_id, mod_inst_info.module_id,
4673 mod_inst_info.instance_id, enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304674
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004675 memset(&param_hdr, 0, sizeof(param_hdr));
4676 param_hdr.module_id = mod_inst_info.module_id;
4677 param_hdr.instance_id = mod_inst_info.instance_id;
4678 param_hdr.param_id = AUDPROC_PARAM_ID_ENABLE;
4679 param_hdr.param_size = sizeof(enable_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304680
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004681 enable_param = enable;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304682
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004683 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4684 (uint8_t *) &enable_param);
4685 if (rc)
4686 pr_err("%s: Failed to set enable of module(%d) instance(%d) to %d, err %d\n",
4687 __func__, mod_inst_info.module_id,
4688 mod_inst_info.instance_id, enable, rc);
4689
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304690 return rc;
4691
4692}
Vidyakumar Athota98464a22018-03-15 20:39:37 -07004693EXPORT_SYMBOL(adm_param_enable_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304694
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304695/**
4696 * adm_send_calibration -
4697 * send ADM calibration to DSP
4698 *
4699 * @port_id: Port ID number
4700 * @copp_idx: copp index assigned
4701 * @path: direction or ADM path type
4702 * @perf_mode: performance mode like LL/ULL/..
4703 * @cal_type: calibration type to use
4704 * @params: pointer with cal data
4705 * @size: cal size
4706 *
4707 * Returns 0 on success or error on failure
4708 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304709int adm_send_calibration(int port_id, int copp_idx, int path, int perf_mode,
4710 int cal_type, char *params, int size)
4711{
4712
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004713 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304714
4715 pr_debug("%s:port_id %d, path %d, perf_mode %d, cal_type %d, size %d\n",
4716 __func__, port_id, path, perf_mode, cal_type, size);
4717
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304718 /* Maps audio_dev_ctrl path definition to ACDB definition */
4719 if (get_cal_path(path) != RX_DEVICE) {
4720 pr_err("%s: acdb_path %d\n", __func__, path);
4721 rc = -EINVAL;
4722 goto end;
4723 }
4724
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004725 rc = adm_set_pp_params(port_id, copp_idx, NULL, (u8 *) params, size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304726
4727end:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304728 return rc;
4729}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304730EXPORT_SYMBOL(adm_send_calibration);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304731
4732/*
4733 * adm_update_wait_parameters must be called with routing driver locks.
4734 * adm_reset_wait_parameters must be called with routing driver locks.
4735 * set and reset parmeters are separated to make sure it is always called
4736 * under routing driver lock.
4737 * adm_wait_timeout is to block until timeout or interrupted. Timeout is
4738 * not a an error.
4739 */
4740int adm_set_wait_parameters(int port_id, int copp_idx)
4741{
4742
4743 int ret = 0, port_idx;
4744
4745 pr_debug("%s: port_id 0x%x, copp_idx %d\n", __func__, port_id,
4746 copp_idx);
4747 port_id = afe_convert_virtual_to_portid(port_id);
4748 port_idx = adm_validate_and_get_port_index(port_id);
4749 if (port_idx < 0) {
4750 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4751 ret = -EINVAL;
4752 goto end;
4753 }
4754
4755 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4756 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4757 return -EINVAL;
4758 }
4759
4760 this_adm.copp.adm_delay[port_idx][copp_idx] = 1;
4761 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 0);
4762
4763end:
4764 return ret;
4765
4766}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304767EXPORT_SYMBOL(adm_set_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304768
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304769/**
4770 * adm_reset_wait_parameters -
4771 * reset wait parameters or ADM delay value
4772 *
4773 * @port_id: Port ID number
4774 * @copp_idx: copp index assigned
4775 *
4776 * Returns 0 on success or error on failure
4777 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304778int adm_reset_wait_parameters(int port_id, int copp_idx)
4779{
4780 int ret = 0, port_idx;
4781
4782 pr_debug("%s: port_id 0x%x copp_idx %d\n", __func__, port_id,
4783 copp_idx);
4784 port_id = afe_convert_virtual_to_portid(port_id);
4785 port_idx = adm_validate_and_get_port_index(port_id);
4786 if (port_idx < 0) {
4787 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4788 ret = -EINVAL;
4789 goto end;
4790 }
4791
4792 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4793 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4794 return -EINVAL;
4795 }
4796
4797 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 1);
4798 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
4799
4800end:
4801 return ret;
4802}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304803EXPORT_SYMBOL(adm_reset_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304804
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304805/**
4806 * adm_wait_timeout -
4807 * ADM wait command after command send to DSP
4808 *
4809 * @port_id: Port ID number
4810 * @copp_idx: copp index assigned
4811 * @wait_time: value in ms for command timeout
4812 *
4813 * Returns 0 on success or error on failure
4814 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304815int adm_wait_timeout(int port_id, int copp_idx, int wait_time)
4816{
4817 int ret = 0, port_idx;
4818
4819 pr_debug("%s: port_id 0x%x, copp_idx %d, wait_time %d\n", __func__,
4820 port_id, copp_idx, wait_time);
4821 port_id = afe_convert_virtual_to_portid(port_id);
4822 port_idx = adm_validate_and_get_port_index(port_id);
4823 if (port_idx < 0) {
4824 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4825 ret = -EINVAL;
4826 goto end;
4827 }
4828
4829 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4830 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4831 return -EINVAL;
4832 }
4833
4834 ret = wait_event_timeout(
4835 this_adm.copp.adm_delay_wait[port_idx][copp_idx],
4836 atomic_read(&this_adm.copp.adm_delay_stat[port_idx][copp_idx]),
4837 msecs_to_jiffies(wait_time));
4838 pr_debug("%s: return %d\n", __func__, ret);
4839 if (ret != 0)
4840 ret = -EINTR;
4841end:
4842 pr_debug("%s: return %d--\n", __func__, ret);
4843 return ret;
4844}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304845EXPORT_SYMBOL(adm_wait_timeout);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304846
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304847/**
4848 * adm_store_cal_data -
4849 * Retrieve calibration data for ADM copp device
4850 *
4851 * @port_id: Port ID number
4852 * @copp_idx: copp index assigned
4853 * @path: direction or copp type
4854 * @perf_mode: performance mode like LL/ULL/..
4855 * @cal_index: calibration index to use
4856 * @params: pointer to store cal data
4857 * @size: pointer to fill with cal size
4858 *
4859 * Returns 0 on success or error on failure
4860 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304861int adm_store_cal_data(int port_id, int copp_idx, int path, int perf_mode,
4862 int cal_index, char *params, int *size)
4863{
4864 int rc = 0;
4865 struct cal_block_data *cal_block = NULL;
4866 int app_type, acdb_id, port_idx, sample_rate;
4867
4868 if (this_adm.cal_data[cal_index] == NULL) {
4869 pr_debug("%s: cal_index %d not allocated!\n",
4870 __func__, cal_index);
4871 goto end;
4872 }
4873
4874 if (get_cal_path(path) != RX_DEVICE) {
4875 pr_debug("%s: Invalid path to store calibration %d\n",
4876 __func__, path);
4877 rc = -EINVAL;
4878 goto end;
4879 }
4880
4881 port_id = afe_convert_virtual_to_portid(port_id);
4882 port_idx = adm_validate_and_get_port_index(port_id);
4883 if (port_idx < 0) {
4884 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
4885 rc = -EINVAL;
4886 goto end;
4887 }
4888
4889 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4890 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4891 return -EINVAL;
4892 }
4893
4894 acdb_id = atomic_read(&this_adm.copp.acdb_id[port_idx][copp_idx]);
4895 app_type = atomic_read(&this_adm.copp.app_type[port_idx][copp_idx]);
4896 sample_rate = atomic_read(&this_adm.copp.rate[port_idx][copp_idx]);
4897
4898 mutex_lock(&this_adm.cal_data[cal_index]->lock);
4899 cal_block = adm_find_cal(cal_index, get_cal_path(path), app_type,
4900 acdb_id, sample_rate);
4901 if (cal_block == NULL)
4902 goto unlock;
4903
4904 if (cal_block->cal_data.size <= 0) {
4905 pr_debug("%s: No ADM cal send for port_id = 0x%x!\n",
4906 __func__, port_id);
4907 rc = -EINVAL;
4908 goto unlock;
4909 }
4910
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304911 if (cal_index == ADM_AUDPROC_CAL || cal_index == ADM_LSM_AUDPROC_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304912 if (cal_block->cal_data.size > AUD_PROC_BLOCK_SIZE) {
4913 pr_err("%s:audproc:invalid size exp/actual[%zd, %d]\n",
4914 __func__, cal_block->cal_data.size, *size);
4915 rc = -ENOMEM;
4916 goto unlock;
4917 }
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004918 } else if (cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
4919 if (cal_block->cal_data.size > AUD_PROC_PERSIST_BLOCK_SIZE) {
4920 pr_err("%s:persist invalid size exp/actual[%zd, %d]\n",
4921 __func__, cal_block->cal_data.size, *size);
4922 rc = -ENOMEM;
4923 goto unlock;
4924 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304925 } else if (cal_index == ADM_AUDVOL_CAL) {
4926 if (cal_block->cal_data.size > AUD_VOL_BLOCK_SIZE) {
4927 pr_err("%s:aud_vol:invalid size exp/actual[%zd, %d]\n",
4928 __func__, cal_block->cal_data.size, *size);
4929 rc = -ENOMEM;
4930 goto unlock;
4931 }
4932 } else {
4933 pr_debug("%s: Not valid calibration for dolby topolgy\n",
4934 __func__);
4935 rc = -EINVAL;
4936 goto unlock;
4937 }
4938 memcpy(params, cal_block->cal_data.kvaddr, cal_block->cal_data.size);
4939 *size = cal_block->cal_data.size;
4940
4941 pr_debug("%s:port_id %d, copp_idx %d, path %d",
4942 __func__, port_id, copp_idx, path);
4943 pr_debug("perf_mode %d, cal_type %d, size %d\n",
4944 perf_mode, cal_index, *size);
4945
4946unlock:
4947 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
4948end:
4949 return rc;
4950}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304951EXPORT_SYMBOL(adm_store_cal_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304952
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304953/**
4954 * adm_send_compressed_device_mute -
4955 * command to send mute for compressed device
4956 *
4957 * @port_id: Port ID number
4958 * @copp_idx: copp index assigned
4959 * @mute_on: flag to indicate mute or unmute
4960 *
4961 * Returns 0 on success or error on failure
4962 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304963int adm_send_compressed_device_mute(int port_id, int copp_idx, bool mute_on)
4964{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004965 u32 mute_param = mute_on ? 1 : 0;
4966 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304967 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304968
4969 pr_debug("%s port_id: 0x%x, copp_idx %d, mute_on: %d\n",
4970 __func__, port_id, copp_idx, mute_on);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304971
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004972 memset(&param_hdr, 0, sizeof(param_hdr));
4973 param_hdr.module_id = AUDPROC_MODULE_ID_COMPRESSED_MUTE;
4974 param_hdr.instance_id = INSTANCE_ID_0;
4975 param_hdr.param_id = AUDPROC_PARAM_ID_COMPRESSED_MUTE;
4976 param_hdr.param_size = sizeof(mute_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304977
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004978 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4979 (uint8_t *) &mute_param);
4980 if (ret)
4981 pr_err("%s: Failed to set mute, err %d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304982
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304983 return ret;
4984}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304985EXPORT_SYMBOL(adm_send_compressed_device_mute);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304986
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304987/**
4988 * adm_send_compressed_device_latency -
4989 * command to send latency for compressed device
4990 *
4991 * @port_id: Port ID number
4992 * @copp_idx: copp index assigned
4993 * @latency: latency value to pass
4994 *
4995 * Returns 0 on success or error on failure
4996 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304997int adm_send_compressed_device_latency(int port_id, int copp_idx, int latency)
4998{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004999 u32 latency_param;
5000 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305001 int ret = 0;
5002
5003 pr_debug("%s port_id: 0x%x, copp_idx %d latency: %d\n", __func__,
5004 port_id, copp_idx, latency);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005005
5006 if (latency < 0) {
5007 pr_err("%s: Invalid value for latency %d", __func__, latency);
5008 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305009 }
5010
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005011 memset(&param_hdr, 0, sizeof(param_hdr));
5012 param_hdr.module_id = AUDPROC_MODULE_ID_COMPRESSED_LATENCY;
5013 param_hdr.instance_id = INSTANCE_ID_0;
5014 param_hdr.param_id = AUDPROC_PARAM_ID_COMPRESSED_LATENCY;
5015 param_hdr.param_size = sizeof(latency_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305016
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005017 latency_param = latency;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305018
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005019 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
5020 (uint8_t *) &latency_param);
5021 if (ret)
5022 pr_err("%s: Failed to set latency, err %d\n", __func__, ret);
5023
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305024 return ret;
5025}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305026EXPORT_SYMBOL(adm_send_compressed_device_latency);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305027
5028/**
5029 * adm_swap_speaker_channels
5030 *
5031 * Receives port_id, copp_idx, sample rate, spk_swap and
5032 * send MFC command to swap speaker channel.
5033 * Return zero on success. On failure returns nonzero.
5034 *
5035 * port_id - Passed value, port_id for which channels swap is wanted
5036 * copp_idx - Passed value, copp_idx for which channels swap is wanted
5037 * sample_rate - Passed value, sample rate used by app type config
5038 * spk_swap - Passed value, spk_swap for check if swap flag is set
5039 */
5040int adm_swap_speaker_channels(int port_id, int copp_idx,
5041 int sample_rate, bool spk_swap)
5042{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005043 struct audproc_mfc_param_media_fmt mfc_cfg;
5044 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305045 uint16_t num_channels;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005046 int port_idx = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305047 int ret = 0;
5048
5049 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5050 __func__, port_id, copp_idx);
5051 port_id = q6audio_convert_virtual_to_portid(port_id);
5052 port_idx = adm_validate_and_get_port_index(port_id);
5053 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
5054 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005055 return -EINVAL;
5056 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
5057 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
5058 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305059 }
5060
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005061 num_channels = atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305062 if (num_channels != 2) {
5063 pr_debug("%s: Invalid number of channels: %d\n",
5064 __func__, num_channels);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005065 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305066 }
5067
5068 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005069 memset(&param_hdr, 0, sizeof(param_hdr));
5070
5071 param_hdr.module_id = AUDPROC_MODULE_ID_MFC;
5072 param_hdr.instance_id = INSTANCE_ID_0;
5073 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
5074 param_hdr.param_size = sizeof(mfc_cfg);
5075
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305076 mfc_cfg.sampling_rate = sample_rate;
5077 mfc_cfg.bits_per_sample =
5078 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
5079 mfc_cfg.num_channels = num_channels;
5080
5081 /* Currently applying speaker swap for only 2 channel use case */
5082 if (spk_swap) {
5083 mfc_cfg.channel_type[0] =
5084 (uint16_t) PCM_CHANNEL_FR;
5085 mfc_cfg.channel_type[1] =
5086 (uint16_t) PCM_CHANNEL_FL;
5087 } else {
5088 mfc_cfg.channel_type[0] =
5089 (uint16_t) PCM_CHANNEL_FL;
5090 mfc_cfg.channel_type[1] =
5091 (uint16_t) PCM_CHANNEL_FR;
5092 }
5093
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005094 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
5095 (u8 *) &mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305096 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005097 pr_err("%s: Failed to set swap speaker channels on port[0x%x] failed %d\n",
5098 __func__, port_id, ret);
5099 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305100 }
5101
5102 pr_debug("%s: mfc_cfg Set params returned success", __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005103 return 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305104}
5105EXPORT_SYMBOL(adm_swap_speaker_channels);
5106
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305107/**
5108 * adm_set_sound_focus -
5109 * Update sound focus info
5110 *
5111 * @port_id: Port ID number
5112 * @copp_idx: copp index assigned
5113 * @soundFocusData: sound focus data to pass
5114 *
5115 * Returns 0 on success or error on failure
5116 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305117int adm_set_sound_focus(int port_id, int copp_idx,
5118 struct sound_focus_param soundFocusData)
5119{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005120 struct adm_param_fluence_soundfocus_t soundfocus_params;
5121 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305122 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305123 int i;
5124
5125 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5126 __func__, port_id, copp_idx);
5127
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005128 memset(&param_hdr, 0, sizeof(param_hdr));
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005129 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005130 param_hdr.instance_id = INSTANCE_ID_0;
5131 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
5132 param_hdr.param_size = sizeof(soundfocus_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305133
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005134 memset(&(soundfocus_params), 0xFF, sizeof(soundfocus_params));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305135 for (i = 0; i < MAX_SECTORS; i++) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005136 soundfocus_params.start_angles[i] =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305137 soundFocusData.start_angle[i];
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005138 soundfocus_params.enables[i] = soundFocusData.enable[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305139 pr_debug("%s: start_angle[%d] = %d\n",
5140 __func__, i, soundFocusData.start_angle[i]);
5141 pr_debug("%s: enable[%d] = %d\n",
5142 __func__, i, soundFocusData.enable[i]);
5143 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005144 soundfocus_params.gain_step = soundFocusData.gain_step;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305145 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData.gain_step);
5146
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005147 soundfocus_params.reserved = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305148
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005149 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
5150 (uint8_t *) &soundfocus_params);
5151 if (ret)
5152 pr_err("%s: Failed to set sound focus params, err %d\n",
5153 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305154
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305155 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
5156
5157 return ret;
5158}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305159EXPORT_SYMBOL(adm_set_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305160
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305161/**
5162 * adm_get_sound_focus -
5163 * Retrieve sound focus info
5164 *
5165 * @port_id: Port ID number
5166 * @copp_idx: copp index assigned
5167 * @soundFocusData: pointer for sound focus data to be updated with
5168 *
5169 * Returns 0 on success or error on failure
5170 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305171int adm_get_sound_focus(int port_id, int copp_idx,
5172 struct sound_focus_param *soundFocusData)
5173{
5174 int ret = 0, i;
5175 char *params_value;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005176 uint32_t max_param_size = 0;
5177 struct adm_param_fluence_soundfocus_t *soundfocus_params = NULL;
5178 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305179
5180 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5181 __func__, port_id, copp_idx);
5182
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005183 max_param_size = sizeof(struct adm_param_fluence_soundfocus_t) +
5184 sizeof(union param_hdrs);
5185 params_value = kzalloc(max_param_size, GFP_KERNEL);
5186 if (!params_value)
5187 return -ENOMEM;
5188
5189 memset(&param_hdr, 0, sizeof(param_hdr));
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005190 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005191 param_hdr.instance_id = INSTANCE_ID_0;
5192 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
5193 param_hdr.param_size = max_param_size;
5194 ret = adm_get_pp_params(port_id, copp_idx,
5195 ADM_CLIENT_ID_SOURCE_TRACKING, NULL, &param_hdr,
5196 params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305197 if (ret) {
5198 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305199 ret = -EINVAL;
5200 goto done;
5201 }
5202
5203 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
5204 pr_err("%s - get params returned error [%s]\n",
5205 __func__, adsp_err_get_err_str(
5206 this_adm.sourceTrackingData.apr_cmd_status));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305207 ret = adsp_err_get_lnx_err_code(
5208 this_adm.sourceTrackingData.apr_cmd_status);
5209 goto done;
5210 }
5211
5212 soundfocus_params = (struct adm_param_fluence_soundfocus_t *)
5213 params_value;
5214 for (i = 0; i < MAX_SECTORS; i++) {
5215 soundFocusData->start_angle[i] =
5216 soundfocus_params->start_angles[i];
5217 soundFocusData->enable[i] = soundfocus_params->enables[i];
5218 pr_debug("%s: start_angle[%d] = %d\n",
5219 __func__, i, soundFocusData->start_angle[i]);
5220 pr_debug("%s: enable[%d] = %d\n",
5221 __func__, i, soundFocusData->enable[i]);
5222 }
5223 soundFocusData->gain_step = soundfocus_params->gain_step;
5224 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData->gain_step);
5225
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305226done:
5227 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5228
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005229 kfree(params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305230 return ret;
5231}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305232EXPORT_SYMBOL(adm_get_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305233
5234static int adm_source_tracking_alloc_map_memory(void)
5235{
5236 int ret;
5237
5238 pr_debug("%s: Enter\n", __func__);
5239
Banajit Goswami08bb7362017-11-03 22:48:23 -07005240 ret = msm_audio_ion_alloc(&this_adm.sourceTrackingData.dma_buf,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305241 AUD_PROC_BLOCK_SIZE,
5242 &this_adm.sourceTrackingData.memmap.paddr,
5243 &this_adm.sourceTrackingData.memmap.size,
5244 &this_adm.sourceTrackingData.memmap.kvaddr);
5245 if (ret) {
5246 pr_err("%s: failed to allocate memory\n", __func__);
5247
5248 ret = -EINVAL;
5249 goto done;
5250 }
5251
5252 atomic_set(&this_adm.mem_map_index, ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
5253 ret = adm_memory_map_regions(&this_adm.sourceTrackingData.memmap.paddr,
5254 0,
5255 (uint32_t *)&this_adm.sourceTrackingData.memmap.size,
5256 1);
5257 if (ret < 0) {
5258 pr_err("%s: failed to map memory, paddr = 0x%pK, size = %d\n",
5259 __func__,
5260 (void *)this_adm.sourceTrackingData.memmap.paddr,
5261 (uint32_t)this_adm.sourceTrackingData.memmap.size);
5262
Banajit Goswami08bb7362017-11-03 22:48:23 -07005263 msm_audio_ion_free(this_adm.sourceTrackingData.dma_buf);
5264 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305265 this_adm.sourceTrackingData.memmap.size = 0;
5266 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5267 this_adm.sourceTrackingData.memmap.paddr = 0;
5268 this_adm.sourceTrackingData.apr_cmd_status = -1;
5269 atomic_set(&this_adm.mem_map_handles
5270 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
5271
5272 ret = -EINVAL;
5273 goto done;
5274 }
5275 ret = 0;
5276 pr_debug("%s: paddr = 0x%pK, size = %d, mem_map_handle = 0x%x\n",
5277 __func__, (void *)this_adm.sourceTrackingData.memmap.paddr,
5278 (uint32_t)this_adm.sourceTrackingData.memmap.size,
5279 atomic_read(&this_adm.mem_map_handles
5280 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING]));
5281
5282done:
5283 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5284
5285 return ret;
5286}
5287
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305288/**
5289 * adm_get_source_tracking -
5290 * Retrieve source tracking info
5291 *
5292 * @port_id: Port ID number
5293 * @copp_idx: copp index assigned
5294 * @sourceTrackingData: pointer for source track data to be updated with
5295 *
5296 * Returns 0 on success or error on failure
5297 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305298int adm_get_source_tracking(int port_id, int copp_idx,
5299 struct source_tracking_param *sourceTrackingData)
5300{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005301 struct adm_param_fluence_sourcetracking_t *source_tracking_params =
5302 NULL;
5303 struct mem_mapping_hdr mem_hdr;
5304 struct param_hdr_v3 param_hdr;
5305 int i = 0;
5306 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305307
5308 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5309 __func__, port_id, copp_idx);
5310
5311 if (!this_adm.sourceTrackingData.memmap.paddr) {
5312 /* Allocate and map shared memory for out of band usage */
5313 ret = adm_source_tracking_alloc_map_memory();
5314 if (ret != 0) {
5315 ret = -EINVAL;
5316 goto done;
5317 }
5318 }
5319
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005320 memset(&mem_hdr, 0, sizeof(mem_hdr));
5321 memset(&param_hdr, 0, sizeof(param_hdr));
5322 mem_hdr.data_payload_addr_lsw =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305323 lower_32_bits(this_adm.sourceTrackingData.memmap.paddr);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005324 mem_hdr.data_payload_addr_msw = msm_audio_populate_upper_32_bits(
5325 this_adm.sourceTrackingData.memmap.paddr);
5326 mem_hdr.mem_map_handle = atomic_read(
5327 &this_adm.mem_map_handles[ADM_MEM_MAP_INDEX_SOURCE_TRACKING]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305328
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005329 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005330 param_hdr.instance_id = INSTANCE_ID_0;
5331 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOURCETRACKING;
5332 /*
5333 * This size should be the max size of the calibration data + header.
5334 * Use the union size to ensure max size is used.
5335 */
5336 param_hdr.param_size =
5337 sizeof(struct adm_param_fluence_sourcetracking_t) +
5338 sizeof(union param_hdrs);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305339
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005340 /*
5341 * Retrieving parameters out of band, so no need to provide a buffer for
5342 * the returned parameter data as it will be at the memory location
5343 * provided.
5344 */
5345 ret = adm_get_pp_params(port_id, copp_idx,
5346 ADM_CLIENT_ID_SOURCE_TRACKING, &mem_hdr,
5347 &param_hdr, NULL);
5348 if (ret) {
5349 pr_err("%s: Failed to get params, error %d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305350 goto done;
5351 }
5352
5353 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
5354 pr_err("%s - get params returned error [%s]\n",
5355 __func__, adsp_err_get_err_str(
5356 this_adm.sourceTrackingData.apr_cmd_status));
5357
5358 ret = adsp_err_get_lnx_err_code(
5359 this_adm.sourceTrackingData.apr_cmd_status);
5360 goto done;
5361 }
5362
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005363 /* How do we know what the param data was retrieved with for hdr size */
5364 source_tracking_params =
5365 (struct adm_param_fluence_sourcetracking_t
5366 *) (this_adm.sourceTrackingData.memmap.kvaddr +
5367 sizeof(struct param_hdr_v1));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305368 for (i = 0; i < MAX_SECTORS; i++) {
5369 sourceTrackingData->vad[i] = source_tracking_params->vad[i];
5370 pr_debug("%s: vad[%d] = %d\n",
5371 __func__, i, sourceTrackingData->vad[i]);
5372 }
5373 sourceTrackingData->doa_speech = source_tracking_params->doa_speech;
5374 pr_debug("%s: doa_speech = %d\n",
5375 __func__, sourceTrackingData->doa_speech);
5376
5377 for (i = 0; i < MAX_NOISE_SOURCE_INDICATORS; i++) {
5378 sourceTrackingData->doa_noise[i] =
5379 source_tracking_params->doa_noise[i];
5380 pr_debug("%s: doa_noise[%d] = %d\n",
5381 __func__, i, sourceTrackingData->doa_noise[i]);
5382 }
5383 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
5384 sourceTrackingData->polar_activity[i] =
5385 source_tracking_params->polar_activity[i];
5386 pr_debug("%s: polar_activity[%d] = %d\n",
5387 __func__, i, sourceTrackingData->polar_activity[i]);
5388 }
5389
5390 ret = 0;
5391
5392done:
5393 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
5394
5395 return ret;
5396}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305397EXPORT_SYMBOL(adm_get_source_tracking);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305398
Chaithanya Krishna Bacharaju8c6a1842018-11-16 15:02:39 +05305399/**
5400 * adm_get_doa_tracking_mon -
5401 * Retrieve doa tracking monitor info
5402 *
5403 * @port_id: Port ID number
5404 * @copp_idx: copp index assigned
5405 * @doa_tracking_data: pointer for doa data to be updated with
5406 *
5407 * Returns 0 on success or error on failure
5408 */
5409int adm_get_doa_tracking_mon(int port_id, int copp_idx,
5410 struct doa_tracking_mon_param *doa_tracking_data)
5411{
5412 int ret = 0, i;
5413 char *params_value;
5414 uint32_t max_param_size = 0;
5415 struct adm_param_doa_tracking_mon_t *doa_tracking_params = NULL;
5416 struct param_hdr_v3 param_hdr;
5417
5418 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5419 __func__, port_id, copp_idx);
5420
5421 if (doa_tracking_data == NULL) {
5422 pr_err("%s: Received NULL pointer for doa tracking data\n",
5423 __func__);
5424 return -EINVAL;
5425 }
5426
5427 max_param_size = sizeof(struct adm_param_doa_tracking_mon_t) +
5428 sizeof(union param_hdrs);
5429 params_value = kzalloc(max_param_size, GFP_KERNEL);
5430 if (!params_value)
5431 return -ENOMEM;
5432
5433 memset(&param_hdr, 0, sizeof(param_hdr));
5434 param_hdr.module_id = AUDPROC_MODULE_ID_FFECNS;
5435 param_hdr.instance_id = INSTANCE_ID_0;
5436 param_hdr.param_id = AUDPROC_PARAM_ID_FFV_DOA_TRACKING_MONITOR;
5437 param_hdr.param_size = max_param_size;
5438 ret = adm_get_pp_params(port_id, copp_idx,
5439 ADM_CLIENT_ID_DEFAULT, NULL, &param_hdr,
5440 params_value);
5441 if (ret) {
5442 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
5443 goto done;
5444 }
5445
5446 doa_tracking_params =
5447 (struct adm_param_doa_tracking_mon_t *)params_value;
5448 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
5449 doa_tracking_data->target_angle_L16[i] =
5450 doa_tracking_params->target_angle_L16[i];
5451 pr_debug("%s: target angle[%d] = %d\n",
5452 __func__, i, doa_tracking_data->target_angle_L16[i]);
5453 }
5454
5455 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
5456 doa_tracking_data->interf_angle_L16[i] =
5457 doa_tracking_params->interf_angle_L16[i];
5458 pr_debug("%s: interference angle[%d] = %d\n",
5459 __func__, i, doa_tracking_data->interf_angle_L16[i]);
5460 }
5461
5462 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
5463 doa_tracking_data->polar_activity[i] =
5464 doa_tracking_params->polar_activity[i];
5465 }
5466
5467done:
5468 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5469 kfree(params_value);
5470 return ret;
5471}
5472EXPORT_SYMBOL(adm_get_doa_tracking_mon);
5473
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305474int __init adm_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305475{
5476 int i = 0, j;
5477
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305478 this_adm.ec_ref_rx = -1;
Xiaojun Sangdc9e8c22019-05-13 14:46:15 +08005479 this_adm.ffecns_port_id = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305480 init_waitqueue_head(&this_adm.matrix_map_wait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305481 init_waitqueue_head(&this_adm.adm_wait);
5482
5483 for (i = 0; i < AFE_MAX_PORTS; i++) {
5484 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
5485 atomic_set(&this_adm.copp.id[i][j], RESET_COPP_ID);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305486 init_waitqueue_head(&this_adm.copp.wait[i][j]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305487 init_waitqueue_head(
5488 &this_adm.copp.adm_delay_wait[i][j]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305489 }
5490 }
5491
5492 if (adm_init_cal_data())
5493 pr_err("%s: could not init cal data!\n", __func__);
5494
Banajit Goswami08bb7362017-11-03 22:48:23 -07005495 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305496 this_adm.sourceTrackingData.memmap.size = 0;
5497 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5498 this_adm.sourceTrackingData.memmap.paddr = 0;
5499 this_adm.sourceTrackingData.apr_cmd_status = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305500
5501 return 0;
5502}
5503
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05305504void adm_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305505{
Laxminath Kasam30ad7512017-11-28 12:40:22 +05305506 if (this_adm.apr)
5507 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305508 adm_delete_cal_data();
5509}