blob: 1723bb20b58c34bf2d6ba41ce7c88b7769176a22 [file] [log] [blame]
Meng Wang688a8672019-01-29 13:43:33 +08001// SPDX-License-Identifier: GPL-2.0-only
Meng Wang61af6842018-09-10 17:47:55 +08002/*
Surendar Karkade79a062018-12-05 14:18:55 +05303 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304 */
5#include <linux/module.h>
6#include <linux/slab.h>
7#include <linux/wait.h>
8#include <linux/sched.h>
9#include <linux/jiffies.h>
10#include <linux/uaccess.h>
11#include <linux/atomic.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053012#include <sound/asound.h>
Laxminath Kasam8b1366a2017-10-05 01:44:16 +053013#include <dsp/msm-dts-srs-tm-config.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053014#include <dsp/apr_audio-v2.h>
15#include <dsp/q6adm-v2.h>
16#include <dsp/q6audio-v2.h>
17#include <dsp/q6afe-v2.h>
Dieter Luecking50c55352018-09-28 14:29:17 +020018#include <dsp/q6core.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053019#include <dsp/audio_cal_utils.h>
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -080020#include <dsp/q6common.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053021#include <ipc/apr.h>
22#include "adsp_err.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053023
24#define TIMEOUT_MS 1000
25
26#define RESET_COPP_ID 99
27#define INVALID_COPP_ID 0xFF
28/* Used for inband payload copy, max size is 4k */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -080029/* 3 is to account for module, instance & param ID in payload */
30#define ADM_GET_PARAMETER_LENGTH (4096 - APR_HDR_SIZE - 3 * sizeof(uint32_t))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053031
32#define ULL_SUPPORTED_BITS_PER_SAMPLE 16
33#define ULL_SUPPORTED_SAMPLE_RATE 48000
34
35#ifndef CONFIG_DOLBY_DAP
36#undef DOLBY_ADM_COPP_TOPOLOGY_ID
37#define DOLBY_ADM_COPP_TOPOLOGY_ID 0xFFFFFFFE
38#endif
39
40#ifndef CONFIG_DOLBY_DS2
41#undef DS2_ADM_COPP_TOPOLOGY_ID
42#define DS2_ADM_COPP_TOPOLOGY_ID 0xFFFFFFFF
43#endif
44
45/* ENUM for adm_status */
46enum adm_cal_status {
47 ADM_STATUS_CALIBRATION_REQUIRED = 0,
48 ADM_STATUS_MAX,
49};
50
51struct adm_copp {
52
53 atomic_t id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
54 atomic_t cnt[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
55 atomic_t topology[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
56 atomic_t mode[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
57 atomic_t stat[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
58 atomic_t rate[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
59 atomic_t bit_width[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
60 atomic_t channels[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
61 atomic_t app_type[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
62 atomic_t acdb_id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
Surendar Karkae7507512018-07-20 15:46:54 +053063 atomic_t session_type[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053064 wait_queue_head_t wait[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
65 wait_queue_head_t adm_delay_wait[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
66 atomic_t adm_delay_stat[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
67 uint32_t adm_delay[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
68 unsigned long adm_status[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
69};
70
71struct source_tracking_data {
Banajit Goswami08bb7362017-11-03 22:48:23 -070072 struct dma_buf *dma_buf;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053073 struct param_outband memmap;
74 int apr_cmd_status;
75};
76
77struct adm_ctl {
78 void *apr;
79
80 struct adm_copp copp;
81
82 atomic_t matrix_map_stat;
83 wait_queue_head_t matrix_map_wait;
84
85 atomic_t adm_stat;
86 wait_queue_head_t adm_wait;
87
88 struct cal_type_data *cal_data[ADM_MAX_CAL_TYPES];
89
90 atomic_t mem_map_handles[ADM_MEM_MAP_INDEX_MAX];
91 atomic_t mem_map_index;
92
93 struct param_outband outband_memmap;
94 struct source_tracking_data sourceTrackingData;
95
96 int set_custom_topology;
97 int ec_ref_rx;
98 int num_ec_ref_rx_chans;
99 int ec_ref_rx_bit_width;
100 int ec_ref_rx_sampling_rate;
Dhananjay Kumar43034392019-01-16 21:57:58 +0530101 int num_ec_ref_rx_chans_downmixed;
102 uint16_t ec_ref_chmixer_weights[PCM_FORMAT_MAX_NUM_CHANNEL_V8]
103 [PCM_FORMAT_MAX_NUM_CHANNEL_V8];
Dieter Luecking50c55352018-09-28 14:29:17 +0200104 int native_mode;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530105};
106
107static struct adm_ctl this_adm;
108
109struct adm_multi_ch_map {
110 bool set_channel_map;
Dieter Luecking50c55352018-09-28 14:29:17 +0200111 char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530112};
113
114#define ADM_MCH_MAP_IDX_PLAYBACK 0
115#define ADM_MCH_MAP_IDX_REC 1
116static struct adm_multi_ch_map multi_ch_maps[2] = {
Dieter Luecking50c55352018-09-28 14:29:17 +0200117 { false,
118 {0, 0, 0, 0, 0, 0, 0, 0,
119 0, 0, 0, 0, 0, 0, 0, 0,
120 0, 0, 0, 0, 0, 0, 0, 0,
121 0, 0, 0, 0, 0, 0, 0, 0}
122 },
123 { false,
124 {0, 0, 0, 0, 0, 0, 0, 0,
125 0, 0, 0, 0, 0, 0, 0, 0,
126 0, 0, 0, 0, 0, 0, 0, 0,
127 0, 0, 0, 0, 0, 0, 0, 0}
128 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530129};
130
Rohit kumar2054b692019-02-01 18:01:12 +0530131static struct adm_multi_ch_map port_channel_map[AFE_MAX_PORTS];
132
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530133static int adm_get_parameters[MAX_COPPS_PER_PORT * ADM_GET_PARAMETER_LENGTH];
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800134static int adm_module_topo_list[MAX_COPPS_PER_PORT *
135 ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH];
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530136static struct mutex dts_srs_lock;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530137
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530138void msm_dts_srs_acquire_lock(void)
139{
140 mutex_lock(&dts_srs_lock);
141}
142
143void msm_dts_srs_release_lock(void)
144{
145 mutex_unlock(&dts_srs_lock);
146}
147
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530148static int adm_arrange_mch_map_v8(
149 struct adm_device_endpoint_payload *ep_payload,
150 int path,
Rohit kumar2054b692019-02-01 18:01:12 +0530151 int channel_mode,
152 int port_idx);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530153
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530154/**
155 * adm_validate_and_get_port_index -
156 * validate given port id
157 *
158 * @port_id: Port ID number
159 *
160 * Returns valid index on success or error on failure
161 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530162int adm_validate_and_get_port_index(int port_id)
163{
164 int index;
165 int ret;
166
167 ret = q6audio_validate_port(port_id);
168 if (ret < 0) {
169 pr_err("%s: port validation failed id 0x%x ret %d\n",
170 __func__, port_id, ret);
171 return -EINVAL;
172 }
173
174 index = afe_get_port_index(port_id);
175 if (index < 0 || index >= AFE_MAX_PORTS) {
176 pr_err("%s: Invalid port idx %d port_id 0x%x\n",
177 __func__, index,
178 port_id);
179 return -EINVAL;
180 }
181 pr_debug("%s: port_idx- %d\n", __func__, index);
182 return index;
183}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530184EXPORT_SYMBOL(adm_validate_and_get_port_index);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530185
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530186/**
187 * adm_get_default_copp_idx -
188 * retrieve default copp_idx for given port
189 *
190 * @port_id: Port ID number
191 *
192 * Returns valid value on success or error on failure
193 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530194int adm_get_default_copp_idx(int port_id)
195{
196 int port_idx = adm_validate_and_get_port_index(port_id), idx;
197
198 if (port_idx < 0) {
199 pr_err("%s: Invalid port id: 0x%x", __func__, port_id);
200 return -EINVAL;
201 }
202 pr_debug("%s: port_idx:%d\n", __func__, port_idx);
203 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
204 if (atomic_read(&this_adm.copp.id[port_idx][idx]) !=
205 RESET_COPP_ID)
206 return idx;
207 }
208 return -EINVAL;
209}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530210EXPORT_SYMBOL(adm_get_default_copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530211
212int adm_get_topology_for_port_from_copp_id(int port_id, int copp_id)
213{
214 int port_idx = adm_validate_and_get_port_index(port_id), idx;
215
216 if (port_idx < 0) {
217 pr_err("%s: Invalid port id: 0x%x", __func__, port_id);
218 return 0;
219 }
220 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
221 if (atomic_read(&this_adm.copp.id[port_idx][idx]) == copp_id)
222 return atomic_read(&this_adm.copp.topology[port_idx]
223 [idx]);
224 pr_err("%s: Invalid copp_id %d port_id 0x%x\n",
225 __func__, copp_id, port_id);
226 return 0;
227}
228
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530229/**
230 * adm_get_topology_for_port_copp_idx -
231 * retrieve topology of given port/copp_idx
232 *
233 * @port_id: Port ID number
234 * @copp_idx: copp index of ADM copp
235 *
236 * Returns valid value on success or 0 on failure
237 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530238int adm_get_topology_for_port_copp_idx(int port_id, int copp_idx)
239{
240 int port_idx = adm_validate_and_get_port_index(port_id);
241
242 if (port_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
243 pr_err("%s: Invalid port: 0x%x copp id: 0x%x",
244 __func__, port_id, copp_idx);
245 return 0;
246 }
247 return atomic_read(&this_adm.copp.topology[port_idx][copp_idx]);
248}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530249EXPORT_SYMBOL(adm_get_topology_for_port_copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530250
251int adm_get_indexes_from_copp_id(int copp_id, int *copp_idx, int *port_idx)
252{
253 int p_idx, c_idx;
254
255 for (p_idx = 0; p_idx < AFE_MAX_PORTS; p_idx++) {
256 for (c_idx = 0; c_idx < MAX_COPPS_PER_PORT; c_idx++) {
257 if (atomic_read(&this_adm.copp.id[p_idx][c_idx])
258 == copp_id) {
259 if (copp_idx != NULL)
260 *copp_idx = c_idx;
261 if (port_idx != NULL)
262 *port_idx = p_idx;
263 return 0;
264 }
265 }
266 }
267 return -EINVAL;
268}
269
270static int adm_get_copp_id(int port_idx, int copp_idx)
271{
272 pr_debug("%s: port_idx:%d copp_idx:%d\n", __func__, port_idx, copp_idx);
273
274 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
275 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
276 return -EINVAL;
277 }
278 return atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
279}
280
281static int adm_get_idx_if_copp_exists(int port_idx, int topology, int mode,
Surendar Karkae7507512018-07-20 15:46:54 +0530282 int rate, int bit_width, int app_type,
283 int session_type)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530284{
285 int idx;
286
287 pr_debug("%s: port_idx-%d, topology-0x%x, mode-%d, rate-%d, bit_width-%d\n",
288 __func__, port_idx, topology, mode, rate, bit_width);
289
290 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
291 if ((topology ==
292 atomic_read(&this_adm.copp.topology[port_idx][idx])) &&
293 (mode == atomic_read(&this_adm.copp.mode[port_idx][idx])) &&
294 (rate == atomic_read(&this_adm.copp.rate[port_idx][idx])) &&
295 (bit_width ==
296 atomic_read(&this_adm.copp.bit_width[port_idx][idx])) &&
Surendar Karkae7507512018-07-20 15:46:54 +0530297 (session_type ==
298 atomic_read(
299 &this_adm.copp.session_type[port_idx][idx])) &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530300 (app_type ==
301 atomic_read(&this_adm.copp.app_type[port_idx][idx])))
302 return idx;
303 return -EINVAL;
304}
305
306static int adm_get_next_available_copp(int port_idx)
307{
308 int idx;
309
310 pr_debug("%s:\n", __func__);
311 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
312 pr_debug("%s: copp_id:0x%x port_idx:%d idx:%d\n", __func__,
313 atomic_read(&this_adm.copp.id[port_idx][idx]),
314 port_idx, idx);
315 if (atomic_read(&this_adm.copp.id[port_idx][idx]) ==
316 RESET_COPP_ID)
317 break;
318 }
319 return idx;
320}
321
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530322/**
323 * srs_trumedia_open -
324 * command to set SRS trumedia open
325 *
326 * @port_id: Port ID number
327 * @copp_idx: copp index of ADM copp
328 * @srs_tech_id: SRS tech index
329 * @srs_params: params pointer
330 *
331 * Returns 0 on success or error on failure
332 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530333int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id,
334 void *srs_params)
335{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800336 struct param_hdr_v3 param_hdr;
337 struct mem_mapping_hdr mem_hdr;
338 u32 total_param_size = 0;
339 bool outband = false;
340 int port_idx;
341 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530342
343 pr_debug("SRS - %s", __func__);
344
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800345 memset(&param_hdr, 0, sizeof(param_hdr));
346 memset(&mem_hdr, 0, sizeof(mem_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530347 port_id = afe_convert_virtual_to_portid(port_id);
348 port_idx = adm_validate_and_get_port_index(port_id);
349 if (port_idx < 0) {
350 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
351 return -EINVAL;
352 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800353
354 param_hdr.module_id = SRS_TRUMEDIA_MODULE_ID;
355 param_hdr.instance_id = INSTANCE_ID_0;
356
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530357 switch (srs_tech_id) {
358 case SRS_ID_GLOBAL: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800359 param_hdr.param_id = SRS_TRUMEDIA_PARAMS;
360 param_hdr.param_size =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530361 sizeof(struct srs_trumedia_params_GLOBAL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530362 break;
363 }
364 case SRS_ID_WOWHD: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800365 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_WOWHD;
366 param_hdr.param_size = sizeof(struct srs_trumedia_params_WOWHD);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530367 break;
368 }
369 case SRS_ID_CSHP: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800370 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_CSHP;
371 param_hdr.param_size = sizeof(struct srs_trumedia_params_CSHP);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530372 break;
373 }
374 case SRS_ID_HPF: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800375 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_HPF;
376 param_hdr.param_size = sizeof(struct srs_trumedia_params_HPF);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530377 break;
378 }
379 case SRS_ID_AEQ: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800380 u8 *update_params_ptr = (u8 *) this_adm.outband_memmap.kvaddr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530381
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800382 outband = true;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530383
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530384 if (update_params_ptr == NULL) {
385 pr_err("ADM_SRS_TRUMEDIA - %s: null memmap for AEQ params\n",
386 __func__);
387 ret = -EINVAL;
388 goto fail_cmd;
389 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530390
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800391 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_AEQ;
392 param_hdr.param_size = sizeof(struct srs_trumedia_params_AEQ);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530393
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800394 ret = q6common_pack_pp_params(update_params_ptr, &param_hdr,
395 srs_params, &total_param_size);
396 if (ret) {
397 pr_err("%s: Failed to pack param header and data, error %d\n",
398 __func__, ret);
399 goto fail_cmd;
400 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530401 break;
402 }
403 case SRS_ID_HL: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800404 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_HL;
405 param_hdr.param_size = sizeof(struct srs_trumedia_params_HL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530406 break;
407 }
408 case SRS_ID_GEQ: {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800409 param_hdr.param_id = SRS_TRUMEDIA_PARAMS_GEQ;
410 param_hdr.param_size = sizeof(struct srs_trumedia_params_GEQ);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530411 break;
412 }
413 default:
414 goto fail_cmd;
415 }
416
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530417 if (outband && this_adm.outband_memmap.paddr) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800418 mem_hdr.data_payload_addr_lsw =
419 lower_32_bits(this_adm.outband_memmap.paddr);
420 mem_hdr.data_payload_addr_msw =
421 msm_audio_populate_upper_32_bits(
422 this_adm.outband_memmap.paddr);
423 mem_hdr.mem_map_handle = atomic_read(
424 &this_adm.mem_map_handles[ADM_SRS_TRUMEDIA]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530425
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800426 ret = adm_set_pp_params(port_id, copp_idx, &mem_hdr, NULL,
427 total_param_size);
428 } else {
429 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx,
430 param_hdr,
431 (u8 *) srs_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530432 }
433
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800434 if (ret < 0)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530435 pr_err("SRS - %s: ADM enable for port %d failed\n", __func__,
436 port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530437
438fail_cmd:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530439 return ret;
440}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530441EXPORT_SYMBOL(srs_trumedia_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530442
443static int adm_populate_channel_weight(u16 *ptr,
444 struct msm_pcm_channel_mixer *ch_mixer,
445 int channel_index)
446{
447 u16 i, j, start_index = 0;
448
449 if (channel_index > ch_mixer->output_channel) {
450 pr_err("%s: channel index %d is larger than output_channel %d\n",
451 __func__, channel_index, ch_mixer->output_channel);
452 return -EINVAL;
453 }
454
455 for (i = 0; i < ch_mixer->output_channel; i++) {
456 pr_debug("%s: weight for output %d:", __func__, i);
457 for (j = 0; j < ADM_MAX_CHANNELS; j++)
458 pr_debug(" %d",
459 ch_mixer->channel_weight[i][j]);
460 pr_debug("\n");
461 }
462
463 for (i = 0; i < channel_index; ++i)
464 start_index += ch_mixer->input_channels[i];
465
466 for (i = 0; i < ch_mixer->output_channel; ++i) {
467 for (j = start_index;
468 j < start_index +
469 ch_mixer->input_channels[channel_index]; j++) {
470 *ptr = ch_mixer->channel_weight[i][j];
471 pr_debug("%s: ptr[%d][%d] = %d\n",
472 __func__, i, j, *ptr);
473 ptr++;
474 }
475 }
476
477 return 0;
478}
479
480/*
481 * adm_programable_channel_mixer
482 *
483 * Receives port_id, copp_idx, session_id, session_type, ch_mixer
484 * and channel_index to send ADM command to mix COPP data.
485 *
486 * port_id - Passed value, port_id for which backend is wanted
487 * copp_idx - Passed value, copp_idx for which COPP is wanted
488 * session_id - Passed value, session_id for which session is needed
489 * session_type - Passed value, session_type for RX or TX
490 * ch_mixer - Passed value, ch_mixer for which channel mixer config is needed
491 * channel_index - Passed value, channel_index for which channel is needed
492 */
493int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
494 int session_type,
495 struct msm_pcm_channel_mixer *ch_mixer,
496 int channel_index)
497{
498 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700499 struct param_hdr_v1 data_v5;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530500 int ret = 0, port_idx, sz = 0, param_size = 0;
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530501 struct adm_device_endpoint_payload ep_params = {0, 0, 0, {0}};
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530502 u16 *adm_pspd_params;
503 u16 *ptr;
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530504 int index = 0, i = 0, path_type = ADM_PATH_PLAYBACK;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530505
506 pr_debug("%s: port_id = %d\n", __func__, port_id);
507 port_id = afe_convert_virtual_to_portid(port_id);
508 port_idx = adm_validate_and_get_port_index(port_id);
509 if (port_idx < 0) {
510 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
511 return -EINVAL;
512 }
513 /*
514 * First 8 bytes are 4 bytes as rule number, 2 bytes as output
515 * channel and 2 bytes as input channel.
516 * 2 * ch_mixer->output_channel means output channel mapping.
517 * 2 * ch_mixer->input_channels[channel_index]) means input
518 * channel mapping.
519 * 2 * ch_mixer->input_channels[channel_index] *
520 * ch_mixer->output_channel) means the channel mixer weighting
521 * coefficients.
522 * param_size needs to be a multiple of 4 bytes.
523 */
524
525 param_size = 2 * (4 + ch_mixer->output_channel +
526 ch_mixer->input_channels[channel_index] +
527 ch_mixer->input_channels[channel_index] *
528 ch_mixer->output_channel);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530529 param_size = roundup(param_size, 4);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530530
531 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800532 sizeof(struct default_chmixer_param_id_coeff) +
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700533 sizeof(struct param_hdr_v1) + param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530534 pr_debug("%s: sz = %d\n", __func__, sz);
535 adm_params = kzalloc(sz, GFP_KERNEL);
536 if (!adm_params)
537 return -ENOMEM;
538
539 adm_params->payload_addr_lsw = 0;
540 adm_params->payload_addr_msw = 0;
541 adm_params->mem_map_handle = 0;
542 adm_params->direction = session_type;
543 adm_params->sessionid = session_id;
544 pr_debug("%s: copp_id = %d, session id %d\n", __func__,
545 atomic_read(&this_adm.copp.id[port_idx][copp_idx]),
546 session_id);
547 adm_params->deviceid = atomic_read(
548 &this_adm.copp.id[port_idx][copp_idx]);
549 adm_params->reserved = 0;
550
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800551 /*
552 * This module is internal to ADSP and cannot be configured with
553 * an instance id
554 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530555 data_v5.module_id = MTMX_MODULE_ID_DEFAULT_CHMIXER;
556 data_v5.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
557 data_v5.reserved = 0;
558 data_v5.param_size = param_size;
559 adm_params->payload_size =
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800560 sizeof(struct default_chmixer_param_id_coeff) +
Vignesh Kulothungan2c6dccd2018-03-22 14:18:43 -0700561 sizeof(struct param_hdr_v1) + data_v5.param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530562 adm_pspd_params = (u16 *)((u8 *)adm_params +
563 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5));
564 memcpy(adm_pspd_params, &data_v5, sizeof(data_v5));
565
566 adm_pspd_params = (u16 *)((u8 *)adm_params +
567 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)
568 + sizeof(data_v5));
569
570 adm_pspd_params[0] = ch_mixer->rule;
571 adm_pspd_params[2] = ch_mixer->output_channel;
572 adm_pspd_params[3] = ch_mixer->input_channels[channel_index];
573 index = 4;
574
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530575 path_type = (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) ?
576 ADM_PATH_PLAYBACK : ADM_PATH_LIVE_REC;
577
578 if (ch_mixer->override_out_ch_map) {
579 memcpy(&adm_pspd_params[index], &ch_mixer->out_ch_map,
580 ch_mixer->output_channel * sizeof(uint16_t));
581 index += ch_mixer->output_channel;
582 } else {
583 ep_params.dev_num_channel = ch_mixer->output_channel;
Rohit kumar2054b692019-02-01 18:01:12 +0530584 adm_arrange_mch_map_v8(&ep_params, path_type,
585 ep_params.dev_num_channel, port_idx);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530586 for (i = 0; i < ch_mixer->output_channel; i++)
587 adm_pspd_params[index++] = ep_params.dev_channel_mapping[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530588 }
589
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530590 if (ch_mixer->override_in_ch_map) {
591 memcpy(&adm_pspd_params[index], &ch_mixer->in_ch_map,
592 ch_mixer->input_channel * sizeof(uint16_t));
593 index += ch_mixer->input_channel;
594 } else {
595 ep_params.dev_num_channel = ch_mixer->input_channels[channel_index];
Rohit kumar2054b692019-02-01 18:01:12 +0530596 adm_arrange_mch_map_v8(&ep_params, path_type,
597 ep_params.dev_num_channel, port_idx);
Dhananjay Kumardefd81b2018-12-11 18:05:59 +0530598 for (i = 0; i < ch_mixer->input_channels[channel_index]; i++)
599 adm_pspd_params[index++] = ep_params.dev_channel_mapping[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530600 }
601
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530602 ret = adm_populate_channel_weight(&adm_pspd_params[index],
603 ch_mixer, channel_index);
Meng Wangd9fa69c2018-01-23 12:42:52 +0800604 if (ret) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530605 pr_err("%s: fail to get channel weight with error %d\n",
606 __func__, ret);
607 goto fail_cmd;
608 }
609
610 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
611 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
612 adm_params->hdr.src_svc = APR_SVC_ADM;
613 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
614 adm_params->hdr.src_port = port_id;
615 adm_params->hdr.dest_svc = APR_SVC_ADM;
616 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
617 adm_params->hdr.dest_port =
618 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
619 adm_params->hdr.token = port_idx << 16 | copp_idx;
620 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
621 adm_params->hdr.pkt_size = sz;
622 adm_params->payload_addr_lsw = 0;
623 adm_params->payload_addr_msw = 0;
624 adm_params->mem_map_handle = 0;
625 adm_params->reserved = 0;
626
627 ptr = (u16 *)adm_params;
628 for (index = 0; index < (sz / 2); index++)
629 pr_debug("%s: adm_params[%d] = 0x%x\n",
630 __func__, index, (unsigned int)ptr[index]);
631
632 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], 0);
633 ret = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
634 if (ret < 0) {
635 pr_err("%s: Set params failed port %d rc %d\n", __func__,
636 port_id, ret);
637 ret = -EINVAL;
638 goto fail_cmd;
639 }
640
641 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
642 atomic_read(
643 &this_adm.copp.stat[port_idx][copp_idx]) >= 0,
644 msecs_to_jiffies(TIMEOUT_MS));
645 if (!ret) {
646 pr_err("%s: set params timed out port = %d\n",
647 __func__, port_id);
648 ret = -ETIMEDOUT;
649 goto fail_cmd;
650 }
651 ret = 0;
652fail_cmd:
653 kfree(adm_params);
654
655 return ret;
656}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530657EXPORT_SYMBOL(adm_programable_channel_mixer);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530658
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530659/**
660 * adm_set_stereo_to_custom_stereo -
661 * command to update custom stereo
662 *
663 * @port_id: Port ID number
664 * @copp_idx: copp index of ADM copp
665 * @session_id: session id to be updated
666 * @params: params pointer
667 * @param_length: length of params
668 *
669 * Returns 0 on success or error on failure
670 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530671int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx,
672 unsigned int session_id, char *params,
673 uint32_t params_length)
674{
675 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
676 int sz, rc = 0, port_idx;
677
678 pr_debug("%s:\n", __func__);
679 port_id = afe_convert_virtual_to_portid(port_id);
680 port_idx = adm_validate_and_get_port_index(port_id);
681 if (port_idx < 0) {
682 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
683 return -EINVAL;
684 }
685
686 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
687 params_length;
688 adm_params = kzalloc(sz, GFP_KERNEL);
689 if (!adm_params) {
690 pr_err("%s, adm params memory alloc failed\n", __func__);
691 return -ENOMEM;
692 }
693
694 memcpy(((u8 *)adm_params +
695 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)),
696 params, params_length);
697 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
698 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
699 adm_params->hdr.pkt_size = sz;
700 adm_params->hdr.src_svc = APR_SVC_ADM;
701 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
702 adm_params->hdr.src_port = port_id;
703 adm_params->hdr.dest_svc = APR_SVC_ADM;
704 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
705 adm_params->hdr.dest_port = 0; /* Ignored */;
706 adm_params->hdr.token = port_idx << 16 | copp_idx;
707 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
708 adm_params->payload_addr_lsw = 0;
709 adm_params->payload_addr_msw = 0;
710 adm_params->mem_map_handle = 0;
711 adm_params->payload_size = params_length;
712 /* direction RX as 0 */
713 adm_params->direction = ADM_MATRIX_ID_AUDIO_RX;
714 /* session id for this cmd to be applied on */
715 adm_params->sessionid = session_id;
716 adm_params->deviceid =
717 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
718 adm_params->reserved = 0;
719 pr_debug("%s: deviceid %d, session_id %d, src_port %d, dest_port %d\n",
720 __func__, adm_params->deviceid, adm_params->sessionid,
721 adm_params->hdr.src_port, adm_params->hdr.dest_port);
722 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
723 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
724 if (rc < 0) {
725 pr_err("%s: Set params failed port = 0x%x rc %d\n",
726 __func__, port_id, rc);
727 rc = -EINVAL;
728 goto set_stereo_to_custom_stereo_return;
729 }
730 /* Wait for the callback */
731 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
732 atomic_read(&this_adm.copp.stat
733 [port_idx][copp_idx]) >= 0,
734 msecs_to_jiffies(TIMEOUT_MS));
735 if (!rc) {
736 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
737 port_id);
738 rc = -EINVAL;
739 goto set_stereo_to_custom_stereo_return;
740 } else if (atomic_read(&this_adm.copp.stat
741 [port_idx][copp_idx]) > 0) {
742 pr_err("%s: DSP returned error[%s]\n", __func__,
743 adsp_err_get_err_str(atomic_read(
744 &this_adm.copp.stat
745 [port_idx][copp_idx])));
746 rc = adsp_err_get_lnx_err_code(
747 atomic_read(&this_adm.copp.stat
748 [port_idx][copp_idx]));
749 goto set_stereo_to_custom_stereo_return;
750 }
751 rc = 0;
752set_stereo_to_custom_stereo_return:
753 kfree(adm_params);
754 return rc;
755}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530756EXPORT_SYMBOL(adm_set_stereo_to_custom_stereo);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530757
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800758/*
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -0700759 * adm_set_custom_chmix_cfg:
760 * Set the custom channel mixer configuration for ADM
761 *
762 * @port_id: Backend port id
763 * @copp_idx: ADM copp index
764 * @session_id: ID of the requesting session
765 * @params: Expected packaged params for channel mixer
766 * @params_length: Length of the params to be set
767 * @direction: RX or TX direction
768 * @stream_type: Audio or Listen stream type
769 */
770int adm_set_custom_chmix_cfg(int port_id, int copp_idx,
771 unsigned int session_id, char *params,
772 uint32_t params_length, int direction,
773 int stream_type)
774{
775 struct adm_cmd_set_pspd_mtmx_strtr_params_v6 *adm_params = NULL;
776 int sz, rc = 0, port_idx;
777
778 port_id = afe_convert_virtual_to_portid(port_id);
779 port_idx = adm_validate_and_get_port_index(port_id);
780 if (port_idx < 0) {
781 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
782 return -EINVAL;
783 }
784
785 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v6) +
786 params_length;
787 adm_params = kzalloc(sz, GFP_KERNEL);
788 if (!adm_params) {
789 pr_err("%s, adm params memory alloc failed\n", __func__);
790 return -ENOMEM;
791 }
792
793 memcpy(((u8 *)adm_params +
794 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v6)),
795 params, params_length);
796 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
797 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
798 adm_params->hdr.pkt_size = sz;
799 adm_params->hdr.src_svc = APR_SVC_ADM;
800 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
801 adm_params->hdr.src_port = port_id;
802 adm_params->hdr.dest_svc = APR_SVC_ADM;
803 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
804 adm_params->hdr.dest_port = 0; /* Ignored */;
805 adm_params->hdr.token = port_idx << 16 | copp_idx;
806 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6;
807 adm_params->payload_addr_lsw = 0;
808 adm_params->payload_addr_msw = 0;
809 adm_params->mem_map_handle = 0;
810 adm_params->payload_size = params_length;
811 adm_params->direction = direction;
812 /* session id for this cmd to be applied on */
813 adm_params->sessionid = session_id;
814 adm_params->deviceid =
815 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
816 /* connecting stream type i.e. lsm or asm */
817 adm_params->stream_type = stream_type;
818 pr_debug("%s: deviceid %d, session_id %d, src_port %d, dest_port %d\n",
819 __func__, adm_params->deviceid, adm_params->sessionid,
820 adm_params->hdr.src_port, adm_params->hdr.dest_port);
821 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
822 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
823 if (rc < 0) {
824 pr_err("%s: Set params failed port = 0x%x rc %d\n",
825 __func__, port_id, rc);
826 rc = -EINVAL;
827 goto exit;
828 }
829 /* Wait for the callback */
830 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
831 atomic_read(&this_adm.copp.stat
832 [port_idx][copp_idx]),
833 msecs_to_jiffies(TIMEOUT_MS));
834 if (!rc) {
835 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
836 port_id);
837 rc = -EINVAL;
838 goto exit;
839 } else if (atomic_read(&this_adm.copp.stat
840 [port_idx][copp_idx]) > 0) {
841 pr_err("%s: DSP returned error[%s]\n", __func__,
842 adsp_err_get_err_str(atomic_read(
843 &this_adm.copp.stat
844 [port_idx][copp_idx])));
845 rc = adsp_err_get_lnx_err_code(
846 atomic_read(&this_adm.copp.stat
847 [port_idx][copp_idx]));
848 goto exit;
849 }
850
851 rc = 0;
852exit:
853 kfree(adm_params);
854 return rc;
855}
856EXPORT_SYMBOL(adm_set_custom_chmix_cfg);
857
858/*
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800859 * With pre-packed data, only the opcode differes from V5 and V6.
860 * Use q6common_pack_pp_params to pack the data correctly.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530861 */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800862int adm_set_pp_params(int port_id, int copp_idx,
863 struct mem_mapping_hdr *mem_hdr, u8 *param_data,
864 u32 param_size)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530865{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800866 struct adm_cmd_set_pp_params *adm_set_params = NULL;
867 int size = 0;
868 int port_idx = 0;
869 atomic_t *copp_stat = NULL;
870 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530871
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530872 port_id = afe_convert_virtual_to_portid(port_id);
873 port_idx = adm_validate_and_get_port_index(port_id);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800874 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
875 pr_err("%s: Invalid port_idx 0x%x\n", __func__, port_idx);
876 return -EINVAL;
877 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
878 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530879 return -EINVAL;
880 }
881
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800882 /* Only add params_size in inband case */
883 size = sizeof(struct adm_cmd_set_pp_params);
884 if (param_data != NULL)
885 size += param_size;
886 adm_set_params = kzalloc(size, GFP_KERNEL);
887 if (!adm_set_params)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530888 return -ENOMEM;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800889
890 adm_set_params->apr_hdr.hdr_field =
891 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
892 APR_PKT_VER);
893 adm_set_params->apr_hdr.pkt_size = size;
894 adm_set_params->apr_hdr.src_svc = APR_SVC_ADM;
895 adm_set_params->apr_hdr.src_domain = APR_DOMAIN_APPS;
896 adm_set_params->apr_hdr.src_port = port_id;
897 adm_set_params->apr_hdr.dest_svc = APR_SVC_ADM;
898 adm_set_params->apr_hdr.dest_domain = APR_DOMAIN_ADSP;
899 adm_set_params->apr_hdr.dest_port =
900 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
901 adm_set_params->apr_hdr.token = port_idx << 16 | copp_idx;
902
903 if (q6common_is_instance_id_supported())
904 adm_set_params->apr_hdr.opcode = ADM_CMD_SET_PP_PARAMS_V6;
905 else
906 adm_set_params->apr_hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
907
908 adm_set_params->payload_size = param_size;
909
910 if (mem_hdr != NULL) {
911 /* Out of Band Case */
912 adm_set_params->mem_hdr = *mem_hdr;
913 } else if (param_data != NULL) {
914 /*
915 * In band case. Parameter data must be pre-packed with its
916 * header before calling this function. Use
917 * q6common_pack_pp_params to pack parameter data and header
918 * correctly.
919 */
920 memcpy(&adm_set_params->param_data, param_data, param_size);
921 } else {
922 pr_err("%s: Received NULL pointers for both memory header and param data\n",
923 __func__);
924 ret = -EINVAL;
925 goto done;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530926 }
927
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800928 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
929 atomic_set(copp_stat, -1);
930 ret = apr_send_pkt(this_adm.apr, (uint32_t *) adm_set_params);
931 if (ret < 0) {
932 pr_err("%s: Set params APR send failed port = 0x%x ret %d\n",
933 __func__, port_id, ret);
934 goto done;
935 }
936 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
937 atomic_read(copp_stat) >= 0,
938 msecs_to_jiffies(TIMEOUT_MS));
939 if (!ret) {
940 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
941 port_id);
942 ret = -ETIMEDOUT;
943 goto done;
944 }
945 if (atomic_read(copp_stat) > 0) {
946 pr_err("%s: DSP returned error[%s]\n", __func__,
947 adsp_err_get_err_str(atomic_read(copp_stat)));
948 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
949 goto done;
950 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530951
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800952 ret = 0;
953done:
954 kfree(adm_set_params);
955 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530956}
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800957EXPORT_SYMBOL(adm_set_pp_params);
958
959int adm_pack_and_set_one_pp_param(int port_id, int copp_idx,
960 struct param_hdr_v3 param_hdr, u8 *param_data)
961{
962 u8 *packed_data = NULL;
963 u32 total_size = 0;
964 int ret = 0;
965
966 total_size = sizeof(union param_hdrs) + param_hdr.param_size;
967 packed_data = kzalloc(total_size, GFP_KERNEL);
968 if (!packed_data)
969 return -ENOMEM;
970
971 ret = q6common_pack_pp_params(packed_data, &param_hdr, param_data,
972 &total_size);
973 if (ret) {
974 pr_err("%s: Failed to pack parameter data, error %d\n",
975 __func__, ret);
976 goto done;
977 }
978
979 ret = adm_set_pp_params(port_id, copp_idx, NULL, packed_data,
980 total_size);
981 if (ret)
982 pr_err("%s: Failed to set parameter data, error %d\n", __func__,
983 ret);
984done:
985 kfree(packed_data);
986 return ret;
987}
988EXPORT_SYMBOL(adm_pack_and_set_one_pp_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530989
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800990/*
991 * Only one parameter can be requested at a time. Therefore, packing and sending
992 * the request can be handled locally.
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530993 */
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -0800994int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id,
995 struct mem_mapping_hdr *mem_hdr,
996 struct param_hdr_v3 *param_hdr, u8 *returned_param_data)
997{
998 struct adm_cmd_get_pp_params adm_get_params;
999 int total_size = 0;
1000 int get_param_array_sz = ARRAY_SIZE(adm_get_parameters);
1001 int returned_param_size = 0;
1002 int returned_param_size_in_bytes = 0;
1003 int port_idx = 0;
1004 int idx = 0;
1005 atomic_t *copp_stat = NULL;
1006 int ret = 0;
1007
1008 if (param_hdr == NULL) {
1009 pr_err("%s: Received NULL pointer for parameter header\n",
1010 __func__);
1011 return -EINVAL;
1012 }
1013
1014 port_id = afe_convert_virtual_to_portid(port_id);
1015 port_idx = adm_validate_and_get_port_index(port_id);
1016 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1017 pr_err("%s: Invalid port_idx 0x%x\n", __func__, port_idx);
1018 return -EINVAL;
1019 }
1020 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1021 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
1022 return -EINVAL;
1023 }
1024
1025 memset(&adm_get_params, 0, sizeof(adm_get_params));
1026
1027 if (mem_hdr != NULL)
1028 adm_get_params.mem_hdr = *mem_hdr;
1029
1030 q6common_pack_pp_params((u8 *) &adm_get_params.param_hdr, param_hdr,
1031 NULL, &total_size);
1032
1033 /* Pack APR header after filling body so total_size has correct value */
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001034 adm_get_params.apr_hdr.hdr_field =
1035 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
1036 APR_PKT_VER);
1037 adm_get_params.apr_hdr.pkt_size = sizeof(adm_get_params);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001038 adm_get_params.apr_hdr.src_svc = APR_SVC_ADM;
1039 adm_get_params.apr_hdr.src_domain = APR_DOMAIN_APPS;
1040 adm_get_params.apr_hdr.src_port = port_id;
1041 adm_get_params.apr_hdr.dest_svc = APR_SVC_ADM;
1042 adm_get_params.apr_hdr.dest_domain = APR_DOMAIN_ADSP;
1043 adm_get_params.apr_hdr.dest_port =
1044 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1045 adm_get_params.apr_hdr.token =
1046 port_idx << 16 | client_id << 8 | copp_idx;
1047
1048 if (q6common_is_instance_id_supported())
1049 adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V6;
1050 else
1051 adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
1052
1053 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
1054 atomic_set(copp_stat, -1);
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001055
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001056 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_params);
Vidyakumar Athotae427c412018-06-16 00:02:46 -07001057 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001058 pr_err("%s: Get params APR send failed port = 0x%x ret %d\n",
1059 __func__, port_id, ret);
1060 ret = -EINVAL;
1061 goto done;
1062 }
1063 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1064 atomic_read(copp_stat) >= 0,
1065 msecs_to_jiffies(TIMEOUT_MS));
1066 if (!ret) {
1067 pr_err("%s: Get params timed out port = 0x%x\n", __func__,
1068 port_id);
1069 ret = -ETIMEDOUT;
1070 goto done;
1071 }
1072 if (atomic_read(copp_stat) > 0) {
1073 pr_err("%s: DSP returned error[%s]\n", __func__,
1074 adsp_err_get_err_str(atomic_read(copp_stat)));
1075 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
1076 goto done;
1077 }
1078
1079 ret = 0;
1080
1081 /* Copy data to caller if sent in band */
1082 if (!returned_param_data) {
1083 pr_debug("%s: Received NULL pointer for param destination, not copying payload\n",
1084 __func__);
1085 return 0;
1086 }
1087
1088 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
1089 returned_param_size = adm_get_parameters[idx];
1090 if (returned_param_size < 0 ||
1091 returned_param_size + idx + 1 > get_param_array_sz) {
1092 pr_err("%s: Invalid parameter size %d\n", __func__,
1093 returned_param_size);
1094 return -EINVAL;
1095 }
1096
1097 returned_param_size_in_bytes = returned_param_size * sizeof(uint32_t);
1098 if (param_hdr->param_size < returned_param_size_in_bytes) {
1099 pr_err("%s: Provided buffer is not big enough, provided buffer size(%d) size needed(%d)\n",
1100 __func__, param_hdr->param_size,
1101 returned_param_size_in_bytes);
1102 return -EINVAL;
1103 }
1104
1105 memcpy(returned_param_data, &adm_get_parameters[idx + 1],
1106 returned_param_size_in_bytes);
1107done:
1108 return ret;
1109}
1110EXPORT_SYMBOL(adm_get_pp_params);
1111
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001112int adm_get_pp_topo_module_list_v2(int port_id, int copp_idx,
1113 int32_t param_length,
1114 int32_t *returned_params)
1115{
1116 struct adm_cmd_get_pp_topo_module_list adm_get_module_list;
1117 bool iid_supported = q6common_is_instance_id_supported();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301118 int *topo_list;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001119 int num_modules = 0;
1120 int list_size = 0;
1121 int port_idx, idx;
1122 int i = 0;
1123 atomic_t *copp_stat = NULL;
1124 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301125
1126 pr_debug("%s : port_id %x", __func__, port_id);
1127 port_id = afe_convert_virtual_to_portid(port_id);
1128 port_idx = adm_validate_and_get_port_index(port_id);
1129 if (port_idx < 0) {
1130 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1131 return -EINVAL;
1132 }
1133
1134 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1135 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
1136 return -EINVAL;
1137 }
1138
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001139 memset(&adm_get_module_list, 0, sizeof(adm_get_module_list));
1140
1141 adm_get_module_list.apr_hdr.pkt_size = sizeof(adm_get_module_list);
1142 adm_get_module_list.apr_hdr.src_svc = APR_SVC_ADM;
1143 adm_get_module_list.apr_hdr.src_domain = APR_DOMAIN_APPS;
1144 adm_get_module_list.apr_hdr.src_port = port_id;
1145 adm_get_module_list.apr_hdr.dest_svc = APR_SVC_ADM;
1146 adm_get_module_list.apr_hdr.dest_domain = APR_DOMAIN_ADSP;
1147 adm_get_module_list.apr_hdr.dest_port =
1148 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1149 adm_get_module_list.apr_hdr.token = port_idx << 16 | copp_idx;
1150 /*
1151 * Out of band functionality is not currently utilized.
1152 * Assume in band.
1153 */
1154 if (iid_supported) {
1155 adm_get_module_list.apr_hdr.opcode =
1156 ADM_CMD_GET_PP_TOPO_MODULE_LIST_V2;
1157 adm_get_module_list.param_max_size = param_length;
1158 } else {
1159 adm_get_module_list.apr_hdr.opcode =
1160 ADM_CMD_GET_PP_TOPO_MODULE_LIST;
1161
1162 if (param_length > U16_MAX) {
1163 pr_err("%s: Invalid param length for V1 %d\n", __func__,
1164 param_length);
1165 return -EINVAL;
1166 }
1167 adm_get_module_list.param_max_size = param_length << 16;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301168 }
1169
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001170 copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
1171 atomic_set(copp_stat, -1);
1172 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_module_list);
Vidyakumar Athotae427c412018-06-16 00:02:46 -07001173 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001174 pr_err("%s: APR send pkt failed for port_id: 0x%x failed ret %d\n",
1175 __func__, port_id, ret);
1176 ret = -EINVAL;
1177 goto done;
1178 }
1179 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1180 atomic_read(copp_stat) >= 0,
1181 msecs_to_jiffies(TIMEOUT_MS));
1182 if (!ret) {
1183 pr_err("%s: Timeout for port_id: 0x%x\n", __func__, port_id);
1184 ret = -ETIMEDOUT;
1185 goto done;
1186 }
1187 if (atomic_read(copp_stat) > 0) {
1188 pr_err("%s: DSP returned error[%s]\n", __func__,
1189 adsp_err_get_err_str(atomic_read(copp_stat)));
1190 ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
1191 goto done;
1192 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301193
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001194 ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301195
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001196 if (returned_params) {
1197 /*
1198 * When processing ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST IID is
1199 * added since it is not present. Therefore, there is no need to
1200 * do anything different if IID is not supported here as it is
1201 * already taken care of.
1202 */
1203 idx = ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH * copp_idx;
1204 num_modules = adm_module_topo_list[idx];
1205 if (num_modules < 0 || num_modules > MAX_MODULES_IN_TOPO) {
1206 pr_err("%s: Invalid number of modules returned %d\n",
1207 __func__, num_modules);
1208 return -EINVAL;
1209 }
1210
1211 list_size = num_modules * sizeof(struct module_instance_info);
1212 if (param_length < list_size) {
1213 pr_err("%s: Provided buffer not big enough to hold module-instance list, provided size %d, needed size %d\n",
1214 __func__, param_length, list_size);
1215 return -EINVAL;
1216 }
1217
1218 topo_list = (int32_t *) (&adm_module_topo_list[idx]);
1219 memcpy(returned_params, topo_list, list_size);
1220 for (i = 1; i <= num_modules; i += 2) {
1221 pr_debug("module = 0x%x instance = 0x%x\n",
1222 returned_params[i], returned_params[i + 1]);
1223 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301224 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001225done:
1226 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301227}
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001228EXPORT_SYMBOL(adm_get_pp_topo_module_list_v2);
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301229
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301230static void adm_callback_debug_print(struct apr_client_data *data)
1231{
1232 uint32_t *payload;
1233
1234 payload = data->payload;
1235
1236 if (data->payload_size >= 8)
1237 pr_debug("%s: code = 0x%x PL#0[0x%x], PL#1[0x%x], size = %d\n",
1238 __func__, data->opcode, payload[0], payload[1],
1239 data->payload_size);
1240 else if (data->payload_size >= 4)
1241 pr_debug("%s: code = 0x%x PL#0[0x%x], size = %d\n",
1242 __func__, data->opcode, payload[0],
1243 data->payload_size);
1244 else
1245 pr_debug("%s: code = 0x%x, size = %d\n",
1246 __func__, data->opcode, data->payload_size);
1247}
1248
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301249/**
1250 * adm_set_multi_ch_map -
1251 * Update multi channel map info
1252 *
1253 * @channel_map: pointer with channel map info
1254 * @path: direction or ADM path type
1255 *
1256 * Returns 0 on success or error on failure
1257 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301258int adm_set_multi_ch_map(char *channel_map, int path)
1259{
1260 int idx;
1261
1262 if (path == ADM_PATH_PLAYBACK) {
1263 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1264 } else if (path == ADM_PATH_LIVE_REC) {
1265 idx = ADM_MCH_MAP_IDX_REC;
1266 } else {
1267 pr_err("%s: invalid attempt to set path %d\n", __func__, path);
1268 return -EINVAL;
1269 }
1270
1271 memcpy(multi_ch_maps[idx].channel_mapping, channel_map,
Dieter Luecking50c55352018-09-28 14:29:17 +02001272 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301273 multi_ch_maps[idx].set_channel_map = true;
1274
1275 return 0;
1276}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301277EXPORT_SYMBOL(adm_set_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301278
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301279/**
1280 * adm_get_multi_ch_map -
1281 * Retrieves multi channel map info
1282 *
1283 * @channel_map: pointer to be updated with channel map
1284 * @path: direction or ADM path type
1285 *
1286 * Returns 0 on success or error on failure
1287 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301288int adm_get_multi_ch_map(char *channel_map, int path)
1289{
1290 int idx;
1291
1292 if (path == ADM_PATH_PLAYBACK) {
1293 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1294 } else if (path == ADM_PATH_LIVE_REC) {
1295 idx = ADM_MCH_MAP_IDX_REC;
1296 } else {
1297 pr_err("%s: invalid attempt to get path %d\n", __func__, path);
1298 return -EINVAL;
1299 }
1300
1301 if (multi_ch_maps[idx].set_channel_map) {
1302 memcpy(channel_map, multi_ch_maps[idx].channel_mapping,
Dieter Luecking50c55352018-09-28 14:29:17 +02001303 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301304 }
1305
1306 return 0;
1307}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301308EXPORT_SYMBOL(adm_get_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301309
Rohit kumar2054b692019-02-01 18:01:12 +05301310/**
1311 * adm_set_port_multi_ch_map -
1312 * Update port specific channel map info
1313 *
1314 * @channel_map: pointer with channel map info
1315 * @port_id: port for which chmap is set
1316 */
1317void adm_set_port_multi_ch_map(char *channel_map, int port_id)
1318{
1319 int port_idx;
1320
1321 port_id = q6audio_convert_virtual_to_portid(port_id);
1322 port_idx = adm_validate_and_get_port_index(port_id);
1323
1324 if (port_idx < 0) {
1325 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1326 return;
1327 }
1328
1329 memcpy(port_channel_map[port_idx].channel_mapping, channel_map,
1330 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
1331 port_channel_map[port_idx].set_channel_map = true;
1332}
1333EXPORT_SYMBOL(adm_set_port_multi_ch_map);
1334
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001335static int adm_process_get_param_response(u32 opcode, u32 idx, u32 *payload,
1336 u32 payload_size)
1337{
1338 struct adm_cmd_rsp_get_pp_params_v5 *v5_rsp = NULL;
1339 struct adm_cmd_rsp_get_pp_params_v6 *v6_rsp = NULL;
1340 u32 *param_data = NULL;
1341 int data_size = 0;
1342 int struct_size = 0;
1343
1344 if (payload == NULL) {
1345 pr_err("%s: Payload is NULL\n", __func__);
1346 return -EINVAL;
1347 }
1348
1349 switch (opcode) {
1350 case ADM_CMDRSP_GET_PP_PARAMS_V5:
1351 struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v5);
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001352 if (payload_size < struct_size) {
1353 pr_err("%s: payload size %d < expected size %d\n",
1354 __func__, payload_size, struct_size);
1355 break;
1356 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001357 v5_rsp = (struct adm_cmd_rsp_get_pp_params_v5 *) payload;
1358 data_size = v5_rsp->param_hdr.param_size;
1359 param_data = v5_rsp->param_data;
1360 break;
1361 case ADM_CMDRSP_GET_PP_PARAMS_V6:
1362 struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v6);
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001363 if (payload_size < struct_size) {
1364 pr_err("%s: payload size %d < expected size %d\n",
1365 __func__, payload_size, struct_size);
1366 break;
1367 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001368 v6_rsp = (struct adm_cmd_rsp_get_pp_params_v6 *) payload;
1369 data_size = v6_rsp->param_hdr.param_size;
1370 param_data = v6_rsp->param_data;
1371 break;
1372 default:
1373 pr_err("%s: Invalid opcode %d\n", __func__, opcode);
1374 return -EINVAL;
1375 }
1376
1377 /*
1378 * Just store the returned parameter data, not the header. The calling
1379 * function is expected to know what it asked for. Therefore, there is
1380 * no difference between V5 and V6.
1381 */
1382 if ((payload_size >= struct_size + data_size) &&
1383 (ARRAY_SIZE(adm_get_parameters) > idx) &&
Karthikeyan Mani95be5b12018-11-09 14:57:32 -08001384 (ARRAY_SIZE(adm_get_parameters) > idx + 1 + data_size)) {
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001385 pr_debug("%s: Received parameter data in band\n",
1386 __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001387 /*
1388 * data_size is expressed in number of bytes, store in number of
1389 * ints
1390 */
1391 adm_get_parameters[idx] =
1392 data_size / sizeof(*adm_get_parameters);
1393 pr_debug("%s: GET_PP PARAM: received parameter length: 0x%x\n",
1394 __func__, adm_get_parameters[idx]);
1395 /* store params after param_size */
1396 memcpy(&adm_get_parameters[idx + 1], param_data, data_size);
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001397 } else if (payload_size == sizeof(uint32_t)) {
1398 adm_get_parameters[idx] = -1;
1399 pr_debug("%s: Out of band case, setting size to %d\n",
1400 __func__, adm_get_parameters[idx]);
1401 } else {
1402 pr_err("%s: Invalid parameter combination, payload_size %d, idx %d\n",
1403 __func__, payload_size, idx);
1404 return -EINVAL;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001405 }
Vignesh Kulothunganaadecdf2018-06-20 15:08:24 -07001406 return 0;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001407}
1408
1409static int adm_process_get_topo_list_response(u32 opcode, int copp_idx,
1410 u32 num_modules, u32 *payload,
1411 u32 payload_size)
1412{
1413 u32 *fill_list = NULL;
1414 int idx = 0;
1415 int i = 0;
1416 int j = 0;
1417
1418 if (payload == NULL) {
1419 pr_err("%s: Payload is NULL\n", __func__);
1420 return -EINVAL;
1421 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1422 pr_err("%s: Invalid COPP index %d\n", __func__, copp_idx);
1423 return -EINVAL;
1424 }
1425
1426 idx = ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH * copp_idx;
1427 fill_list = adm_module_topo_list + idx;
1428 *fill_list++ = num_modules;
1429 for (i = 0; i < num_modules; i++) {
1430 if (j > payload_size / sizeof(u32)) {
1431 pr_err("%s: Invalid number of modules specified %d\n",
1432 __func__, num_modules);
1433 return -EINVAL;
1434 }
1435
1436 /* store module ID */
1437 *fill_list++ = payload[j];
1438 j++;
1439
1440 switch (opcode) {
1441 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
1442 /* store instance ID */
1443 *fill_list++ = payload[j];
1444 j++;
1445 break;
1446 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
1447 /* Insert IID 0 when repacking */
1448 *fill_list++ = INSTANCE_ID_0;
1449 break;
1450 default:
1451 pr_err("%s: Invalid opcode %d\n", __func__, opcode);
1452 return -EINVAL;
1453 }
1454 }
1455
1456 return 0;
1457}
1458
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301459static void adm_reset_data(void)
1460{
1461 int i, j;
1462
1463 apr_reset(this_adm.apr);
1464 for (i = 0; i < AFE_MAX_PORTS; i++) {
1465 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
1466 atomic_set(&this_adm.copp.id[i][j],
1467 RESET_COPP_ID);
1468 atomic_set(&this_adm.copp.cnt[i][j], 0);
1469 atomic_set(
1470 &this_adm.copp.topology[i][j], 0);
1471 atomic_set(&this_adm.copp.mode[i][j],
1472 0);
1473 atomic_set(&this_adm.copp.stat[i][j],
1474 0);
1475 atomic_set(&this_adm.copp.rate[i][j],
1476 0);
1477 atomic_set(
1478 &this_adm.copp.channels[i][j],
1479 0);
1480 atomic_set(
1481 &this_adm.copp.bit_width[i][j], 0);
1482 atomic_set(
1483 &this_adm.copp.app_type[i][j], 0);
1484 atomic_set(
1485 &this_adm.copp.acdb_id[i][j], 0);
Surendar Karkae7507512018-07-20 15:46:54 +05301486 atomic_set(
1487 &this_adm.copp.session_type[i][j], 0);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301488 this_adm.copp.adm_status[i][j] =
1489 ADM_STATUS_CALIBRATION_REQUIRED;
1490 }
1491 }
1492 this_adm.apr = NULL;
1493 cal_utils_clear_cal_block_q6maps(ADM_MAX_CAL_TYPES,
1494 this_adm.cal_data);
1495 mutex_lock(&this_adm.cal_data
1496 [ADM_CUSTOM_TOP_CAL]->lock);
1497 this_adm.set_custom_topology = 1;
1498 mutex_unlock(&this_adm.cal_data[
1499 ADM_CUSTOM_TOP_CAL]->lock);
1500 rtac_clear_mapping(ADM_RTAC_CAL);
1501 /*
1502 * Free the ION memory and clear the map handles
1503 * for Source Tracking
1504 */
1505 if (this_adm.sourceTrackingData.memmap.paddr != 0) {
1506 msm_audio_ion_free(
1507 this_adm.sourceTrackingData.dma_buf);
1508 this_adm.sourceTrackingData.dma_buf = NULL;
1509 this_adm.sourceTrackingData.memmap.size = 0;
1510 this_adm.sourceTrackingData.memmap.kvaddr =
1511 NULL;
1512 this_adm.sourceTrackingData.memmap.paddr = 0;
1513 this_adm.sourceTrackingData.apr_cmd_status = -1;
1514 atomic_set(&this_adm.mem_map_handles[
1515 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
1516 }
1517}
1518
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301519static int32_t adm_callback(struct apr_client_data *data, void *priv)
1520{
1521 uint32_t *payload;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001522 int port_idx, copp_idx, idx, client_id;
1523 int num_modules;
1524 int ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301525
1526 if (data == NULL) {
1527 pr_err("%s: data parameter is null\n", __func__);
1528 return -EINVAL;
1529 }
1530
1531 payload = data->payload;
1532
1533 if (data->opcode == RESET_EVENTS) {
1534 pr_debug("%s: Reset event is received: %d %d apr[%pK]\n",
1535 __func__,
1536 data->reset_event, data->reset_proc, this_adm.apr);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301537 if (this_adm.apr)
1538 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301539 return 0;
1540 }
1541
1542 adm_callback_debug_print(data);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001543 if (data->payload_size >= sizeof(uint32_t)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301544 copp_idx = (data->token) & 0XFF;
1545 port_idx = ((data->token) >> 16) & 0xFF;
1546 client_id = ((data->token) >> 8) & 0xFF;
1547 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1548 pr_err("%s: Invalid port idx %d token %d\n",
1549 __func__, port_idx, data->token);
1550 return 0;
1551 }
1552 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1553 pr_err("%s: Invalid copp idx %d token %d\n",
1554 __func__, copp_idx, data->token);
1555 return 0;
1556 }
1557 if (client_id < 0 || client_id >= ADM_CLIENT_ID_MAX) {
1558 pr_err("%s: Invalid client id %d\n", __func__,
1559 client_id);
1560 return 0;
1561 }
1562 if (data->opcode == APR_BASIC_RSP_RESULT) {
1563 pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
1564 __func__, payload[0]);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001565
1566 if (!((client_id != ADM_CLIENT_ID_SOURCE_TRACKING) &&
1567 ((payload[0] == ADM_CMD_SET_PP_PARAMS_V5) ||
1568 (payload[0] == ADM_CMD_SET_PP_PARAMS_V6)))) {
1569 if (data->payload_size <
1570 (2 * sizeof(uint32_t))) {
1571 pr_err("%s: Invalid payload size %d\n",
1572 __func__, data->payload_size);
1573 return 0;
1574 }
1575 }
1576
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301577 if (payload[1] != 0) {
1578 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
1579 __func__, payload[0], payload[1]);
1580 }
1581 switch (payload[0]) {
1582 case ADM_CMD_SET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001583 case ADM_CMD_SET_PP_PARAMS_V6:
1584 pr_debug("%s: ADM_CMD_SET_PP_PARAMS\n",
1585 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301586 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1587 this_adm.sourceTrackingData.
1588 apr_cmd_status = payload[1];
1589 else if (rtac_make_adm_callback(payload,
1590 data->payload_size))
1591 break;
1592 /*
1593 * if soft volume is called and already
1594 * interrupted break out of the sequence here
1595 */
1596 case ADM_CMD_DEVICE_OPEN_V5:
1597 case ADM_CMD_DEVICE_CLOSE_V5:
1598 case ADM_CMD_DEVICE_OPEN_V6:
Dieter Luecking50c55352018-09-28 14:29:17 +02001599 case ADM_CMD_DEVICE_OPEN_V8:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301600 pr_debug("%s: Basic callback received, wake up.\n",
1601 __func__);
1602 atomic_set(&this_adm.copp.stat[port_idx]
1603 [copp_idx], payload[1]);
1604 wake_up(
1605 &this_adm.copp.wait[port_idx][copp_idx]);
1606 break;
1607 case ADM_CMD_ADD_TOPOLOGIES:
1608 pr_debug("%s: callback received, ADM_CMD_ADD_TOPOLOGIES.\n",
1609 __func__);
1610 atomic_set(&this_adm.adm_stat, payload[1]);
1611 wake_up(&this_adm.adm_wait);
1612 break;
1613 case ADM_CMD_MATRIX_MAP_ROUTINGS_V5:
1614 case ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5:
1615 pr_debug("%s: Basic callback received, wake up.\n",
1616 __func__);
1617 atomic_set(&this_adm.matrix_map_stat,
1618 payload[1]);
1619 wake_up(&this_adm.matrix_map_wait);
1620 break;
1621 case ADM_CMD_SHARED_MEM_UNMAP_REGIONS:
1622 pr_debug("%s: ADM_CMD_SHARED_MEM_UNMAP_REGIONS\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_SHARED_MEM_MAP_REGIONS:
1628 pr_debug("%s: ADM_CMD_SHARED_MEM_MAP_REGIONS\n",
1629 __func__);
1630 /* Should only come here if there is an APR */
1631 /* error or malformed APR packet. Otherwise */
1632 /* response will be returned as */
1633 if (payload[1] != 0) {
1634 pr_err("%s: ADM map error, resuming\n",
1635 __func__);
1636 atomic_set(&this_adm.adm_stat,
1637 payload[1]);
1638 wake_up(&this_adm.adm_wait);
1639 }
1640 break;
1641 case ADM_CMD_GET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001642 case ADM_CMD_GET_PP_PARAMS_V6:
1643 pr_debug("%s: ADM_CMD_GET_PP_PARAMS\n",
1644 __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301645 /* Should only come here if there is an APR */
1646 /* error or malformed APR packet. Otherwise */
1647 /* response will be returned as */
1648 /* ADM_CMDRSP_GET_PP_PARAMS_V5 */
1649 if (client_id ==
1650 ADM_CLIENT_ID_SOURCE_TRACKING) {
1651 this_adm.sourceTrackingData.
1652 apr_cmd_status = payload[1];
1653 if (payload[1] != 0)
1654 pr_err("%s: ADM get param error = %d\n",
1655 __func__, payload[1]);
1656
1657 atomic_set(&this_adm.copp.stat
1658 [port_idx][copp_idx],
1659 payload[1]);
1660 wake_up(&this_adm.copp.wait
1661 [port_idx][copp_idx]);
1662 } else {
1663 if (payload[1] != 0) {
1664 pr_err("%s: ADM get param error = %d, resuming\n",
1665 __func__, payload[1]);
1666
1667 rtac_make_adm_callback(payload,
1668 data->payload_size);
1669 }
1670 }
1671 break;
1672 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5:
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -07001673 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6:
1674 pr_debug("%s:callback received PSPD MTMX, wake up\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301675 __func__);
1676 atomic_set(&this_adm.copp.stat[port_idx]
1677 [copp_idx], payload[1]);
1678 wake_up(
1679 &this_adm.copp.wait[port_idx][copp_idx]);
1680 break;
1681 case ADM_CMD_GET_PP_TOPO_MODULE_LIST:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001682 case ADM_CMD_GET_PP_TOPO_MODULE_LIST_V2:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301683 pr_debug("%s:ADM_CMD_GET_PP_TOPO_MODULE_LIST\n",
1684 __func__);
1685 if (payload[1] != 0)
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001686 pr_err("%s: ADM get topo list error = %d\n",
1687 __func__, payload[1]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301688 break;
1689 default:
1690 pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
1691 payload[0]);
1692 break;
1693 }
1694 return 0;
1695 }
1696
1697 switch (data->opcode) {
1698 case ADM_CMDRSP_DEVICE_OPEN_V5:
Dieter Luecking50c55352018-09-28 14:29:17 +02001699 case ADM_CMDRSP_DEVICE_OPEN_V6:
1700 case ADM_CMDRSP_DEVICE_OPEN_V8: {
Vignesh Kulothungan35524622019-01-22 11:13:09 -08001701 struct adm_cmd_rsp_device_open_v5 *open = NULL;
1702 if (data->payload_size <
1703 sizeof(struct adm_cmd_rsp_device_open_v5)) {
1704 pr_err("%s: Invalid payload size %d\n", __func__,
1705 data->payload_size);
1706 return 0;
1707 }
1708 open = (struct adm_cmd_rsp_device_open_v5 *)data->payload;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301709 if (open->copp_id == INVALID_COPP_ID) {
1710 pr_err("%s: invalid coppid rxed %d\n",
1711 __func__, open->copp_id);
1712 atomic_set(&this_adm.copp.stat[port_idx]
1713 [copp_idx], ADSP_EBADPARAM);
1714 wake_up(
1715 &this_adm.copp.wait[port_idx][copp_idx]);
1716 break;
1717 }
1718 atomic_set(&this_adm.copp.stat
1719 [port_idx][copp_idx], payload[0]);
1720 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
1721 open->copp_id);
1722 pr_debug("%s: coppid rxed=%d\n", __func__,
1723 open->copp_id);
1724 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1725 }
1726 break;
1727 case ADM_CMDRSP_GET_PP_PARAMS_V5:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001728 case ADM_CMDRSP_GET_PP_PARAMS_V6:
1729 pr_debug("%s: ADM_CMDRSP_GET_PP_PARAMS\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301730 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1731 this_adm.sourceTrackingData.apr_cmd_status =
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001732 payload[0];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301733 else if (rtac_make_adm_callback(payload,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001734 data->payload_size))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301735 break;
1736
1737 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001738 if (payload[0] == 0 && data->payload_size > 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001739 ret = adm_process_get_param_response(
1740 data->opcode, idx, payload,
1741 data->payload_size);
1742 if (ret)
1743 pr_err("%s: Failed to process get param response, error %d\n",
1744 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301745 } else {
1746 adm_get_parameters[idx] = -1;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001747 pr_err("%s: ADM_CMDRSP_GET_PP_PARAMS returned error 0x%x\n",
1748 __func__, payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301749 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001750 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1751 payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301752 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1753 break;
1754 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001755 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301756 pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n",
1757 __func__);
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001758 if (data->payload_size >= (2 * sizeof(uint32_t))) {
1759 num_modules = payload[1];
1760 pr_debug("%s: Num modules %d\n", __func__,
1761 num_modules);
1762 if (payload[0]) {
1763 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
1764 __func__, payload[0]);
1765 } else if (num_modules > MAX_MODULES_IN_TOPO) {
1766 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n",
1767 __func__, num_modules);
1768 } else {
1769 ret = adm_process_get_topo_list_response(
1770 data->opcode, copp_idx,
1771 num_modules, payload,
1772 data->payload_size);
1773 if (ret)
1774 pr_err("%s: Failed to process get topo modules list response, error %d\n",
1775 __func__, ret);
1776 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301777 } else {
Vignesh Kulothungan4965b8d2019-03-16 18:26:22 -07001778 pr_err("%s: Invalid payload size %d\n",
1779 __func__, data->payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301780 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08001781 atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
1782 payload[0]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301783 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1784 break;
1785 case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
1786 pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
1787 __func__);
1788 atomic_set(&this_adm.mem_map_handles[
1789 atomic_read(&this_adm.mem_map_index)],
1790 *payload);
1791 atomic_set(&this_adm.adm_stat, 0);
1792 wake_up(&this_adm.adm_wait);
1793 break;
1794 default:
1795 pr_err("%s: Unknown cmd:0x%x\n", __func__,
1796 data->opcode);
1797 break;
1798 }
1799 }
1800 return 0;
1801}
1802
1803static int adm_memory_map_regions(phys_addr_t *buf_add, uint32_t mempool_id,
1804 uint32_t *bufsz, uint32_t bufcnt)
1805{
1806 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
1807 struct avs_shared_map_region_payload *mregions = NULL;
1808 void *mmap_region_cmd = NULL;
1809 void *payload = NULL;
1810 int ret = 0;
1811 int i = 0;
1812 int cmd_size = 0;
1813
1814 pr_debug("%s:\n", __func__);
1815 if (this_adm.apr == NULL) {
1816 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
1817 0xFFFFFFFF, &this_adm);
1818 if (this_adm.apr == NULL) {
1819 pr_err("%s: Unable to register ADM\n", __func__);
1820 ret = -ENODEV;
1821 return ret;
1822 }
1823 rtac_set_adm_handle(this_adm.apr);
1824 }
1825
1826 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
1827 + sizeof(struct avs_shared_map_region_payload)
1828 * bufcnt;
1829
1830 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1831 if (!mmap_region_cmd)
1832 return -ENOMEM;
1833
1834 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)mmap_region_cmd;
1835 mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1836 APR_HDR_LEN(APR_HDR_SIZE),
1837 APR_PKT_VER);
1838 mmap_regions->hdr.pkt_size = cmd_size;
1839 mmap_regions->hdr.src_port = 0;
1840
1841 mmap_regions->hdr.dest_port = 0;
1842 mmap_regions->hdr.token = 0;
1843 mmap_regions->hdr.opcode = ADM_CMD_SHARED_MEM_MAP_REGIONS;
1844 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL & 0x00ff;
1845 mmap_regions->num_regions = bufcnt & 0x00ff;
1846 mmap_regions->property_flag = 0x00;
1847
1848 pr_debug("%s: map_regions->num_regions = %d\n", __func__,
1849 mmap_regions->num_regions);
1850 payload = ((u8 *) mmap_region_cmd +
1851 sizeof(struct avs_cmd_shared_mem_map_regions));
1852 mregions = (struct avs_shared_map_region_payload *)payload;
1853
1854 for (i = 0; i < bufcnt; i++) {
1855 mregions->shm_addr_lsw = lower_32_bits(buf_add[i]);
1856 mregions->shm_addr_msw =
1857 msm_audio_populate_upper_32_bits(buf_add[i]);
1858 mregions->mem_size_bytes = bufsz[i];
1859 ++mregions;
1860 }
1861
1862 atomic_set(&this_adm.adm_stat, -1);
1863 ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
1864 if (ret < 0) {
1865 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1866 mmap_regions->hdr.opcode, ret);
1867 ret = -EINVAL;
1868 goto fail_cmd;
1869 }
1870
1871 ret = wait_event_timeout(this_adm.adm_wait,
1872 atomic_read(&this_adm.adm_stat) >= 0,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001873 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301874 if (!ret) {
1875 pr_err("%s: timeout. waited for memory_map\n", __func__);
1876 ret = -EINVAL;
1877 goto fail_cmd;
1878 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1879 pr_err("%s: DSP returned error[%s]\n",
1880 __func__, adsp_err_get_err_str(
1881 atomic_read(&this_adm.adm_stat)));
1882 ret = adsp_err_get_lnx_err_code(
1883 atomic_read(&this_adm.adm_stat));
1884 goto fail_cmd;
1885 }
1886fail_cmd:
1887 kfree(mmap_region_cmd);
1888 return ret;
1889}
1890
1891static int adm_memory_unmap_regions(void)
1892{
1893 struct avs_cmd_shared_mem_unmap_regions unmap_regions;
1894 int ret = 0;
1895
1896 pr_debug("%s:\n", __func__);
1897 if (this_adm.apr == NULL) {
1898 pr_err("%s: APR handle NULL\n", __func__);
1899 return -EINVAL;
1900 }
1901
1902 unmap_regions.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1903 APR_HDR_LEN(APR_HDR_SIZE),
1904 APR_PKT_VER);
1905 unmap_regions.hdr.pkt_size = sizeof(unmap_regions);
1906 unmap_regions.hdr.src_port = 0;
1907 unmap_regions.hdr.dest_port = 0;
1908 unmap_regions.hdr.token = 0;
1909 unmap_regions.hdr.opcode = ADM_CMD_SHARED_MEM_UNMAP_REGIONS;
1910 unmap_regions.mem_map_handle = atomic_read(&this_adm.
1911 mem_map_handles[atomic_read(&this_adm.mem_map_index)]);
1912 atomic_set(&this_adm.adm_stat, -1);
1913 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &unmap_regions);
1914 if (ret < 0) {
1915 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1916 unmap_regions.hdr.opcode, ret);
1917 ret = -EINVAL;
1918 goto fail_cmd;
1919 }
1920
1921 ret = wait_event_timeout(this_adm.adm_wait,
1922 atomic_read(&this_adm.adm_stat) >= 0,
Vignesh Kulothungan0fcf2af2018-09-20 17:43:49 -07001923 msecs_to_jiffies(TIMEOUT_MS));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301924 if (!ret) {
1925 pr_err("%s: timeout. waited for memory_unmap\n",
1926 __func__);
1927 ret = -EINVAL;
1928 goto fail_cmd;
1929 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1930 pr_err("%s: DSP returned error[%s]\n",
1931 __func__, adsp_err_get_err_str(
1932 atomic_read(&this_adm.adm_stat)));
1933 ret = adsp_err_get_lnx_err_code(
1934 atomic_read(&this_adm.adm_stat));
1935 goto fail_cmd;
1936 } else {
1937 pr_debug("%s: Unmap handle 0x%x succeeded\n", __func__,
1938 unmap_regions.mem_map_handle);
1939 }
1940fail_cmd:
1941 return ret;
1942}
1943
1944static int remap_cal_data(struct cal_block_data *cal_block, int cal_index)
1945{
1946 int ret = 0;
1947
Banajit Goswami08bb7362017-11-03 22:48:23 -07001948 if (cal_block->map_data.dma_buf == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301949 pr_err("%s: No ION allocation for cal index %d!\n",
1950 __func__, cal_index);
1951 ret = -EINVAL;
1952 goto done;
1953 }
1954
1955 if ((cal_block->map_data.map_size > 0) &&
1956 (cal_block->map_data.q6map_handle == 0)) {
1957 atomic_set(&this_adm.mem_map_index, cal_index);
1958 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
1959 (uint32_t *)&cal_block->map_data.map_size, 1);
1960 if (ret < 0) {
1961 pr_err("%s: ADM mmap did not work! size = %zd ret %d\n",
1962 __func__,
1963 cal_block->map_data.map_size, ret);
1964 pr_debug("%s: ADM mmap did not work! addr = 0x%pK, size = %zd ret %d\n",
1965 __func__,
1966 &cal_block->cal_data.paddr,
1967 cal_block->map_data.map_size, ret);
1968 goto done;
1969 }
1970 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
1971 mem_map_handles[cal_index]);
1972 }
1973done:
1974 return ret;
1975}
1976
1977static void send_adm_custom_topology(void)
1978{
1979 struct cal_block_data *cal_block = NULL;
1980 struct cmd_set_topologies adm_top;
1981 int cal_index = ADM_CUSTOM_TOP_CAL;
1982 int result;
1983
1984 if (this_adm.cal_data[cal_index] == NULL)
1985 goto done;
1986
1987 mutex_lock(&this_adm.cal_data[cal_index]->lock);
1988 if (!this_adm.set_custom_topology)
1989 goto unlock;
1990 this_adm.set_custom_topology = 0;
1991
1992 cal_block = cal_utils_get_only_cal_block(this_adm.cal_data[cal_index]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07001993 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301994 goto unlock;
1995
1996 pr_debug("%s: Sending cal_index %d\n", __func__, cal_index);
1997
1998 result = remap_cal_data(cal_block, cal_index);
1999 if (result) {
2000 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2001 __func__, cal_index);
2002 goto unlock;
2003 }
2004 atomic_set(&this_adm.mem_map_index, cal_index);
2005 atomic_set(&this_adm.mem_map_handles[cal_index],
2006 cal_block->map_data.q6map_handle);
2007
2008 if (cal_block->cal_data.size == 0) {
2009 pr_debug("%s: No ADM cal to send\n", __func__);
2010 goto unlock;
2011 }
2012
2013 adm_top.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2014 APR_HDR_LEN(20), APR_PKT_VER);
2015 adm_top.hdr.pkt_size = sizeof(adm_top);
2016 adm_top.hdr.src_svc = APR_SVC_ADM;
2017 adm_top.hdr.src_domain = APR_DOMAIN_APPS;
2018 adm_top.hdr.src_port = 0;
2019 adm_top.hdr.dest_svc = APR_SVC_ADM;
2020 adm_top.hdr.dest_domain = APR_DOMAIN_ADSP;
2021 adm_top.hdr.dest_port = 0;
2022 adm_top.hdr.token = 0;
2023 adm_top.hdr.opcode = ADM_CMD_ADD_TOPOLOGIES;
2024 adm_top.payload_addr_lsw = lower_32_bits(cal_block->cal_data.paddr);
2025 adm_top.payload_addr_msw = msm_audio_populate_upper_32_bits(
2026 cal_block->cal_data.paddr);
2027 adm_top.mem_map_handle = cal_block->map_data.q6map_handle;
2028 adm_top.payload_size = cal_block->cal_data.size;
2029
2030 atomic_set(&this_adm.adm_stat, -1);
2031 pr_debug("%s: Sending ADM_CMD_ADD_TOPOLOGIES payload = 0x%pK, size = %d\n",
2032 __func__, &cal_block->cal_data.paddr,
2033 adm_top.payload_size);
2034 result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_top);
2035 if (result < 0) {
2036 pr_err("%s: Set topologies failed payload size = %zd result %d\n",
2037 __func__, cal_block->cal_data.size, result);
2038 goto unlock;
2039 }
2040 /* Wait for the callback */
2041 result = wait_event_timeout(this_adm.adm_wait,
2042 atomic_read(&this_adm.adm_stat) >= 0,
2043 msecs_to_jiffies(TIMEOUT_MS));
2044 if (!result) {
2045 pr_err("%s: Set topologies timed out payload size = %zd\n",
2046 __func__, cal_block->cal_data.size);
2047 goto unlock;
2048 } else if (atomic_read(&this_adm.adm_stat) > 0) {
2049 pr_err("%s: DSP returned error[%s]\n",
2050 __func__, adsp_err_get_err_str(
2051 atomic_read(&this_adm.adm_stat)));
2052 result = adsp_err_get_lnx_err_code(
2053 atomic_read(&this_adm.adm_stat));
2054 goto unlock;
2055 }
2056unlock:
2057 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2058done:
2059 return;
2060}
2061
2062static int send_adm_cal_block(int port_id, int copp_idx,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002063 struct cal_block_data *cal_block, int perf_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302064{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002065 struct mem_mapping_hdr mem_hdr;
2066 int payload_size = 0;
2067 int port_idx = 0;
2068 int topology = 0;
2069 int result = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302070
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002071 pr_debug("%s: Port id 0x%x,\n", __func__, port_id);
2072
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302073 if (!cal_block) {
2074 pr_debug("%s: No ADM cal to send for port_id = 0x%x!\n",
2075 __func__, port_id);
2076 result = -EINVAL;
2077 goto done;
2078 }
2079 if (cal_block->cal_data.size <= 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002080 pr_debug("%s: No ADM cal sent for port_id = 0x%x!\n", __func__,
2081 port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302082 result = -EINVAL;
2083 goto done;
2084 }
2085
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002086 memset(&mem_hdr, 0, sizeof(mem_hdr));
2087 port_id = afe_convert_virtual_to_portid(port_id);
2088 port_idx = adm_validate_and_get_port_index(port_id);
2089 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
2090 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2091 return -EINVAL;
2092 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
2093 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
2094 return -EINVAL;
2095 }
2096
2097 topology = atomic_read(&this_adm.copp.topology[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302098 if (perf_mode == LEGACY_PCM_MODE &&
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002099 topology == DS2_ADM_COPP_TOPOLOGY_ID) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302100 pr_err("%s: perf_mode %d, topology 0x%x\n", __func__, perf_mode,
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002101 topology);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302102 goto done;
2103 }
2104
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002105 mem_hdr.data_payload_addr_lsw =
2106 lower_32_bits(cal_block->cal_data.paddr);
2107 mem_hdr.data_payload_addr_msw =
2108 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
2109 mem_hdr.mem_map_handle = cal_block->map_data.q6map_handle;
2110 payload_size = cal_block->cal_data.size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302111
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002112 adm_set_pp_params(port_id, copp_idx, &mem_hdr, NULL, payload_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302113
2114done:
2115 return result;
2116}
2117
2118static struct cal_block_data *adm_find_cal_by_path(int cal_index, int path)
2119{
2120 struct list_head *ptr, *next;
2121 struct cal_block_data *cal_block = NULL;
2122 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2123 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2124
2125 pr_debug("%s:\n", __func__);
2126
2127 list_for_each_safe(ptr, next,
2128 &this_adm.cal_data[cal_index]->cal_blocks) {
2129
2130 cal_block = list_entry(ptr,
2131 struct cal_block_data, list);
2132
Vikram Panduranga770b8382017-09-27 12:17:36 -07002133 if (cal_utils_is_cal_stale(cal_block))
2134 continue;
2135
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302136 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002137 cal_index == ADM_LSM_AUDPROC_CAL ||
2138 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302139 audproc_cal_info = cal_block->cal_info;
2140 if ((audproc_cal_info->path == path) &&
2141 (cal_block->cal_data.size > 0))
2142 return cal_block;
2143 } else if (cal_index == ADM_AUDVOL_CAL) {
2144 audvol_cal_info = cal_block->cal_info;
2145 if ((audvol_cal_info->path == path) &&
2146 (cal_block->cal_data.size > 0))
2147 return cal_block;
2148 }
2149 }
2150 pr_debug("%s: Can't find ADM cal for cal_index %d, path %d\n",
2151 __func__, cal_index, path);
2152 return NULL;
2153}
2154
2155static struct cal_block_data *adm_find_cal_by_app_type(int cal_index, int path,
2156 int app_type)
2157{
2158 struct list_head *ptr, *next;
2159 struct cal_block_data *cal_block = NULL;
2160 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2161 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2162
2163 pr_debug("%s\n", __func__);
2164
2165 list_for_each_safe(ptr, next,
2166 &this_adm.cal_data[cal_index]->cal_blocks) {
2167
2168 cal_block = list_entry(ptr,
2169 struct cal_block_data, list);
2170
Vikram Panduranga770b8382017-09-27 12:17:36 -07002171 if (cal_utils_is_cal_stale(cal_block))
2172 continue;
2173
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302174 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002175 cal_index == ADM_LSM_AUDPROC_CAL ||
2176 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302177 audproc_cal_info = cal_block->cal_info;
2178 if ((audproc_cal_info->path == path) &&
2179 (audproc_cal_info->app_type == app_type) &&
2180 (cal_block->cal_data.size > 0))
2181 return cal_block;
2182 } else if (cal_index == ADM_AUDVOL_CAL) {
2183 audvol_cal_info = cal_block->cal_info;
2184 if ((audvol_cal_info->path == path) &&
2185 (audvol_cal_info->app_type == app_type) &&
2186 (cal_block->cal_data.size > 0))
2187 return cal_block;
2188 }
2189 }
2190 pr_debug("%s: Can't find ADM cali for cal_index %d, path %d, app %d, defaulting to search by path\n",
2191 __func__, cal_index, path, app_type);
2192 return adm_find_cal_by_path(cal_index, path);
2193}
2194
2195
2196static struct cal_block_data *adm_find_cal(int cal_index, int path,
2197 int app_type, int acdb_id,
2198 int sample_rate)
2199{
2200 struct list_head *ptr, *next;
2201 struct cal_block_data *cal_block = NULL;
2202 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2203 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2204
2205 pr_debug("%s:\n", __func__);
2206
2207 list_for_each_safe(ptr, next,
2208 &this_adm.cal_data[cal_index]->cal_blocks) {
2209
2210 cal_block = list_entry(ptr,
2211 struct cal_block_data, list);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002212 if (cal_utils_is_cal_stale(cal_block))
2213 continue;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302214
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302215 if (cal_index == ADM_AUDPROC_CAL ||
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002216 cal_index == ADM_LSM_AUDPROC_CAL ||
2217 cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302218 audproc_cal_info = cal_block->cal_info;
2219 if ((audproc_cal_info->path == path) &&
2220 (audproc_cal_info->app_type == app_type) &&
2221 (audproc_cal_info->acdb_id == acdb_id) &&
2222 (audproc_cal_info->sample_rate == sample_rate) &&
2223 (cal_block->cal_data.size > 0))
2224 return cal_block;
2225 } else if (cal_index == ADM_AUDVOL_CAL) {
2226 audvol_cal_info = cal_block->cal_info;
2227 if ((audvol_cal_info->path == path) &&
2228 (audvol_cal_info->app_type == app_type) &&
2229 (audvol_cal_info->acdb_id == acdb_id) &&
2230 (cal_block->cal_data.size > 0))
2231 return cal_block;
2232 }
2233 }
2234 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",
2235 __func__, cal_index, path, app_type, acdb_id, sample_rate);
2236 return adm_find_cal_by_app_type(cal_index, path, app_type);
2237}
2238
2239static int adm_remap_and_send_cal_block(int cal_index, int port_id,
2240 int copp_idx, struct cal_block_data *cal_block, int perf_mode,
2241 int app_type, int acdb_id, int sample_rate)
2242{
2243 int ret = 0;
2244
2245 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
2246 ret = remap_cal_data(cal_block, cal_index);
2247 if (ret) {
2248 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2249 __func__, cal_index);
2250 goto done;
2251 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08002252 ret = send_adm_cal_block(port_id, copp_idx, cal_block, perf_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302253 if (ret < 0)
2254 pr_debug("%s: No cal sent for cal_index %d, port_id = 0x%x! ret %d sample_rate %d\n",
2255 __func__, cal_index, port_id, ret, sample_rate);
2256done:
2257 return ret;
2258}
2259
2260static void send_adm_cal_type(int cal_index, int path, int port_id,
2261 int copp_idx, int perf_mode, int app_type,
2262 int acdb_id, int sample_rate)
2263{
2264 struct cal_block_data *cal_block = NULL;
2265 int ret;
2266
2267 pr_debug("%s: cal index %d\n", __func__, cal_index);
2268
2269 if (this_adm.cal_data[cal_index] == NULL) {
2270 pr_debug("%s: cal_index %d not allocated!\n",
2271 __func__, cal_index);
2272 goto done;
2273 }
2274
2275 mutex_lock(&this_adm.cal_data[cal_index]->lock);
2276 cal_block = adm_find_cal(cal_index, path, app_type, acdb_id,
2277 sample_rate);
2278 if (cal_block == NULL)
2279 goto unlock;
2280
2281 ret = adm_remap_and_send_cal_block(cal_index, port_id, copp_idx,
2282 cal_block, perf_mode, app_type, acdb_id, sample_rate);
Vikram Panduranga770b8382017-09-27 12:17:36 -07002283
2284 cal_utils_mark_cal_used(cal_block);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302285unlock:
2286 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2287done:
2288 return;
2289}
2290
2291static int get_cal_path(int path)
2292{
2293 if (path == 0x1)
2294 return RX_DEVICE;
2295 else
2296 return TX_DEVICE;
2297}
2298
2299static void send_adm_cal(int port_id, int copp_idx, int path, int perf_mode,
Aditya Bavanari5106b562018-01-08 13:16:32 +05302300 int app_type, int acdb_id, int sample_rate,
2301 int passthr_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302302{
2303 pr_debug("%s: port id 0x%x copp_idx %d\n", __func__, port_id, copp_idx);
2304
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002305 if (passthr_mode != LISTEN) {
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302306 send_adm_cal_type(ADM_AUDPROC_CAL, path, port_id, copp_idx,
2307 perf_mode, app_type, acdb_id, sample_rate);
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002308 } else {
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302309 send_adm_cal_type(ADM_LSM_AUDPROC_CAL, path, port_id, copp_idx,
2310 perf_mode, app_type, acdb_id, sample_rate);
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07002311
2312 send_adm_cal_type(ADM_LSM_AUDPROC_PERSISTENT_CAL, path,
2313 port_id, copp_idx, perf_mode, app_type,
2314 acdb_id, sample_rate);
2315 }
2316
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302317 send_adm_cal_type(ADM_AUDVOL_CAL, path, port_id, copp_idx, perf_mode,
2318 app_type, acdb_id, sample_rate);
2319}
2320
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302321/**
2322 * adm_connect_afe_port -
2323 * command to send ADM connect AFE port
2324 *
2325 * @mode: value of mode for ADM connect AFE
2326 * @session_id: session active to connect
2327 * @port_id: Port ID number
2328 *
2329 * Returns 0 on success or error on failure
2330 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302331int adm_connect_afe_port(int mode, int session_id, int port_id)
2332{
2333 struct adm_cmd_connect_afe_port_v5 cmd;
2334 int ret = 0;
2335 int port_idx, copp_idx = 0;
2336
2337 pr_debug("%s: port_id: 0x%x session id:%d mode:%d\n", __func__,
2338 port_id, session_id, mode);
2339
2340 port_id = afe_convert_virtual_to_portid(port_id);
2341 port_idx = adm_validate_and_get_port_index(port_id);
2342 if (port_idx < 0) {
2343 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2344 return -EINVAL;
2345 }
2346
2347 if (this_adm.apr == NULL) {
2348 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
2349 0xFFFFFFFF, &this_adm);
2350 if (this_adm.apr == NULL) {
2351 pr_err("%s: Unable to register ADM\n", __func__);
2352 ret = -ENODEV;
2353 return ret;
2354 }
2355 rtac_set_adm_handle(this_adm.apr);
2356 }
2357 pr_debug("%s: Port ID 0x%x, index %d\n", __func__, port_id, port_idx);
2358
2359 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2360 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2361 cmd.hdr.pkt_size = sizeof(cmd);
2362 cmd.hdr.src_svc = APR_SVC_ADM;
2363 cmd.hdr.src_domain = APR_DOMAIN_APPS;
2364 cmd.hdr.src_port = port_id;
2365 cmd.hdr.dest_svc = APR_SVC_ADM;
2366 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
2367 cmd.hdr.dest_port = 0; /* Ignored */
2368 cmd.hdr.token = port_idx << 16 | copp_idx;
2369 cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V5;
2370
2371 cmd.mode = mode;
2372 cmd.session_id = session_id;
2373 cmd.afe_port_id = port_id;
2374
2375 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
2376 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
2377 if (ret < 0) {
2378 pr_err("%s: ADM enable for port_id: 0x%x failed ret %d\n",
2379 __func__, port_id, ret);
2380 ret = -EINVAL;
2381 goto fail_cmd;
2382 }
2383 /* Wait for the callback with copp id */
2384 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
2385 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
2386 msecs_to_jiffies(TIMEOUT_MS));
2387 if (!ret) {
2388 pr_err("%s: ADM connect timedout for port_id: 0x%x\n",
2389 __func__, port_id);
2390 ret = -EINVAL;
2391 goto fail_cmd;
2392 } else if (atomic_read(&this_adm.copp.stat
2393 [port_idx][copp_idx]) > 0) {
2394 pr_err("%s: DSP returned error[%s]\n",
2395 __func__, adsp_err_get_err_str(
2396 atomic_read(&this_adm.copp.stat
2397 [port_idx][copp_idx])));
2398 ret = adsp_err_get_lnx_err_code(
2399 atomic_read(&this_adm.copp.stat
2400 [port_idx][copp_idx]));
2401 goto fail_cmd;
2402 }
2403 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
2404 return 0;
2405
2406fail_cmd:
2407
2408 return ret;
2409}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302410EXPORT_SYMBOL(adm_connect_afe_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302411
2412int adm_arrange_mch_map(struct adm_cmd_device_open_v5 *open, int path,
Rohit kumar2054b692019-02-01 18:01:12 +05302413 int channel_mode, int port_idx)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302414{
2415 int rc = 0, idx;
2416
Bhalchandra Gajareeed46bd2018-05-15 16:48:07 -07002417 pr_debug("%s: channel mode %d", __func__, channel_mode);
2418
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302419 memset(open->dev_channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
2420 switch (path) {
2421 case ADM_PATH_PLAYBACK:
2422 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2423 break;
2424 case ADM_PATH_LIVE_REC:
2425 case ADM_PATH_NONLIVE_REC:
2426 idx = ADM_MCH_MAP_IDX_REC;
2427 break;
2428 default:
2429 goto non_mch_path;
2430 };
Rohit kumar2054b692019-02-01 18:01:12 +05302431
2432 if ((open->dev_num_channel > 2) &&
2433 (port_channel_map[port_idx].set_channel_map ||
2434 multi_ch_maps[idx].set_channel_map)) {
2435 if (port_channel_map[port_idx].set_channel_map)
2436 memcpy(open->dev_channel_mapping,
2437 port_channel_map[port_idx].channel_mapping,
2438 PCM_FORMAT_MAX_NUM_CHANNEL);
2439 else
2440 memcpy(open->dev_channel_mapping,
2441 multi_ch_maps[idx].channel_mapping,
2442 PCM_FORMAT_MAX_NUM_CHANNEL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302443 } else {
2444 if (channel_mode == 1) {
2445 open->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2446 } else if (channel_mode == 2) {
2447 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2448 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2449 } else if (channel_mode == 3) {
2450 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2451 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2452 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2453 } else if (channel_mode == 4) {
2454 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2455 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2456 open->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2457 open->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2458 } else if (channel_mode == 5) {
2459 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2460 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2461 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2462 open->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2463 open->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2464 } else if (channel_mode == 6) {
2465 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2466 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2467 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2468 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2469 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2470 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2471 } else if (channel_mode == 7) {
2472 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2473 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2474 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2475 open->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
2476 open->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2477 open->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2478 open->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2479 } else if (channel_mode == 8) {
2480 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2481 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2482 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2483 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2484 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2485 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2486 open->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2487 open->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2488 } else {
2489 pr_err("%s: invalid num_chan %d\n", __func__,
2490 channel_mode);
2491 rc = -EINVAL;
2492 goto inval_ch_mod;
2493 }
2494 }
2495
2496non_mch_path:
2497inval_ch_mod:
2498 return rc;
2499}
2500
2501int adm_arrange_mch_ep2_map(struct adm_cmd_device_open_v6 *open_v6,
2502 int channel_mode)
2503{
2504 int rc = 0;
2505
2506 memset(open_v6->dev_channel_mapping_eid2, 0,
2507 PCM_FORMAT_MAX_NUM_CHANNEL);
2508
2509 if (channel_mode == 1) {
2510 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FC;
2511 } else if (channel_mode == 2) {
2512 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2513 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2514 } else if (channel_mode == 3) {
2515 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2516 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2517 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2518 } else if (channel_mode == 4) {
2519 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2520 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2521 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LS;
2522 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_RS;
2523 } else if (channel_mode == 5) {
2524 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2525 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2526 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2527 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_LS;
2528 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_RS;
2529 } else if (channel_mode == 6) {
2530 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2531 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2532 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
2533 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2534 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2535 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2536 } else if (channel_mode == 8) {
2537 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2538 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2539 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
2540 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2541 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2542 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2543 open_v6->dev_channel_mapping_eid2[6] = PCM_CHANNEL_LB;
2544 open_v6->dev_channel_mapping_eid2[7] = PCM_CHANNEL_RB;
2545 } else {
2546 pr_err("%s: invalid num_chan %d\n", __func__,
2547 channel_mode);
2548 rc = -EINVAL;
2549 }
2550
2551 return rc;
2552}
2553
Dieter Luecking50c55352018-09-28 14:29:17 +02002554static int adm_arrange_mch_map_v8(
2555 struct adm_device_endpoint_payload *ep_payload,
Rohit kumar2054b692019-02-01 18:01:12 +05302556 int path, int channel_mode, int port_idx)
Dieter Luecking50c55352018-09-28 14:29:17 +02002557{
2558 int rc = 0, idx;
2559
2560 memset(ep_payload->dev_channel_mapping,
2561 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2562 switch (path) {
2563 case ADM_PATH_PLAYBACK:
2564 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2565 break;
2566 case ADM_PATH_LIVE_REC:
2567 case ADM_PATH_NONLIVE_REC:
2568 idx = ADM_MCH_MAP_IDX_REC;
2569 break;
2570 default:
2571 goto non_mch_path;
2572 };
2573
2574 if ((ep_payload->dev_num_channel > 2) &&
Rohit kumar2054b692019-02-01 18:01:12 +05302575 (port_channel_map[port_idx].set_channel_map ||
2576 multi_ch_maps[idx].set_channel_map)) {
2577 if (port_channel_map[port_idx].set_channel_map)
2578 memcpy(ep_payload->dev_channel_mapping,
2579 port_channel_map[port_idx].channel_mapping,
2580 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2581 else
2582 memcpy(ep_payload->dev_channel_mapping,
2583 multi_ch_maps[idx].channel_mapping,
2584 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
Dieter Luecking50c55352018-09-28 14:29:17 +02002585 } else {
2586 if (channel_mode == 1) {
2587 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2588 } else if (channel_mode == 2) {
2589 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2590 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2591 } else if (channel_mode == 3) {
2592 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2593 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2594 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2595 } else if (channel_mode == 4) {
2596 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2597 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2598 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2599 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2600 } else if (channel_mode == 5) {
2601 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2602 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2603 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2604 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2605 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2606 } else if (channel_mode == 6) {
2607 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2608 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2609 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2610 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2611 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2612 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2613 } else if (channel_mode == 7) {
2614 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2615 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2616 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2617 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
2618 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2619 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2620 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2621 } else if (channel_mode == 8) {
2622 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2623 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2624 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2625 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2626 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2627 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2628 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2629 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2630 } else if (channel_mode == 10) {
2631 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2632 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2633 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2634 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2635 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2636 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2637 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2638 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2639 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2640 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2641 } else if (channel_mode == 12) {
2642 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2643 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2644 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2645 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2646 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2647 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2648 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2649 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2650 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2651 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2652 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2653 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
Chaithanya Krishna Bacharaju3dd8fdf2019-05-02 12:14:37 +05302654 } else if (channel_mode == 14) {
2655 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2656 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2657 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2658 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2659 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2660 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2661 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2662 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2663 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2664 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2665 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2666 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2667 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2668 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
Dieter Luecking50c55352018-09-28 14:29:17 +02002669 } else if (channel_mode == 16) {
2670 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2671 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2672 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2673 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2674 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2675 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2676 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
2677 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
2678 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2679 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2680 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2681 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2682 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2683 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2684 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2685 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
2686 } else {
2687 pr_err("%s: invalid num_chan %d\n", __func__,
2688 channel_mode);
2689 rc = -EINVAL;
2690 goto inval_ch_mod;
2691 }
2692 }
2693
2694non_mch_path:
2695inval_ch_mod:
2696 return rc;
2697}
2698
2699static int adm_arrange_mch_ep2_map_v8(
2700 struct adm_device_endpoint_payload *ep_payload,
2701 int channel_mode)
2702{
2703 int rc = 0;
2704
2705 memset(ep_payload->dev_channel_mapping, 0,
2706 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
2707
2708 if (channel_mode == 1) {
2709 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2710 } else if (channel_mode == 2) {
2711 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2712 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2713 } else if (channel_mode == 3) {
2714 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2715 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2716 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2717 } else if (channel_mode == 4) {
2718 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2719 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2720 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2721 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2722 } else if (channel_mode == 5) {
2723 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2724 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2725 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2726 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2727 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2728 } else if (channel_mode == 6) {
2729 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2730 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2731 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2732 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2733 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2734 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2735 } else if (channel_mode == 8) {
2736 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2737 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2738 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2739 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2740 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2741 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2742 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2743 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2744 } else if (channel_mode == 10) {
2745 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2746 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2747 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2748 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2749 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2750 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2751 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2752 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2753 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
Ralf Herzfb81b6e2018-12-12 10:36:11 +01002754 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
Dieter Luecking50c55352018-09-28 14:29:17 +02002755 } else if (channel_mode == 12) {
2756 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2757 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2758 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2759 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2760 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2761 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2762 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2763 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2764 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
2765 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
2766 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
2767 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
2768 } else if (channel_mode == 16) {
2769 ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2770 ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2771 ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2772 ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2773 ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2774 ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2775 ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2776 ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2777 ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
Ralf Herzfb81b6e2018-12-12 10:36:11 +01002778 ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TS;
Dieter Luecking50c55352018-09-28 14:29:17 +02002779 ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
2780 ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
2781 ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
2782 ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
2783 ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
2784 ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
2785 } else {
2786 pr_err("%s: invalid num_chan %d\n", __func__,
2787 channel_mode);
2788 rc = -EINVAL;
2789 }
2790
2791 return rc;
2792}
Dhananjay Kumar43034392019-01-16 21:57:58 +05302793
2794static int adm_copp_set_ec_ref_mfc_cfg(int port_id, int copp_idx,
2795 int sample_rate, int bps,
2796 int in_channels, int out_channels)
2797{
2798 struct audproc_mfc_param_media_fmt mfc_cfg;
2799 struct param_hdr_v3 param_hdr;
2800 u16 *chmixer_params = NULL;
2801 int rc = 0, i = 0, j = 0, param_index = 0, param_size = 0;
2802 struct adm_device_endpoint_payload ep_payload = {0, 0, 0, {0}};
2803
2804 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
2805 memset(&ep_payload, 0, sizeof(ep_payload));
2806 memset(&param_hdr, 0, sizeof(param_hdr));
2807
2808 param_hdr.module_id = AUDPROC_MODULE_ID_MFC_EC_REF;
2809 param_hdr.instance_id = INSTANCE_ID_0;
2810
2811 pr_debug("%s: port_id %d copp_idx %d SR %d, BW %d in_ch %d out_ch %d\n",
2812 __func__, port_id, copp_idx, sample_rate,
2813 bps, in_channels, out_channels);
2814
Dhananjay Kumar3d61b362019-03-01 15:47:56 +05302815 if (out_channels <= 0 || out_channels > AUDPROC_MFC_OUT_CHANNELS_MAX) {
2816 pr_err("%s: unsupported out channels=%d\n", __func__, out_channels);
2817 return -EINVAL;
2818 }
2819
Dhananjay Kumar43034392019-01-16 21:57:58 +05302820 /* 1. Update Media Format */
2821 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
2822 param_hdr.param_size = sizeof(mfc_cfg);
2823
2824 mfc_cfg.sampling_rate = sample_rate;
2825 mfc_cfg.bits_per_sample = bps;
2826 mfc_cfg.num_channels = out_channels;
2827
2828 ep_payload.dev_num_channel = out_channels;
2829 rc = adm_arrange_mch_ep2_map_v8(&ep_payload, out_channels);
2830 if (rc < 0) {
2831 pr_err("%s: unable to get map for out channels=%d\n",
2832 __func__, out_channels);
2833 return -EINVAL;
2834 }
2835
2836 for (i = 0; i < out_channels; i++)
2837 mfc_cfg.channel_type[i] = (uint16_t) ep_payload.dev_channel_mapping[i];
2838
2839
2840 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx,
2841 param_hdr, (uint8_t *) &mfc_cfg);
2842 if (rc) {
2843 pr_err("%s: Failed to set media format, err %d\n", __func__, rc);
2844 return rc;
2845 }
2846
2847 /* 2. Send Channel Mixer params */
2848 param_size = 2 * (4 + out_channels + in_channels + (out_channels * in_channels));
2849 param_size = round_up(param_size, 4);
2850 param_hdr.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
2851 param_hdr.param_size = param_size;
2852
2853 pr_debug("%s: chmixer param sz = %d\n", __func__, param_size);
2854 chmixer_params = kzalloc(param_size, GFP_KERNEL);
2855 if (!chmixer_params) {
2856 return -ENOMEM;
2857 }
2858 param_index = 2; /* param[0] and [1] represents chmixer rule(always 0) */
2859 chmixer_params[param_index++] = out_channels;
2860 chmixer_params[param_index++] = in_channels;
2861
2862 /* output channel map is same as one set in media format */
2863 for (i = 0; i < out_channels; i++)
2864 chmixer_params[param_index++] = ep_payload.dev_channel_mapping[i];
2865
2866 /* input channel map should be same as one set for ep2 during copp open */
2867 ep_payload.dev_num_channel = in_channels;
2868 rc = adm_arrange_mch_ep2_map_v8(&ep_payload, in_channels);
2869 if (rc < 0) {
2870 pr_err("%s: unable to get in channal map\n", __func__);
2871 goto exit;
2872 }
2873 for (i = 0; i < in_channels; i++)
2874 chmixer_params[param_index++] = ep_payload.dev_channel_mapping[i];
2875
2876 for (i = 0; i < out_channels; i++)
2877 for (j = 0; j < in_channels; j++)
2878 chmixer_params[param_index++] = this_adm.ec_ref_chmixer_weights[i][j];
2879
2880 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx,
2881 param_hdr, (uint8_t *) chmixer_params);
2882 if (rc)
2883 pr_err("%s: Failed to set chmixer params, err %d\n", __func__, rc);
2884
2885exit:
2886 kfree(chmixer_params);
2887 return rc;
2888}
2889
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302890/**
2891 * adm_open -
2892 * command to send ADM open
2893 *
2894 * @port_id: port id number
2895 * @path: direction or ADM path type
2896 * @rate: sample rate of session
2897 * @channel_mode: number of channels set
2898 * @topology: topology active for this session
2899 * @perf_mode: performance mode like LL/ULL/..
2900 * @bit_width: bit width to set for copp
2901 * @app_type: App type used for this session
2902 * @acdb_id: ACDB ID of this device
Surendar Karkae7507512018-07-20 15:46:54 +05302903 * @session_type: type of session
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302904 *
2905 * Returns 0 on success or error on failure
2906 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302907int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
Surendar Karkae7507512018-07-20 15:46:54 +05302908 int perf_mode, uint16_t bit_width, int app_type, int acdb_id,
2909 int session_type)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302910{
2911 struct adm_cmd_device_open_v5 open;
2912 struct adm_cmd_device_open_v6 open_v6;
Dieter Luecking50c55352018-09-28 14:29:17 +02002913 struct adm_cmd_device_open_v8 open_v8;
2914 struct adm_device_endpoint_payload ep1_payload;
2915 struct adm_device_endpoint_payload ep2_payload;
2916 int ep1_payload_size = 0;
2917 int ep2_payload_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302918 int ret = 0;
Asish Bhattacharya34504582017-08-08 12:55:01 +05302919 int port_idx, flags;
2920 int copp_idx = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302921 int tmp_port = q6audio_get_port_id(port_id);
Dieter Luecking50c55352018-09-28 14:29:17 +02002922 void *adm_params = NULL;
2923 int param_size;
Dhananjay Kumar43034392019-01-16 21:57:58 +05302924 int num_ec_ref_rx_chans = this_adm.num_ec_ref_rx_chans;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302925
2926 pr_debug("%s:port %#x path:%d rate:%d mode:%d perf_mode:%d,topo_id %d\n",
2927 __func__, port_id, path, rate, channel_mode, perf_mode,
2928 topology);
2929
2930 port_id = q6audio_convert_virtual_to_portid(port_id);
2931 port_idx = adm_validate_and_get_port_index(port_id);
2932 if (port_idx < 0) {
2933 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2934 return -EINVAL;
2935 }
Dieter Luecking50c55352018-09-28 14:29:17 +02002936 if (channel_mode < 0 || channel_mode > 32) {
2937 pr_err("%s: Invalid channel number 0x%x\n",
2938 __func__, channel_mode);
2939 return -EINVAL;
2940 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302941
2942 if (this_adm.apr == NULL) {
2943 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
2944 0xFFFFFFFF, &this_adm);
2945 if (this_adm.apr == NULL) {
2946 pr_err("%s: Unable to register ADM\n", __func__);
2947 return -ENODEV;
2948 }
2949 rtac_set_adm_handle(this_adm.apr);
2950 }
2951
2952 if (perf_mode == ULL_POST_PROCESSING_PCM_MODE) {
2953 flags = ADM_ULL_POST_PROCESSING_DEVICE_SESSION;
2954 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
2955 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
2956 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
2957 topology = DEFAULT_COPP_TOPOLOGY;
2958 } else if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
2959 flags = ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
2960 topology = NULL_COPP_TOPOLOGY;
2961 rate = ULL_SUPPORTED_SAMPLE_RATE;
2962 bit_width = ULL_SUPPORTED_BITS_PER_SAMPLE;
2963 } else if (perf_mode == LOW_LATENCY_PCM_MODE) {
2964 flags = ADM_LOW_LATENCY_DEVICE_SESSION;
2965 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
2966 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
2967 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
2968 topology = DEFAULT_COPP_TOPOLOGY;
2969 } else {
2970 if ((path == ADM_PATH_COMPRESSED_RX) ||
2971 (path == ADM_PATH_COMPRESSED_TX))
2972 flags = 0;
2973 else
2974 flags = ADM_LEGACY_DEVICE_SESSION;
2975 }
2976
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05302977 if ((topology == VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY) ||
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302978 (topology == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY) ||
kunleiz1529b552019-01-24 17:15:49 +08002979 (topology == VPM_TX_DM_RFECNS_COPP_TOPOLOGY)||
2980 (topology == VPM_TX_DM_FLUENCE_EF_COPP_TOPOLOGY)) {
2981 if ((rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_8K) &&
2982 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_16K) &&
2983 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_32K) &&
2984 (rate != ADM_CMD_COPP_OPEN_SAMPLE_RATE_48K))
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302985 rate = 16000;
kunleiz1529b552019-01-24 17:15:49 +08002986 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302987
kunleizc0cd19e2018-10-18 17:11:35 +08002988 if (topology == VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY)
2989 channel_mode = 1;
2990
Asish Bhattacharya34504582017-08-08 12:55:01 +05302991 /*
2992 * Routing driver reuses the same adm for streams with the same
2993 * app_type, sample_rate etc.
2994 * This isn't allowed for ULL streams as per the DSP interface
2995 */
2996 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE)
2997 copp_idx = adm_get_idx_if_copp_exists(port_idx, topology,
2998 perf_mode,
2999 rate, bit_width,
Surendar Karkae7507512018-07-20 15:46:54 +05303000 app_type, session_type);
Asish Bhattacharya34504582017-08-08 12:55:01 +05303001
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303002 if (copp_idx < 0) {
3003 copp_idx = adm_get_next_available_copp(port_idx);
3004 if (copp_idx >= MAX_COPPS_PER_PORT) {
3005 pr_err("%s: exceeded copp id %d\n",
3006 __func__, copp_idx);
3007 return -EINVAL;
3008 }
3009 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
3010 atomic_set(&this_adm.copp.topology[port_idx][copp_idx],
3011 topology);
3012 atomic_set(&this_adm.copp.mode[port_idx][copp_idx],
3013 perf_mode);
3014 atomic_set(&this_adm.copp.rate[port_idx][copp_idx],
3015 rate);
3016 atomic_set(&this_adm.copp.channels[port_idx][copp_idx],
3017 channel_mode);
3018 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx],
3019 bit_width);
3020 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx],
3021 app_type);
3022 atomic_set(&this_adm.copp.acdb_id[port_idx][copp_idx],
3023 acdb_id);
Surendar Karkae7507512018-07-20 15:46:54 +05303024 atomic_set(&this_adm.copp.session_type[port_idx][copp_idx],
3025 session_type);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303026 set_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3027 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
3028 if ((path != ADM_PATH_COMPRESSED_RX) &&
3029 (path != ADM_PATH_COMPRESSED_TX))
3030 send_adm_custom_topology();
3031 }
3032
3033 if (this_adm.copp.adm_delay[port_idx][copp_idx] &&
3034 perf_mode == LEGACY_PCM_MODE) {
3035 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
3036 1);
3037 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
3038 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
3039 }
3040
3041 /* Create a COPP if port id are not enabled */
3042 if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) {
3043 pr_debug("%s: open ADM: port_idx: %d, copp_idx: %d\n", __func__,
3044 port_idx, copp_idx);
Dieter Luecking50c55352018-09-28 14:29:17 +02003045 if ((topology == SRS_TRUMEDIA_TOPOLOGY_ID) &&
3046 perf_mode == LEGACY_PCM_MODE) {
3047 int res;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303048
Dieter Luecking50c55352018-09-28 14:29:17 +02003049 atomic_set(&this_adm.mem_map_index, ADM_SRS_TRUMEDIA);
3050 msm_dts_srs_tm_ion_memmap(&this_adm.outband_memmap);
3051 res = adm_memory_map_regions(
3052 &this_adm.outband_memmap.paddr, 0,
3053 (uint32_t *)&this_adm.outband_memmap.size, 1);
3054 if (res < 0) {
3055 pr_err("%s: SRS adm_memory_map_regions failed! addr = 0x%pK, size = %d\n",
3056 __func__,
3057 (void *)this_adm.outband_memmap.paddr,
3058 (uint32_t)this_adm.outband_memmap.size);
3059 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303060 }
3061
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303062
Mangesh Kunchamwar9f295c72018-10-08 18:20:41 +05303063 if ((q6core_get_avcs_api_version_per_service(
Dieter Luecking50c55352018-09-28 14:29:17 +02003064 APRV2_IDS_SERVICE_ID_ADSP_ADM_V) >=
Mangesh Kunchamwar9f295c72018-10-08 18:20:41 +05303065 ADSP_ADM_API_VERSION_V3) &&
3066 q6core_use_Q6_32ch_support()) {
Dieter Luecking50c55352018-09-28 14:29:17 +02003067 memset(&open_v8, 0, sizeof(open_v8));
3068 memset(&ep1_payload, 0, sizeof(ep1_payload));
3069 memset(&ep2_payload, 0, sizeof(ep2_payload));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303070
Dieter Luecking50c55352018-09-28 14:29:17 +02003071 open_v8.hdr.hdr_field = APR_HDR_FIELD(
3072 APR_MSG_TYPE_SEQ_CMD,
3073 APR_HDR_LEN(APR_HDR_SIZE),
3074 APR_PKT_VER);
3075 open_v8.hdr.src_svc = APR_SVC_ADM;
3076 open_v8.hdr.src_domain = APR_DOMAIN_APPS;
3077 open_v8.hdr.src_port = tmp_port;
3078 open_v8.hdr.dest_svc = APR_SVC_ADM;
3079 open_v8.hdr.dest_domain = APR_DOMAIN_ADSP;
3080 open_v8.hdr.dest_port = tmp_port;
3081 open_v8.hdr.token = port_idx << 16 | copp_idx;
3082 open_v8.hdr.opcode = ADM_CMD_DEVICE_OPEN_V8;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303083
Dieter Luecking50c55352018-09-28 14:29:17 +02003084 if (this_adm.native_mode != 0) {
3085 open_v8.flags = flags |
3086 (this_adm.native_mode << 11);
3087 this_adm.native_mode = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303088 } else {
Dieter Luecking50c55352018-09-28 14:29:17 +02003089 open_v8.flags = flags;
3090 }
3091 open_v8.mode_of_operation = path;
3092 open_v8.endpoint_id_1 = tmp_port;
3093 open_v8.endpoint_id_2 = 0xFFFF;
3094 open_v8.endpoint_id_3 = 0xFFFF;
3095
Chaithanya Krishna Bacharaju8b0abba2019-01-11 19:35:54 +05303096 if (((this_adm.ec_ref_rx & AFE_PORT_INVALID) !=
3097 AFE_PORT_INVALID) &&
3098 (path != ADM_PATH_PLAYBACK)) {
Surendar Karkade79a062018-12-05 14:18:55 +05303099 if (this_adm.num_ec_ref_rx_chans != 0) {
3100 open_v8.endpoint_id_2 =
3101 this_adm.ec_ref_rx;
Chaithanya Krishna Bacharaju757f0d22019-06-21 13:10:22 +05303102 this_adm.ec_ref_rx = AFE_PORT_INVALID;
Surendar Karkade79a062018-12-05 14:18:55 +05303103 } else {
3104 pr_err("%s: EC channels not set %d\n",
3105 __func__,
3106 this_adm.num_ec_ref_rx_chans);
3107 return -EINVAL;
3108 }
Dieter Luecking41620832018-11-14 15:11:47 +01003109 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303110
Dieter Luecking50c55352018-09-28 14:29:17 +02003111 open_v8.topology_id = topology;
3112 open_v8.reserved = 0;
3113
3114 /* variable endpoint payload */
3115 ep1_payload.dev_num_channel = channel_mode & 0x00FF;
3116 ep1_payload.bit_width = bit_width;
3117 ep1_payload.sample_rate = rate;
3118 ret = adm_arrange_mch_map_v8(&ep1_payload, path,
Rohit kumar2054b692019-02-01 18:01:12 +05303119 channel_mode, port_idx);
Dieter Luecking50c55352018-09-28 14:29:17 +02003120 if (ret)
3121 return ret;
3122
3123 pr_debug("%s: port_id=0x%x %x %x topology_id=0x%X flags %x ref_ch %x\n",
3124 __func__, open_v8.endpoint_id_1,
3125 open_v8.endpoint_id_2,
3126 open_v8.endpoint_id_3,
3127 open_v8.topology_id,
3128 open_v8.flags,
3129 this_adm.num_ec_ref_rx_chans);
3130
3131 ep1_payload_size = 8 +
3132 roundup(ep1_payload.dev_num_channel, 4);
3133 param_size = sizeof(struct adm_cmd_device_open_v8)
3134 + ep1_payload_size;
3135 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3136
Dieter Luecking27c57722018-10-05 16:45:41 +02003137 if ((this_adm.num_ec_ref_rx_chans != 0)
3138 && (path != ADM_PATH_PLAYBACK)
Dieter Luecking50c55352018-09-28 14:29:17 +02003139 && (open_v8.endpoint_id_2 != 0xFFFF)) {
3140 ep2_payload.dev_num_channel =
3141 this_adm.num_ec_ref_rx_chans;
Dieter Luecking50c55352018-09-28 14:29:17 +02003142
3143 if (this_adm.ec_ref_rx_bit_width != 0) {
3144 ep2_payload.bit_width =
3145 this_adm.ec_ref_rx_bit_width;
Dieter Luecking50c55352018-09-28 14:29:17 +02003146 } else {
3147 ep2_payload.bit_width = bit_width;
3148 }
3149
3150 if (this_adm.ec_ref_rx_sampling_rate != 0) {
3151 ep2_payload.sample_rate =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303152 this_adm.ec_ref_rx_sampling_rate;
Dieter Luecking50c55352018-09-28 14:29:17 +02003153 } else {
3154 ep2_payload.sample_rate = rate;
3155 }
3156
3157 pr_debug("%s: adm open_v8 eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
3158 __func__,
3159 ep2_payload.dev_num_channel,
3160 ep2_payload.bit_width,
3161 ep2_payload.sample_rate);
3162
3163 ret = adm_arrange_mch_ep2_map_v8(&ep2_payload,
3164 ep2_payload.dev_num_channel);
3165
3166 if (ret)
3167 return ret;
3168 ep2_payload_size = 8 +
3169 roundup(ep2_payload.dev_num_channel, 4);
3170 param_size += ep2_payload_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303171 }
3172
Dieter Luecking27c57722018-10-05 16:45:41 +02003173 open_v8.hdr.pkt_size = param_size;
Dieter Luecking50c55352018-09-28 14:29:17 +02003174 adm_params = kzalloc(param_size, GFP_KERNEL);
3175 if (!adm_params)
3176 return -ENOMEM;
Dieter Luecking50c55352018-09-28 14:29:17 +02003177 memcpy(adm_params, &open_v8, sizeof(open_v8));
3178 memcpy(adm_params + sizeof(open_v8),
3179 (void *)&ep1_payload,
3180 ep1_payload_size);
Dieter Luecking27c57722018-10-05 16:45:41 +02003181
3182 if ((this_adm.num_ec_ref_rx_chans != 0)
3183 && (path != ADM_PATH_PLAYBACK)
3184 && (open_v8.endpoint_id_2 != 0xFFFF)) {
Dieter Luecking41620832018-11-14 15:11:47 +01003185 this_adm.num_ec_ref_rx_chans = 0;
Dieter Luecking27c57722018-10-05 16:45:41 +02003186 memcpy(adm_params + sizeof(open_v8)
3187 + ep1_payload_size,
3188 (void *)&ep2_payload,
3189 ep2_payload_size);
3190 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303191
Dieter Luecking50c55352018-09-28 14:29:17 +02003192 ret = apr_send_pkt(this_adm.apr,
3193 (uint32_t *)adm_params);
3194 if (ret < 0) {
3195 pr_err("%s: port_id: 0x%x for[0x%x] failed %d for open_v8\n",
3196 __func__, tmp_port, port_id, ret);
3197 return -EINVAL;
3198 }
3199 kfree(adm_params);
3200 } else {
3201
3202 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3203 APR_HDR_LEN(APR_HDR_SIZE),
3204 APR_PKT_VER);
3205 open.hdr.pkt_size = sizeof(open);
3206 open.hdr.src_svc = APR_SVC_ADM;
3207 open.hdr.src_domain = APR_DOMAIN_APPS;
3208 open.hdr.src_port = tmp_port;
3209 open.hdr.dest_svc = APR_SVC_ADM;
3210 open.hdr.dest_domain = APR_DOMAIN_ADSP;
3211 open.hdr.dest_port = tmp_port;
3212 open.hdr.token = port_idx << 16 | copp_idx;
3213 open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
3214 open.flags = flags;
3215 open.mode_of_operation = path;
3216 open.endpoint_id_1 = tmp_port;
3217 open.endpoint_id_2 = 0xFFFF;
3218
Surendar Karkae7507512018-07-20 15:46:54 +05303219 if (this_adm.ec_ref_rx && (path != 1) &&
3220 (afe_get_port_type(tmp_port) == MSM_AFE_PORT_TYPE_TX)) {
Dieter Luecking50c55352018-09-28 14:29:17 +02003221 open.endpoint_id_2 = this_adm.ec_ref_rx;
Dieter Luecking50c55352018-09-28 14:29:17 +02003222 }
3223
3224 open.topology_id = topology;
3225
3226 open.dev_num_channel = channel_mode & 0x00FF;
3227 open.bit_width = bit_width;
3228 WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
3229 (rate != ULL_SUPPORTED_SAMPLE_RATE));
3230 open.sample_rate = rate;
3231
Rohit kumar2054b692019-02-01 18:01:12 +05303232 ret = adm_arrange_mch_map(&open, path, channel_mode,
3233 port_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303234 if (ret)
3235 return ret;
3236
Dieter Luecking50c55352018-09-28 14:29:17 +02003237 pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
3238 __func__, open.endpoint_id_1, open.sample_rate,
3239 open.topology_id);
3240
3241 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3242
3243 if ((this_adm.num_ec_ref_rx_chans != 0) &&
3244 (path != 1) && (open.endpoint_id_2 != 0xFFFF)) {
3245 memset(&open_v6, 0,
3246 sizeof(struct adm_cmd_device_open_v6));
3247 memcpy(&open_v6, &open,
3248 sizeof(struct adm_cmd_device_open_v5));
3249 open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
3250 open_v6.hdr.pkt_size = sizeof(open_v6);
3251 open_v6.dev_num_channel_eid2 =
3252 this_adm.num_ec_ref_rx_chans;
Dieter Luecking50c55352018-09-28 14:29:17 +02003253
3254 if (this_adm.ec_ref_rx_bit_width != 0) {
3255 open_v6.bit_width_eid2 =
3256 this_adm.ec_ref_rx_bit_width;
Dieter Luecking50c55352018-09-28 14:29:17 +02003257 } else {
3258 open_v6.bit_width_eid2 = bit_width;
3259 }
3260
3261 if (this_adm.ec_ref_rx_sampling_rate != 0) {
3262 open_v6.sample_rate_eid2 =
3263 this_adm.ec_ref_rx_sampling_rate;
Dieter Luecking50c55352018-09-28 14:29:17 +02003264 } else {
3265 open_v6.sample_rate_eid2 = rate;
3266 }
3267
3268 pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
3269 __func__, open_v6.dev_num_channel_eid2,
3270 open_v6.bit_width_eid2,
3271 open_v6.sample_rate_eid2);
3272
3273 ret = adm_arrange_mch_ep2_map(&open_v6,
3274 open_v6.dev_num_channel_eid2);
3275
3276 if (ret)
3277 return ret;
3278
3279 ret = apr_send_pkt(this_adm.apr,
3280 (uint32_t *)&open_v6);
3281 } else {
3282 ret = apr_send_pkt(this_adm.apr,
3283 (uint32_t *)&open);
3284 }
3285 if (ret < 0) {
3286 pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
3287 __func__, tmp_port, port_id, ret);
3288 return -EINVAL;
3289 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303290 }
Dieter Luecking50c55352018-09-28 14:29:17 +02003291
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303292 /* Wait for the callback with copp id */
3293 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3294 atomic_read(&this_adm.copp.stat
3295 [port_idx][copp_idx]) >= 0,
3296 msecs_to_jiffies(TIMEOUT_MS));
3297 if (!ret) {
3298 pr_err("%s: ADM open timedout for port_id: 0x%x for [0x%x]\n",
3299 __func__, tmp_port, port_id);
3300 return -EINVAL;
3301 } else if (atomic_read(&this_adm.copp.stat
3302 [port_idx][copp_idx]) > 0) {
3303 pr_err("%s: DSP returned error[%s]\n",
3304 __func__, adsp_err_get_err_str(
3305 atomic_read(&this_adm.copp.stat
3306 [port_idx][copp_idx])));
3307 return adsp_err_get_lnx_err_code(
3308 atomic_read(&this_adm.copp.stat
3309 [port_idx][copp_idx]));
3310 }
3311 }
3312 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
Dhananjay Kumar43034392019-01-16 21:57:58 +05303313
3314 /*
3315 * Configure MFC(in ec_ref path) if chmixing param is applicable and set.
3316 * Except channels and channel maps the media format config for this module
3317 * should match with the COPP(EP1) config values.
3318 */
3319 if (path != ADM_PATH_PLAYBACK &&
3320 this_adm.num_ec_ref_rx_chans_downmixed != 0 &&
3321 num_ec_ref_rx_chans != this_adm.num_ec_ref_rx_chans_downmixed) {
3322 ret = adm_copp_set_ec_ref_mfc_cfg(port_id, copp_idx,
3323 rate, bit_width, num_ec_ref_rx_chans,
3324 this_adm.num_ec_ref_rx_chans_downmixed);
3325 this_adm.num_ec_ref_rx_chans_downmixed = 0;
3326 if (ret)
3327 pr_err("%s: set EC REF MFC cfg failed, err %d\n", __func__, ret);
3328 }
3329
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303330 return copp_idx;
3331}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303332EXPORT_SYMBOL(adm_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303333
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303334/**
3335 * adm_copp_mfc_cfg -
3336 * command to send ADM MFC config
3337 *
3338 * @port_id: Port ID number
3339 * @copp_idx: copp index assigned
3340 * @dst_sample_rate: sink sample rate
3341 *
3342 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303343void adm_copp_mfc_cfg(int port_id, int copp_idx, int dst_sample_rate)
3344{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003345 struct audproc_mfc_param_media_fmt mfc_cfg;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303346 struct adm_cmd_device_open_v5 open;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003347 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303348 int port_idx;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303349 int rc = 0;
3350 int i = 0;
3351
3352 port_id = q6audio_convert_virtual_to_portid(port_id);
3353 port_idx = adm_validate_and_get_port_index(port_id);
3354
3355 if (port_idx < 0) {
3356 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
3357 goto fail_cmd;
3358 }
3359
3360 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
3361 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
3362 goto fail_cmd;
3363 }
3364
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003365 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
3366 memset(&open, 0, sizeof(open));
3367 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303368
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003369 param_hdr.module_id = AUDPROC_MODULE_ID_MFC;
3370 param_hdr.instance_id = INSTANCE_ID_0;
3371 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
3372 param_hdr.param_size = sizeof(mfc_cfg);
3373
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303374 mfc_cfg.sampling_rate = dst_sample_rate;
3375 mfc_cfg.bits_per_sample =
3376 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
3377 open.dev_num_channel = mfc_cfg.num_channels =
3378 atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
3379
3380 rc = adm_arrange_mch_map(&open, ADM_PATH_PLAYBACK,
Rohit kumar2054b692019-02-01 18:01:12 +05303381 mfc_cfg.num_channels, port_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303382 if (rc < 0) {
3383 pr_err("%s: unable to get channal map\n", __func__);
3384 goto fail_cmd;
3385 }
3386
3387 for (i = 0; i < mfc_cfg.num_channels; i++)
3388 mfc_cfg.channel_type[i] =
3389 (uint16_t) open.dev_channel_mapping[i];
3390
3391 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3392
3393 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",
3394 __func__, port_idx, copp_idx,
3395 atomic_read(&this_adm.copp.rate[port_idx][copp_idx]),
3396 mfc_cfg.bits_per_sample, mfc_cfg.num_channels,
3397 mfc_cfg.sampling_rate);
3398
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08003399 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
3400 (uint8_t *) &mfc_cfg);
3401 if (rc)
3402 pr_err("%s: Failed to set media format configuration data, err %d\n",
3403 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303404
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303405fail_cmd:
3406 return;
3407}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303408EXPORT_SYMBOL(adm_copp_mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303409
3410static void route_set_opcode_matrix_id(
3411 struct adm_cmd_matrix_map_routings_v5 **route_addr,
3412 int path, uint32_t passthr_mode)
3413{
3414 struct adm_cmd_matrix_map_routings_v5 *route = *route_addr;
3415
3416 switch (path) {
3417 case ADM_PATH_PLAYBACK:
3418 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
3419 route->matrix_id = ADM_MATRIX_ID_AUDIO_RX;
3420 break;
3421 case ADM_PATH_LIVE_REC:
3422 if (passthr_mode == LISTEN) {
3423 route->hdr.opcode =
3424 ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3425 route->matrix_id = ADM_MATRIX_ID_LISTEN_TX;
3426 break;
3427 }
3428 /* fall through to set matrix id for non-listen case */
3429 case ADM_PATH_NONLIVE_REC:
3430 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
3431 route->matrix_id = ADM_MATRIX_ID_AUDIO_TX;
3432 break;
3433 case ADM_PATH_COMPRESSED_RX:
3434 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3435 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_RX;
3436 break;
3437 case ADM_PATH_COMPRESSED_TX:
3438 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
3439 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_TX;
3440 break;
3441 default:
3442 pr_err("%s: Wrong path set[%d]\n", __func__, path);
3443 break;
3444 }
3445 pr_debug("%s: opcode 0x%x, matrix id %d\n",
3446 __func__, route->hdr.opcode, route->matrix_id);
3447}
3448
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303449/**
3450 * adm_matrix_map -
3451 * command to send ADM matrix map for ADM copp list
3452 *
3453 * @path: direction or ADM path type
3454 * @payload_map: have info of session id and associated copp_idx/num_copps
3455 * @perf_mode: performance mode like LL/ULL/..
3456 * @passthr_mode: flag to indicate passthrough mode
3457 *
3458 * Returns 0 on success or error on failure
3459 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303460int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode,
3461 uint32_t passthr_mode)
3462{
3463 struct adm_cmd_matrix_map_routings_v5 *route;
3464 struct adm_session_map_node_v5 *node;
3465 uint16_t *copps_list;
3466 int cmd_size = 0;
3467 int ret = 0, i = 0;
3468 void *payload = NULL;
3469 void *matrix_map = NULL;
3470 int port_idx, copp_idx;
3471
3472 /* Assumes port_ids have already been validated during adm_open */
3473 cmd_size = (sizeof(struct adm_cmd_matrix_map_routings_v5) +
3474 sizeof(struct adm_session_map_node_v5) +
3475 (sizeof(uint32_t) * payload_map.num_copps));
3476 matrix_map = kzalloc(cmd_size, GFP_KERNEL);
3477 if (matrix_map == NULL) {
3478 pr_err("%s: Mem alloc failed\n", __func__);
3479 ret = -EINVAL;
3480 return ret;
3481 }
3482 route = (struct adm_cmd_matrix_map_routings_v5 *)matrix_map;
3483
3484 route->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3485 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3486 route->hdr.pkt_size = cmd_size;
3487 route->hdr.src_svc = 0;
3488 route->hdr.src_domain = APR_DOMAIN_APPS;
3489 route->hdr.src_port = 0; /* Ignored */;
3490 route->hdr.dest_svc = APR_SVC_ADM;
3491 route->hdr.dest_domain = APR_DOMAIN_ADSP;
3492 route->hdr.dest_port = 0; /* Ignored */;
3493 route->hdr.token = 0;
3494 route->num_sessions = 1;
3495 route_set_opcode_matrix_id(&route, path, passthr_mode);
3496
3497 payload = ((u8 *)matrix_map +
3498 sizeof(struct adm_cmd_matrix_map_routings_v5));
3499 node = (struct adm_session_map_node_v5 *)payload;
3500
3501 node->session_id = payload_map.session_id;
3502 node->num_copps = payload_map.num_copps;
3503 payload = (u8 *)node + sizeof(struct adm_session_map_node_v5);
3504 copps_list = (uint16_t *)payload;
3505 for (i = 0; i < payload_map.num_copps; i++) {
3506 port_idx =
3507 adm_validate_and_get_port_index(payload_map.port_id[i]);
3508 if (port_idx < 0) {
3509 pr_err("%s: Invalid port_id 0x%x\n", __func__,
3510 payload_map.port_id[i]);
3511 ret = -EINVAL;
3512 goto fail_cmd;
3513 }
3514 copp_idx = payload_map.copp_idx[i];
3515 copps_list[i] = atomic_read(&this_adm.copp.id[port_idx]
3516 [copp_idx]);
3517 }
3518 atomic_set(&this_adm.matrix_map_stat, -1);
3519
3520 ret = apr_send_pkt(this_adm.apr, (uint32_t *)matrix_map);
3521 if (ret < 0) {
3522 pr_err("%s: routing for syream %d failed ret %d\n",
3523 __func__, payload_map.session_id, ret);
3524 ret = -EINVAL;
3525 goto fail_cmd;
3526 }
3527 ret = wait_event_timeout(this_adm.matrix_map_wait,
3528 atomic_read(&this_adm.matrix_map_stat) >= 0,
3529 msecs_to_jiffies(TIMEOUT_MS));
3530 if (!ret) {
3531 pr_err("%s: routing for syream %d failed\n", __func__,
3532 payload_map.session_id);
3533 ret = -EINVAL;
3534 goto fail_cmd;
3535 } else if (atomic_read(&this_adm.matrix_map_stat) > 0) {
3536 pr_err("%s: DSP returned error[%s]\n", __func__,
3537 adsp_err_get_err_str(atomic_read(
3538 &this_adm.matrix_map_stat)));
3539 ret = adsp_err_get_lnx_err_code(
3540 atomic_read(&this_adm.matrix_map_stat));
3541 goto fail_cmd;
3542 }
3543
3544 if ((perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) &&
3545 (path != ADM_PATH_COMPRESSED_RX)) {
3546 for (i = 0; i < payload_map.num_copps; i++) {
3547 port_idx = afe_get_port_index(payload_map.port_id[i]);
3548 copp_idx = payload_map.copp_idx[i];
3549 if (port_idx < 0 || copp_idx < 0 ||
3550 (copp_idx > MAX_COPPS_PER_PORT - 1)) {
3551 pr_err("%s: Invalid idx port_idx %d copp_idx %d\n",
3552 __func__, port_idx, copp_idx);
3553 continue;
3554 }
3555 rtac_add_adm_device(payload_map.port_id[i],
3556 atomic_read(&this_adm.copp.id
3557 [port_idx][copp_idx]),
3558 get_cal_path(path),
3559 payload_map.session_id,
3560 payload_map.app_type[i],
3561 payload_map.acdb_dev_id[i]);
3562
3563 if (!test_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3564 (void *)&this_adm.copp.adm_status[port_idx]
3565 [copp_idx])) {
3566 pr_debug("%s: adm copp[0x%x][%d] already sent",
3567 __func__, port_idx, copp_idx);
3568 continue;
3569 }
3570 send_adm_cal(payload_map.port_id[i], copp_idx,
3571 get_cal_path(path), perf_mode,
3572 payload_map.app_type[i],
3573 payload_map.acdb_dev_id[i],
Aditya Bavanari5106b562018-01-08 13:16:32 +05303574 payload_map.sample_rate[i],
3575 passthr_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303576 /* ADM COPP calibration is already sent */
3577 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3578 (void *)&this_adm.copp.
3579 adm_status[port_idx][copp_idx]);
3580 pr_debug("%s: copp_id: %d\n", __func__,
3581 atomic_read(&this_adm.copp.id[port_idx]
3582 [copp_idx]));
3583 }
3584 }
3585
3586fail_cmd:
3587 kfree(matrix_map);
3588 return ret;
3589}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303590EXPORT_SYMBOL(adm_matrix_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303591
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303592/**
3593 * adm_ec_ref_rx_id -
3594 * Update EC ref port ID
3595 *
3596 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303597void adm_ec_ref_rx_id(int port_id)
3598{
3599 this_adm.ec_ref_rx = port_id;
3600 pr_debug("%s: ec_ref_rx:%d\n", __func__, this_adm.ec_ref_rx);
3601}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303602EXPORT_SYMBOL(adm_ec_ref_rx_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303603
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303604/**
3605 * adm_num_ec_ref_rx_chans -
3606 * Update EC ref number of channels
3607 *
3608 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303609void adm_num_ec_ref_rx_chans(int num_chans)
3610{
3611 this_adm.num_ec_ref_rx_chans = num_chans;
3612 pr_debug("%s: num_ec_ref_rx_chans:%d\n",
3613 __func__, this_adm.num_ec_ref_rx_chans);
3614}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303615EXPORT_SYMBOL(adm_num_ec_ref_rx_chans);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303616
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303617/**
Dhananjay Kumar43034392019-01-16 21:57:58 +05303618 * adm_num_ec_rx_ref_chans_downmixed -
3619 * Update EC ref num of channels(downmixed) to be fed to EC algo
3620 *
3621 */
3622void adm_num_ec_ref_rx_chans_downmixed(int num_chans)
3623{
3624 this_adm.num_ec_ref_rx_chans_downmixed = num_chans;
3625 pr_debug("%s: num_ec_ref_rx_chans_downmixed:%d\n",
3626 __func__, this_adm.num_ec_ref_rx_chans_downmixed);
3627}
3628EXPORT_SYMBOL(adm_num_ec_ref_rx_chans_downmixed);
3629
3630/**
3631 * adm_ec_ref_chmixer_weights -
3632 * Update MFC(in ec ref) Channel Mixer Weights to be used
3633 * for downmixing rx channels before feeding them to EC algo
3634 * @out_channel_idx: index of output channel to which weightages are applicable
3635 * @weights: pointer to array having input weightages
3636 * @count: array sizeof pointer weights, max supported value is
3637 * PCM_FORMAT_MAX_NUM_CHANNEL_V8
3638 * Returns 0 on success or error on failure
3639 */
3640int adm_ec_ref_chmixer_weights(int out_channel_idx,
3641 uint16_t *weights, int count)
3642{
3643 int i = 0;
3644
3645 if (weights == NULL || count <= 0 || out_channel_idx < 0 ||
3646 count > PCM_FORMAT_MAX_NUM_CHANNEL_V8 ||
3647 out_channel_idx >= PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
3648 pr_err("%s: invalid weightages count(%d) ch_idx(%d)",
3649 __func__, count, out_channel_idx);
3650 return -EINVAL;
3651 }
3652
3653 for (i = 0; i < count; i++) {
3654 this_adm.ec_ref_chmixer_weights[out_channel_idx][i] = weights[i];
3655 pr_debug("%s: out ch idx :%d, weight[%d] = %d\n",
3656 __func__, out_channel_idx, i, weights[i]);
3657 }
3658
3659 return 0;
3660}
3661EXPORT_SYMBOL(adm_ec_ref_chmixer_weights);
3662
3663/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303664 * adm_ec_ref_rx_bit_width -
3665 * Update EC ref bit_width
3666 *
3667 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303668void adm_ec_ref_rx_bit_width(int bit_width)
3669{
3670 this_adm.ec_ref_rx_bit_width = bit_width;
3671 pr_debug("%s: ec_ref_rx_bit_width:%d\n",
3672 __func__, this_adm.ec_ref_rx_bit_width);
3673}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303674EXPORT_SYMBOL(adm_ec_ref_rx_bit_width);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303675
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303676/**
3677 * adm_ec_ref_rx_sampling_rate -
3678 * Update EC ref sample rate
3679 *
3680 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303681void adm_ec_ref_rx_sampling_rate(int sampling_rate)
3682{
3683 this_adm.ec_ref_rx_sampling_rate = sampling_rate;
3684 pr_debug("%s: ec_ref_rx_sampling_rate:%d\n",
3685 __func__, this_adm.ec_ref_rx_sampling_rate);
3686}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303687EXPORT_SYMBOL(adm_ec_ref_rx_sampling_rate);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303688
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303689/**
Dieter Luecking50c55352018-09-28 14:29:17 +02003690 * adm_set_native_mode -
3691 * Set adm channel native mode.
3692 * If enabled matrix mixer will be
3693 * running in native mode for channel
3694 * configuration for this device session.
3695 *
3696 */
3697void adm_set_native_mode(int mode)
3698{
3699 this_adm.native_mode = mode;
3700 pr_debug("%s: enable native_mode :%d\n",
3701 __func__, this_adm.native_mode);
3702}
3703EXPORT_SYMBOL(adm_set_native_mode);
3704
3705/**
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303706 * adm_close -
3707 * command to close ADM copp
3708 *
3709 * @port_id: Port ID number
3710 * @perf_mode: performance mode like LL/ULL/..
3711 * @copp_idx: copp index assigned
3712 *
3713 * Returns 0 on success or error on failure
3714 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303715int adm_close(int port_id, int perf_mode, int copp_idx)
3716{
3717 struct apr_hdr close;
3718
3719 int ret = 0, port_idx;
3720 int copp_id = RESET_COPP_ID;
3721
3722 pr_debug("%s: port_id=0x%x perf_mode: %d copp_idx: %d\n", __func__,
3723 port_id, perf_mode, copp_idx);
3724
3725 port_id = q6audio_convert_virtual_to_portid(port_id);
3726 port_idx = adm_validate_and_get_port_index(port_id);
3727 if (port_idx < 0) {
3728 pr_err("%s: Invalid port_id 0x%x\n",
3729 __func__, port_id);
3730 return -EINVAL;
3731 }
3732
3733 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
3734 pr_err("%s: Invalid copp idx: %d\n", __func__, copp_idx);
3735 return -EINVAL;
3736 }
3737
Rohit kumar2054b692019-02-01 18:01:12 +05303738 port_channel_map[port_idx].set_channel_map = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303739 if (this_adm.copp.adm_delay[port_idx][copp_idx] && perf_mode
3740 == LEGACY_PCM_MODE) {
3741 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
3742 1);
3743 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
3744 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
3745 }
3746
3747 atomic_dec(&this_adm.copp.cnt[port_idx][copp_idx]);
3748 if (!(atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]))) {
3749 copp_id = adm_get_copp_id(port_idx, copp_idx);
3750 pr_debug("%s: Closing ADM port_idx:%d copp_idx:%d copp_id:0x%x\n",
3751 __func__, port_idx, copp_idx, copp_id);
3752 if ((!perf_mode) && (this_adm.outband_memmap.paddr != 0) &&
3753 (atomic_read(&this_adm.copp.topology[port_idx][copp_idx]) ==
3754 SRS_TRUMEDIA_TOPOLOGY_ID)) {
3755 atomic_set(&this_adm.mem_map_index,
3756 ADM_SRS_TRUMEDIA);
3757 ret = adm_memory_unmap_regions();
3758 if (ret < 0) {
3759 pr_err("%s: adm mem unmmap err %d",
3760 __func__, ret);
3761 } else {
3762 atomic_set(&this_adm.mem_map_handles
3763 [ADM_SRS_TRUMEDIA], 0);
3764 }
3765 }
3766
3767
3768 if ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) &&
3769 this_adm.sourceTrackingData.memmap.paddr) {
3770 atomic_set(&this_adm.mem_map_index,
3771 ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
3772 ret = adm_memory_unmap_regions();
3773 if (ret < 0) {
3774 pr_err("%s: adm mem unmmap err %d",
3775 __func__, ret);
3776 }
3777 msm_audio_ion_free(
Banajit Goswami08bb7362017-11-03 22:48:23 -07003778 this_adm.sourceTrackingData.dma_buf);
3779 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303780 this_adm.sourceTrackingData.memmap.size = 0;
3781 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
3782 this_adm.sourceTrackingData.memmap.paddr = 0;
3783 this_adm.sourceTrackingData.apr_cmd_status = -1;
3784 atomic_set(&this_adm.mem_map_handles[
3785 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
3786 }
3787
3788 close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3789 APR_HDR_LEN(APR_HDR_SIZE),
3790 APR_PKT_VER);
3791 close.pkt_size = sizeof(close);
3792 close.src_svc = APR_SVC_ADM;
3793 close.src_domain = APR_DOMAIN_APPS;
3794 close.src_port = port_id;
3795 close.dest_svc = APR_SVC_ADM;
3796 close.dest_domain = APR_DOMAIN_ADSP;
3797 close.dest_port = copp_id;
3798 close.token = port_idx << 16 | copp_idx;
3799 close.opcode = ADM_CMD_DEVICE_CLOSE_V5;
3800
3801 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
3802 RESET_COPP_ID);
3803 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
3804 atomic_set(&this_adm.copp.topology[port_idx][copp_idx], 0);
3805 atomic_set(&this_adm.copp.mode[port_idx][copp_idx], 0);
3806 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3807 atomic_set(&this_adm.copp.rate[port_idx][copp_idx], 0);
3808 atomic_set(&this_adm.copp.channels[port_idx][copp_idx], 0);
3809 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx], 0);
3810 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx], 0);
Surendar Karkae7507512018-07-20 15:46:54 +05303811 atomic_set(&this_adm.copp.session_type[port_idx][copp_idx], 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303812
3813 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3814 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
3815
3816 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
3817 if (ret < 0) {
3818 pr_err("%s: ADM close failed %d\n", __func__, ret);
3819 return -EINVAL;
3820 }
3821
3822 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3823 atomic_read(&this_adm.copp.stat
3824 [port_idx][copp_idx]) >= 0,
3825 msecs_to_jiffies(TIMEOUT_MS));
3826 if (!ret) {
3827 pr_err("%s: ADM cmd Route timedout for port 0x%x\n",
3828 __func__, port_id);
3829 return -EINVAL;
3830 } else if (atomic_read(&this_adm.copp.stat
3831 [port_idx][copp_idx]) > 0) {
3832 pr_err("%s: DSP returned error[%s]\n",
3833 __func__, adsp_err_get_err_str(
3834 atomic_read(&this_adm.copp.stat
3835 [port_idx][copp_idx])));
3836 return adsp_err_get_lnx_err_code(
3837 atomic_read(&this_adm.copp.stat
3838 [port_idx][copp_idx]));
3839 }
3840 }
3841
3842 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
3843 pr_debug("%s: remove adm device from rtac\n", __func__);
3844 rtac_remove_adm_device(port_id, copp_id);
3845 }
3846 return 0;
3847}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303848EXPORT_SYMBOL(adm_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303849
3850int send_rtac_audvol_cal(void)
3851{
3852 int ret = 0;
3853 int ret2 = 0;
3854 int i = 0;
3855 int copp_idx, port_idx, acdb_id, app_id, path;
3856 struct cal_block_data *cal_block = NULL;
3857 struct audio_cal_info_audvol *audvol_cal_info = NULL;
3858 struct rtac_adm rtac_adm_data;
3859
3860 mutex_lock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
3861
3862 cal_block = cal_utils_get_only_cal_block(
3863 this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]);
Vikram Panduranga770b8382017-09-27 12:17:36 -07003864 if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303865 pr_err("%s: can't find cal block!\n", __func__);
3866 goto unlock;
3867 }
3868
3869 audvol_cal_info = cal_block->cal_info;
3870 if (audvol_cal_info == NULL) {
3871 pr_err("%s: audvol_cal_info is NULL!\n", __func__);
3872 goto unlock;
3873 }
3874
3875 get_rtac_adm_data(&rtac_adm_data);
3876 for (; i < rtac_adm_data.num_of_dev; i++) {
3877
3878 acdb_id = rtac_adm_data.device[i].acdb_dev_id;
3879 if (acdb_id == 0)
3880 acdb_id = audvol_cal_info->acdb_id;
3881
3882 app_id = rtac_adm_data.device[i].app_type;
3883 if (app_id == 0)
3884 app_id = audvol_cal_info->app_type;
3885
3886 path = afe_get_port_type(rtac_adm_data.device[i].afe_port);
3887 if ((acdb_id == audvol_cal_info->acdb_id) &&
3888 (app_id == audvol_cal_info->app_type) &&
3889 (path == audvol_cal_info->path)) {
3890
3891 if (adm_get_indexes_from_copp_id(rtac_adm_data.
3892 device[i].copp, &copp_idx, &port_idx) != 0) {
3893 pr_debug("%s: Copp Id %d is not active\n",
3894 __func__,
3895 rtac_adm_data.device[i].copp);
3896 continue;
3897 }
3898
3899 ret2 = adm_remap_and_send_cal_block(ADM_RTAC_AUDVOL_CAL,
3900 rtac_adm_data.device[i].afe_port,
3901 copp_idx, cal_block,
3902 atomic_read(&this_adm.copp.
3903 mode[port_idx][copp_idx]),
3904 audvol_cal_info->app_type,
3905 audvol_cal_info->acdb_id,
3906 atomic_read(&this_adm.copp.
3907 rate[port_idx][copp_idx]));
3908 if (ret2 < 0) {
3909 pr_debug("%s: remap and send failed for copp Id %d, acdb id %d, app type %d, path %d\n",
3910 __func__, rtac_adm_data.device[i].copp,
3911 audvol_cal_info->acdb_id,
3912 audvol_cal_info->app_type,
3913 audvol_cal_info->path);
3914 ret = ret2;
3915 }
3916 }
3917 }
3918unlock:
3919 mutex_unlock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
3920 return ret;
3921}
3922
3923int adm_map_rtac_block(struct rtac_cal_block_data *cal_block)
3924{
3925 int result = 0;
3926
3927 pr_debug("%s:\n", __func__);
3928
3929 if (cal_block == NULL) {
3930 pr_err("%s: cal_block is NULL!\n",
3931 __func__);
3932 result = -EINVAL;
3933 goto done;
3934 }
3935
3936 if (cal_block->cal_data.paddr == 0) {
3937 pr_debug("%s: No address to map!\n",
3938 __func__);
3939 result = -EINVAL;
3940 goto done;
3941 }
3942
3943 if (cal_block->map_data.map_size == 0) {
3944 pr_debug("%s: map size is 0!\n",
3945 __func__);
3946 result = -EINVAL;
3947 goto done;
3948 }
3949
3950 /* valid port ID needed for callback use primary I2S */
3951 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
3952 result = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
3953 &cal_block->map_data.map_size, 1);
3954 if (result < 0) {
3955 pr_err("%s: RTAC mmap did not work! size = %d result %d\n",
3956 __func__,
3957 cal_block->map_data.map_size, result);
3958 pr_debug("%s: RTAC mmap did not work! addr = 0x%pK, size = %d\n",
3959 __func__,
3960 &cal_block->cal_data.paddr,
3961 cal_block->map_data.map_size);
3962 goto done;
3963 }
3964
3965 cal_block->map_data.map_handle = atomic_read(
3966 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]);
3967done:
3968 return result;
3969}
3970
3971int adm_unmap_rtac_block(uint32_t *mem_map_handle)
3972{
3973 int result = 0;
3974
3975 pr_debug("%s:\n", __func__);
3976
3977 if (mem_map_handle == NULL) {
3978 pr_debug("%s: Map handle is NULL, nothing to unmap\n",
3979 __func__);
3980 goto done;
3981 }
3982
3983 if (*mem_map_handle == 0) {
3984 pr_debug("%s: Map handle is 0, nothing to unmap\n",
3985 __func__);
3986 goto done;
3987 }
3988
3989 if (*mem_map_handle != atomic_read(
3990 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL])) {
3991 pr_err("%s: Map handles do not match! Unmapping RTAC, RTAC map 0x%x, ADM map 0x%x\n",
3992 __func__, *mem_map_handle, atomic_read(
3993 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]));
3994
3995 /* if mismatch use handle passed in to unmap */
3996 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL],
3997 *mem_map_handle);
3998 }
3999
4000 /* valid port ID needed for callback use primary I2S */
4001 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
4002 result = adm_memory_unmap_regions();
4003 if (result < 0) {
4004 pr_debug("%s: adm_memory_unmap_regions failed, error %d\n",
4005 __func__, result);
4006 } else {
4007 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL], 0);
4008 *mem_map_handle = 0;
4009 }
4010done:
4011 return result;
4012}
4013
4014static int get_cal_type_index(int32_t cal_type)
4015{
4016 int ret = -EINVAL;
4017
4018 switch (cal_type) {
4019 case ADM_AUDPROC_CAL_TYPE:
4020 ret = ADM_AUDPROC_CAL;
4021 break;
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304022 case ADM_LSM_AUDPROC_CAL_TYPE:
4023 ret = ADM_LSM_AUDPROC_CAL;
4024 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304025 case ADM_AUDVOL_CAL_TYPE:
4026 ret = ADM_AUDVOL_CAL;
4027 break;
4028 case ADM_CUST_TOPOLOGY_CAL_TYPE:
4029 ret = ADM_CUSTOM_TOP_CAL;
4030 break;
4031 case ADM_RTAC_INFO_CAL_TYPE:
4032 ret = ADM_RTAC_INFO_CAL;
4033 break;
4034 case ADM_RTAC_APR_CAL_TYPE:
4035 ret = ADM_RTAC_APR_CAL;
4036 break;
4037 case ADM_RTAC_AUDVOL_CAL_TYPE:
4038 ret = ADM_RTAC_AUDVOL_CAL;
4039 break;
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004040 case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
4041 ret = ADM_LSM_AUDPROC_PERSISTENT_CAL;
4042 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304043 default:
4044 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
4045 }
4046 return ret;
4047}
4048
4049static int adm_alloc_cal(int32_t cal_type, size_t data_size, void *data)
4050{
4051 int ret = 0;
4052 int cal_index;
4053
4054 pr_debug("%s:\n", __func__);
4055
4056 cal_index = get_cal_type_index(cal_type);
4057 if (cal_index < 0) {
4058 pr_err("%s: could not get cal index %d!\n",
4059 __func__, cal_index);
4060 ret = -EINVAL;
4061 goto done;
4062 }
4063
4064 ret = cal_utils_alloc_cal(data_size, data,
4065 this_adm.cal_data[cal_index], 0, NULL);
4066 if (ret < 0) {
4067 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
4068 __func__, ret, cal_type);
4069 ret = -EINVAL;
4070 goto done;
4071 }
4072done:
4073 return ret;
4074}
4075
4076static int adm_dealloc_cal(int32_t cal_type, size_t data_size, void *data)
4077{
4078 int ret = 0;
4079 int cal_index;
4080
4081 pr_debug("%s:\n", __func__);
4082
4083 cal_index = get_cal_type_index(cal_type);
4084 if (cal_index < 0) {
4085 pr_err("%s: could not get cal index %d!\n",
4086 __func__, cal_index);
4087 ret = -EINVAL;
4088 goto done;
4089 }
4090
4091 ret = cal_utils_dealloc_cal(data_size, data,
4092 this_adm.cal_data[cal_index]);
4093 if (ret < 0) {
4094 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
4095 __func__, ret, cal_type);
4096 ret = -EINVAL;
4097 goto done;
4098 }
4099done:
4100 return ret;
4101}
4102
4103static int adm_set_cal(int32_t cal_type, size_t data_size, void *data)
4104{
4105 int ret = 0;
4106 int cal_index;
4107
4108 pr_debug("%s:\n", __func__);
4109
4110 cal_index = get_cal_type_index(cal_type);
4111 if (cal_index < 0) {
4112 pr_err("%s: could not get cal index %d!\n",
4113 __func__, cal_index);
4114 ret = -EINVAL;
4115 goto done;
4116 }
4117
4118 ret = cal_utils_set_cal(data_size, data,
4119 this_adm.cal_data[cal_index], 0, NULL);
4120 if (ret < 0) {
4121 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
4122 __func__, ret, cal_type);
4123 ret = -EINVAL;
4124 goto done;
4125 }
4126
4127 if (cal_index == ADM_CUSTOM_TOP_CAL) {
4128 mutex_lock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
4129 this_adm.set_custom_topology = 1;
4130 mutex_unlock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
4131 } else if (cal_index == ADM_RTAC_AUDVOL_CAL) {
4132 send_rtac_audvol_cal();
4133 }
4134done:
4135 return ret;
4136}
4137
4138static int adm_map_cal_data(int32_t cal_type,
4139 struct cal_block_data *cal_block)
4140{
4141 int ret = 0;
4142 int cal_index;
4143
4144 pr_debug("%s:\n", __func__);
4145
4146 cal_index = get_cal_type_index(cal_type);
4147 if (cal_index < 0) {
4148 pr_err("%s: could not get cal index %d!\n",
4149 __func__, cal_index);
4150 ret = -EINVAL;
4151 goto done;
4152 }
4153
4154 atomic_set(&this_adm.mem_map_index, cal_index);
4155 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
4156 (uint32_t *)&cal_block->map_data.map_size, 1);
4157 if (ret < 0) {
4158 pr_err("%s: map did not work! cal_type %i ret %d\n",
4159 __func__, cal_index, ret);
4160 ret = -ENODEV;
4161 goto done;
4162 }
4163 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
4164 mem_map_handles[cal_index]);
4165done:
4166 return ret;
4167}
4168
4169static int adm_unmap_cal_data(int32_t cal_type,
4170 struct cal_block_data *cal_block)
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 if (cal_block == NULL) {
4186 pr_err("%s: Cal block is NULL!\n",
4187 __func__);
4188 goto done;
4189 }
4190
4191 if (cal_block->map_data.q6map_handle == 0) {
4192 pr_err("%s: Map handle is NULL, nothing to unmap\n",
4193 __func__);
4194 goto done;
4195 }
4196
4197 atomic_set(&this_adm.mem_map_handles[cal_index],
4198 cal_block->map_data.q6map_handle);
4199 atomic_set(&this_adm.mem_map_index, cal_index);
4200 ret = adm_memory_unmap_regions();
4201 if (ret < 0) {
4202 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
4203 __func__, cal_index, ret);
4204 ret = -ENODEV;
4205 goto done;
4206 }
4207 cal_block->map_data.q6map_handle = 0;
4208done:
4209 return ret;
4210}
4211
4212static void adm_delete_cal_data(void)
4213{
4214 pr_debug("%s:\n", __func__);
4215
4216 cal_utils_destroy_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data);
4217}
4218
4219static int adm_init_cal_data(void)
4220{
4221 int ret = 0;
4222 struct cal_type_info cal_type_info[] = {
4223 {{ADM_CUST_TOPOLOGY_CAL_TYPE,
4224 {adm_alloc_cal, adm_dealloc_cal, NULL,
4225 adm_set_cal, NULL, NULL} },
4226 {adm_map_cal_data, adm_unmap_cal_data,
4227 cal_utils_match_buf_num} },
4228
4229 {{ADM_AUDPROC_CAL_TYPE,
4230 {adm_alloc_cal, adm_dealloc_cal, NULL,
4231 adm_set_cal, NULL, NULL} },
4232 {adm_map_cal_data, adm_unmap_cal_data,
4233 cal_utils_match_buf_num} },
4234
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304235 {{ADM_LSM_AUDPROC_CAL_TYPE,
4236 {adm_alloc_cal, adm_dealloc_cal, NULL,
4237 adm_set_cal, NULL, NULL} },
4238 {adm_map_cal_data, adm_unmap_cal_data,
4239 cal_utils_match_buf_num} },
4240
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304241 {{ADM_AUDVOL_CAL_TYPE,
4242 {adm_alloc_cal, adm_dealloc_cal, NULL,
4243 adm_set_cal, NULL, NULL} },
4244 {adm_map_cal_data, adm_unmap_cal_data,
4245 cal_utils_match_buf_num} },
4246
4247 {{ADM_RTAC_INFO_CAL_TYPE,
4248 {NULL, NULL, NULL, NULL, NULL, NULL} },
4249 {NULL, NULL, cal_utils_match_buf_num} },
4250
4251 {{ADM_RTAC_APR_CAL_TYPE,
4252 {NULL, NULL, NULL, NULL, NULL, NULL} },
4253 {NULL, NULL, cal_utils_match_buf_num} },
4254
4255 {{SRS_TRUMEDIA_CAL_TYPE,
4256 {NULL, NULL, NULL, NULL, NULL, NULL} },
4257 {NULL, NULL, cal_utils_match_buf_num} },
4258
4259 {{ADM_RTAC_AUDVOL_CAL_TYPE,
4260 {adm_alloc_cal, adm_dealloc_cal, NULL,
4261 adm_set_cal, NULL, NULL} },
4262 {adm_map_cal_data, adm_unmap_cal_data,
4263 cal_utils_match_buf_num} },
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004264
4265 {{ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE,
4266 {adm_alloc_cal, adm_dealloc_cal, NULL,
4267 adm_set_cal, NULL, NULL} },
4268 {adm_map_cal_data, adm_unmap_cal_data,
4269 cal_utils_match_buf_num} },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304270 };
4271 pr_debug("%s:\n", __func__);
4272
4273 ret = cal_utils_create_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data,
4274 cal_type_info);
4275 if (ret < 0) {
4276 pr_err("%s: could not create cal type! ret %d\n",
4277 __func__, ret);
4278 ret = -EINVAL;
4279 goto err;
4280 }
4281
4282 return ret;
4283err:
4284 adm_delete_cal_data();
4285 return ret;
4286}
4287
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304288/**
4289 * adm_set_volume -
4290 * command to set volume on ADM copp
4291 *
4292 * @port_id: Port ID number
4293 * @copp_idx: copp index assigned
4294 * @volume: gain value to set
4295 *
4296 * Returns 0 on success or error on failure
4297 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304298int adm_set_volume(int port_id, int copp_idx, int volume)
4299{
4300 struct audproc_volume_ctrl_master_gain audproc_vol;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004301 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304302 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304303
4304 pr_debug("%s: port_id %d, volume %d\n", __func__, port_id, volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304305
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004306 memset(&audproc_vol, 0, sizeof(audproc_vol));
4307 memset(&param_hdr, 0, sizeof(param_hdr));
4308 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
4309 param_hdr.instance_id = INSTANCE_ID_0;
4310 param_hdr.param_id = AUDPROC_PARAM_ID_VOL_CTRL_MASTER_GAIN;
4311 param_hdr.param_size = sizeof(audproc_vol);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304312
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304313 audproc_vol.master_gain = volume;
4314
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004315 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4316 (uint8_t *) &audproc_vol);
4317 if (rc)
4318 pr_err("%s: Failed to set volume, err %d\n", __func__, rc);
4319
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304320 return rc;
4321}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304322EXPORT_SYMBOL(adm_set_volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304323
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304324/**
4325 * adm_set_softvolume -
4326 * command to set softvolume
4327 *
4328 * @port_id: Port ID number
4329 * @copp_idx: copp index assigned
4330 * @softvol_param: Params to set for softvolume
4331 *
4332 * Returns 0 on success or error on failure
4333 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304334int adm_set_softvolume(int port_id, int copp_idx,
4335 struct audproc_softvolume_params *softvol_param)
4336{
4337 struct audproc_soft_step_volume_params audproc_softvol;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004338 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304339 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304340
4341 pr_debug("%s: period %d step %d curve %d\n", __func__,
4342 softvol_param->period, softvol_param->step,
4343 softvol_param->rampingcurve);
4344
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004345 memset(&audproc_softvol, 0, sizeof(audproc_softvol));
4346 memset(&param_hdr, 0, sizeof(param_hdr));
4347 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
4348 param_hdr.instance_id = INSTANCE_ID_0;
4349 param_hdr.param_id = AUDPROC_PARAM_ID_SOFT_VOL_STEPPING_PARAMETERS;
4350 param_hdr.param_size = sizeof(audproc_softvol);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304351
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304352 audproc_softvol.period = softvol_param->period;
4353 audproc_softvol.step = softvol_param->step;
4354 audproc_softvol.ramping_curve = softvol_param->rampingcurve;
4355
4356 pr_debug("%s: period %d, step %d, curve %d\n", __func__,
4357 audproc_softvol.period, audproc_softvol.step,
4358 audproc_softvol.ramping_curve);
4359
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004360 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4361 (uint8_t *) &audproc_softvol);
4362 if (rc)
4363 pr_err("%s: Failed to set soft volume, err %d\n", __func__, rc);
4364
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304365 return rc;
4366}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304367EXPORT_SYMBOL(adm_set_softvolume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304368
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304369/**
4370 * adm_set_mic_gain -
4371 * command to set MIC gain
4372 *
4373 * @port_id: Port ID number
4374 * @copp_idx: copp index assigned
4375 * @volume: gain value to set
4376 *
4377 * Returns 0 on success or error on failure
4378 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304379int adm_set_mic_gain(int port_id, int copp_idx, int volume)
4380{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004381 struct admx_mic_gain mic_gain_params;
4382 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304383 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304384
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004385 pr_debug("%s: Setting mic gain to %d at port_id 0x%x\n", __func__,
4386 volume, port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304387
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004388 memset(&mic_gain_params, 0, sizeof(mic_gain_params));
4389 memset(&param_hdr, 0, sizeof(param_hdr));
4390 param_hdr.module_id = ADM_MODULE_IDX_MIC_GAIN_CTRL;
4391 param_hdr.instance_id = INSTANCE_ID_0;
4392 param_hdr.param_id = ADM_PARAM_IDX_MIC_GAIN;
4393 param_hdr.param_size = sizeof(mic_gain_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304394
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004395 mic_gain_params.tx_mic_gain = volume;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304396
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004397 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4398 (uint8_t *) &mic_gain_params);
4399 if (rc)
4400 pr_err("%s: Failed to set mic gain, err %d\n", __func__, rc);
4401
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304402 return rc;
4403}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304404EXPORT_SYMBOL(adm_set_mic_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304405
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304406/**
4407 * adm_send_set_multichannel_ec_primary_mic_ch -
4408 * command to set multi-ch EC primary mic
4409 *
4410 * @port_id: Port ID number
4411 * @copp_idx: copp index assigned
4412 * @primary_mic_ch: channel number of primary mic
4413 *
4414 * Returns 0 on success or error on failure
4415 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304416int adm_send_set_multichannel_ec_primary_mic_ch(int port_id, int copp_idx,
4417 int primary_mic_ch)
4418{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004419 struct admx_sec_primary_mic_ch sec_primary_ch_params;
4420 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304421 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304422
4423 pr_debug("%s port_id 0x%x, copp_idx 0x%x, primary_mic_ch %d\n",
4424 __func__, port_id, copp_idx, primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304425
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004426 memset(&sec_primary_ch_params, 0, sizeof(sec_primary_ch_params));
4427 memset(&param_hdr, 0, sizeof(param_hdr));
4428 param_hdr.module_id = AUDPROC_MODULE_ID_VOICE_TX_SECNS;
4429 param_hdr.instance_id = INSTANCE_ID_0;
4430 param_hdr.param_id = AUDPROC_PARAM_IDX_SEC_PRIMARY_MIC_CH;
4431 param_hdr.param_size = sizeof(sec_primary_ch_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304432
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004433 sec_primary_ch_params.version = 0;
4434 sec_primary_ch_params.sec_primary_mic_ch = primary_mic_ch;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304435
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004436 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4437 (uint8_t *) &sec_primary_ch_params);
4438 if (rc)
4439 pr_err("%s: Failed to set primary mic chanel, err %d\n",
4440 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304441
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304442 return rc;
4443}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304444EXPORT_SYMBOL(adm_send_set_multichannel_ec_primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304445
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304446/**
4447 * adm_param_enable -
4448 * command to send params to ADM for given module
4449 *
4450 * @port_id: Port ID number
4451 * @copp_idx: copp index assigned
4452 * @module_id: ADM module
4453 * @enable: flag to enable or disable module
4454 *
4455 * Returns 0 on success or error on failure
4456 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304457int adm_param_enable(int port_id, int copp_idx, int module_id, int enable)
4458{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004459 struct module_instance_info mod_inst_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304460
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004461 memset(&mod_inst_info, 0, sizeof(mod_inst_info));
4462 mod_inst_info.module_id = module_id;
4463 mod_inst_info.instance_id = INSTANCE_ID_0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304464
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004465 return adm_param_enable_v2(port_id, copp_idx, mod_inst_info, enable);
4466}
Vidyakumar Athota98464a22018-03-15 20:39:37 -07004467EXPORT_SYMBOL(adm_param_enable);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004468
4469/**
4470 * adm_param_enable_v2 -
4471 * command to send params to ADM for given module
4472 *
4473 * @port_id: Port ID number
4474 * @copp_idx: copp index assigned
4475 * @mod_inst_info: module and instance ID info
4476 * @enable: flag to enable or disable module
4477 *
4478 * Returns 0 on success or error on failure
4479 */
4480int adm_param_enable_v2(int port_id, int copp_idx,
4481 struct module_instance_info mod_inst_info, int enable)
4482{
4483 uint32_t enable_param;
4484 struct param_hdr_v3 param_hdr;
4485 int rc = 0;
4486
4487 if (enable < 0 || enable > 1) {
4488 pr_err("%s: Invalid value for enable %d\n", __func__, enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304489 return -EINVAL;
4490 }
4491
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004492 pr_debug("%s port_id %d, module_id 0x%x, instance_id 0x%x, enable %d\n",
4493 __func__, port_id, mod_inst_info.module_id,
4494 mod_inst_info.instance_id, enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304495
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004496 memset(&param_hdr, 0, sizeof(param_hdr));
4497 param_hdr.module_id = mod_inst_info.module_id;
4498 param_hdr.instance_id = mod_inst_info.instance_id;
4499 param_hdr.param_id = AUDPROC_PARAM_ID_ENABLE;
4500 param_hdr.param_size = sizeof(enable_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304501
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004502 enable_param = enable;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304503
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004504 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4505 (uint8_t *) &enable_param);
4506 if (rc)
4507 pr_err("%s: Failed to set enable of module(%d) instance(%d) to %d, err %d\n",
4508 __func__, mod_inst_info.module_id,
4509 mod_inst_info.instance_id, enable, rc);
4510
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304511 return rc;
4512
4513}
Vidyakumar Athota98464a22018-03-15 20:39:37 -07004514EXPORT_SYMBOL(adm_param_enable_v2);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304515
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304516/**
4517 * adm_send_calibration -
4518 * send ADM calibration to DSP
4519 *
4520 * @port_id: Port ID number
4521 * @copp_idx: copp index assigned
4522 * @path: direction or ADM path type
4523 * @perf_mode: performance mode like LL/ULL/..
4524 * @cal_type: calibration type to use
4525 * @params: pointer with cal data
4526 * @size: cal size
4527 *
4528 * Returns 0 on success or error on failure
4529 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304530int adm_send_calibration(int port_id, int copp_idx, int path, int perf_mode,
4531 int cal_type, char *params, int size)
4532{
4533
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004534 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304535
4536 pr_debug("%s:port_id %d, path %d, perf_mode %d, cal_type %d, size %d\n",
4537 __func__, port_id, path, perf_mode, cal_type, size);
4538
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304539 /* Maps audio_dev_ctrl path definition to ACDB definition */
4540 if (get_cal_path(path) != RX_DEVICE) {
4541 pr_err("%s: acdb_path %d\n", __func__, path);
4542 rc = -EINVAL;
4543 goto end;
4544 }
4545
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004546 rc = adm_set_pp_params(port_id, copp_idx, NULL, (u8 *) params, size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304547
4548end:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304549 return rc;
4550}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304551EXPORT_SYMBOL(adm_send_calibration);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304552
4553/*
4554 * adm_update_wait_parameters must be called with routing driver locks.
4555 * adm_reset_wait_parameters must be called with routing driver locks.
4556 * set and reset parmeters are separated to make sure it is always called
4557 * under routing driver lock.
4558 * adm_wait_timeout is to block until timeout or interrupted. Timeout is
4559 * not a an error.
4560 */
4561int adm_set_wait_parameters(int port_id, int copp_idx)
4562{
4563
4564 int ret = 0, port_idx;
4565
4566 pr_debug("%s: port_id 0x%x, copp_idx %d\n", __func__, port_id,
4567 copp_idx);
4568 port_id = afe_convert_virtual_to_portid(port_id);
4569 port_idx = adm_validate_and_get_port_index(port_id);
4570 if (port_idx < 0) {
4571 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4572 ret = -EINVAL;
4573 goto end;
4574 }
4575
4576 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4577 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4578 return -EINVAL;
4579 }
4580
4581 this_adm.copp.adm_delay[port_idx][copp_idx] = 1;
4582 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 0);
4583
4584end:
4585 return ret;
4586
4587}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304588EXPORT_SYMBOL(adm_set_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304589
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304590/**
4591 * adm_reset_wait_parameters -
4592 * reset wait parameters or ADM delay value
4593 *
4594 * @port_id: Port ID number
4595 * @copp_idx: copp index assigned
4596 *
4597 * Returns 0 on success or error on failure
4598 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304599int adm_reset_wait_parameters(int port_id, int copp_idx)
4600{
4601 int ret = 0, port_idx;
4602
4603 pr_debug("%s: port_id 0x%x copp_idx %d\n", __func__, port_id,
4604 copp_idx);
4605 port_id = afe_convert_virtual_to_portid(port_id);
4606 port_idx = adm_validate_and_get_port_index(port_id);
4607 if (port_idx < 0) {
4608 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4609 ret = -EINVAL;
4610 goto end;
4611 }
4612
4613 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4614 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4615 return -EINVAL;
4616 }
4617
4618 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 1);
4619 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
4620
4621end:
4622 return ret;
4623}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304624EXPORT_SYMBOL(adm_reset_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304625
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304626/**
4627 * adm_wait_timeout -
4628 * ADM wait command after command send to DSP
4629 *
4630 * @port_id: Port ID number
4631 * @copp_idx: copp index assigned
4632 * @wait_time: value in ms for command timeout
4633 *
4634 * Returns 0 on success or error on failure
4635 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304636int adm_wait_timeout(int port_id, int copp_idx, int wait_time)
4637{
4638 int ret = 0, port_idx;
4639
4640 pr_debug("%s: port_id 0x%x, copp_idx %d, wait_time %d\n", __func__,
4641 port_id, copp_idx, wait_time);
4642 port_id = afe_convert_virtual_to_portid(port_id);
4643 port_idx = adm_validate_and_get_port_index(port_id);
4644 if (port_idx < 0) {
4645 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4646 ret = -EINVAL;
4647 goto end;
4648 }
4649
4650 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4651 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4652 return -EINVAL;
4653 }
4654
4655 ret = wait_event_timeout(
4656 this_adm.copp.adm_delay_wait[port_idx][copp_idx],
4657 atomic_read(&this_adm.copp.adm_delay_stat[port_idx][copp_idx]),
4658 msecs_to_jiffies(wait_time));
4659 pr_debug("%s: return %d\n", __func__, ret);
4660 if (ret != 0)
4661 ret = -EINTR;
4662end:
4663 pr_debug("%s: return %d--\n", __func__, ret);
4664 return ret;
4665}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304666EXPORT_SYMBOL(adm_wait_timeout);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304667
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304668/**
4669 * adm_store_cal_data -
4670 * Retrieve calibration data for ADM copp device
4671 *
4672 * @port_id: Port ID number
4673 * @copp_idx: copp index assigned
4674 * @path: direction or copp type
4675 * @perf_mode: performance mode like LL/ULL/..
4676 * @cal_index: calibration index to use
4677 * @params: pointer to store cal data
4678 * @size: pointer to fill with cal size
4679 *
4680 * Returns 0 on success or error on failure
4681 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304682int adm_store_cal_data(int port_id, int copp_idx, int path, int perf_mode,
4683 int cal_index, char *params, int *size)
4684{
4685 int rc = 0;
4686 struct cal_block_data *cal_block = NULL;
4687 int app_type, acdb_id, port_idx, sample_rate;
4688
4689 if (this_adm.cal_data[cal_index] == NULL) {
4690 pr_debug("%s: cal_index %d not allocated!\n",
4691 __func__, cal_index);
4692 goto end;
4693 }
4694
4695 if (get_cal_path(path) != RX_DEVICE) {
4696 pr_debug("%s: Invalid path to store calibration %d\n",
4697 __func__, path);
4698 rc = -EINVAL;
4699 goto end;
4700 }
4701
4702 port_id = afe_convert_virtual_to_portid(port_id);
4703 port_idx = adm_validate_and_get_port_index(port_id);
4704 if (port_idx < 0) {
4705 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
4706 rc = -EINVAL;
4707 goto end;
4708 }
4709
4710 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4711 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4712 return -EINVAL;
4713 }
4714
4715 acdb_id = atomic_read(&this_adm.copp.acdb_id[port_idx][copp_idx]);
4716 app_type = atomic_read(&this_adm.copp.app_type[port_idx][copp_idx]);
4717 sample_rate = atomic_read(&this_adm.copp.rate[port_idx][copp_idx]);
4718
4719 mutex_lock(&this_adm.cal_data[cal_index]->lock);
4720 cal_block = adm_find_cal(cal_index, get_cal_path(path), app_type,
4721 acdb_id, sample_rate);
4722 if (cal_block == NULL)
4723 goto unlock;
4724
4725 if (cal_block->cal_data.size <= 0) {
4726 pr_debug("%s: No ADM cal send for port_id = 0x%x!\n",
4727 __func__, port_id);
4728 rc = -EINVAL;
4729 goto unlock;
4730 }
4731
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304732 if (cal_index == ADM_AUDPROC_CAL || cal_index == ADM_LSM_AUDPROC_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304733 if (cal_block->cal_data.size > AUD_PROC_BLOCK_SIZE) {
4734 pr_err("%s:audproc:invalid size exp/actual[%zd, %d]\n",
4735 __func__, cal_block->cal_data.size, *size);
4736 rc = -ENOMEM;
4737 goto unlock;
4738 }
Bhalchandra Gajarebbb64142018-05-10 14:16:49 -07004739 } else if (cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
4740 if (cal_block->cal_data.size > AUD_PROC_PERSIST_BLOCK_SIZE) {
4741 pr_err("%s:persist invalid size exp/actual[%zd, %d]\n",
4742 __func__, cal_block->cal_data.size, *size);
4743 rc = -ENOMEM;
4744 goto unlock;
4745 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304746 } else if (cal_index == ADM_AUDVOL_CAL) {
4747 if (cal_block->cal_data.size > AUD_VOL_BLOCK_SIZE) {
4748 pr_err("%s:aud_vol:invalid size exp/actual[%zd, %d]\n",
4749 __func__, cal_block->cal_data.size, *size);
4750 rc = -ENOMEM;
4751 goto unlock;
4752 }
4753 } else {
4754 pr_debug("%s: Not valid calibration for dolby topolgy\n",
4755 __func__);
4756 rc = -EINVAL;
4757 goto unlock;
4758 }
4759 memcpy(params, cal_block->cal_data.kvaddr, cal_block->cal_data.size);
4760 *size = cal_block->cal_data.size;
4761
4762 pr_debug("%s:port_id %d, copp_idx %d, path %d",
4763 __func__, port_id, copp_idx, path);
4764 pr_debug("perf_mode %d, cal_type %d, size %d\n",
4765 perf_mode, cal_index, *size);
4766
4767unlock:
4768 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
4769end:
4770 return rc;
4771}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304772EXPORT_SYMBOL(adm_store_cal_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304773
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304774/**
4775 * adm_send_compressed_device_mute -
4776 * command to send mute for compressed device
4777 *
4778 * @port_id: Port ID number
4779 * @copp_idx: copp index assigned
4780 * @mute_on: flag to indicate mute or unmute
4781 *
4782 * Returns 0 on success or error on failure
4783 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304784int adm_send_compressed_device_mute(int port_id, int copp_idx, bool mute_on)
4785{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004786 u32 mute_param = mute_on ? 1 : 0;
4787 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304788 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304789
4790 pr_debug("%s port_id: 0x%x, copp_idx %d, mute_on: %d\n",
4791 __func__, port_id, copp_idx, mute_on);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304792
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004793 memset(&param_hdr, 0, sizeof(param_hdr));
4794 param_hdr.module_id = AUDPROC_MODULE_ID_COMPRESSED_MUTE;
4795 param_hdr.instance_id = INSTANCE_ID_0;
4796 param_hdr.param_id = AUDPROC_PARAM_ID_COMPRESSED_MUTE;
4797 param_hdr.param_size = sizeof(mute_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304798
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004799 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4800 (uint8_t *) &mute_param);
4801 if (ret)
4802 pr_err("%s: Failed to set mute, err %d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304803
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304804 return ret;
4805}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304806EXPORT_SYMBOL(adm_send_compressed_device_mute);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304807
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304808/**
4809 * adm_send_compressed_device_latency -
4810 * command to send latency for compressed device
4811 *
4812 * @port_id: Port ID number
4813 * @copp_idx: copp index assigned
4814 * @latency: latency value to pass
4815 *
4816 * Returns 0 on success or error on failure
4817 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304818int adm_send_compressed_device_latency(int port_id, int copp_idx, int latency)
4819{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004820 u32 latency_param;
4821 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304822 int ret = 0;
4823
4824 pr_debug("%s port_id: 0x%x, copp_idx %d latency: %d\n", __func__,
4825 port_id, copp_idx, latency);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004826
4827 if (latency < 0) {
4828 pr_err("%s: Invalid value for latency %d", __func__, latency);
4829 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304830 }
4831
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004832 memset(&param_hdr, 0, sizeof(param_hdr));
4833 param_hdr.module_id = AUDPROC_MODULE_ID_COMPRESSED_LATENCY;
4834 param_hdr.instance_id = INSTANCE_ID_0;
4835 param_hdr.param_id = AUDPROC_PARAM_ID_COMPRESSED_LATENCY;
4836 param_hdr.param_size = sizeof(latency_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304837
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004838 latency_param = latency;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304839
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004840 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4841 (uint8_t *) &latency_param);
4842 if (ret)
4843 pr_err("%s: Failed to set latency, err %d\n", __func__, ret);
4844
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304845 return ret;
4846}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304847EXPORT_SYMBOL(adm_send_compressed_device_latency);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304848
4849/**
4850 * adm_swap_speaker_channels
4851 *
4852 * Receives port_id, copp_idx, sample rate, spk_swap and
4853 * send MFC command to swap speaker channel.
4854 * Return zero on success. On failure returns nonzero.
4855 *
4856 * port_id - Passed value, port_id for which channels swap is wanted
4857 * copp_idx - Passed value, copp_idx for which channels swap is wanted
4858 * sample_rate - Passed value, sample rate used by app type config
4859 * spk_swap - Passed value, spk_swap for check if swap flag is set
4860 */
4861int adm_swap_speaker_channels(int port_id, int copp_idx,
4862 int sample_rate, bool spk_swap)
4863{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004864 struct audproc_mfc_param_media_fmt mfc_cfg;
4865 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304866 uint16_t num_channels;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004867 int port_idx = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304868 int ret = 0;
4869
4870 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
4871 __func__, port_id, copp_idx);
4872 port_id = q6audio_convert_virtual_to_portid(port_id);
4873 port_idx = adm_validate_and_get_port_index(port_id);
4874 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
4875 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004876 return -EINVAL;
4877 } else if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4878 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
4879 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304880 }
4881
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004882 num_channels = atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304883 if (num_channels != 2) {
4884 pr_debug("%s: Invalid number of channels: %d\n",
4885 __func__, num_channels);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004886 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304887 }
4888
4889 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004890 memset(&param_hdr, 0, sizeof(param_hdr));
4891
4892 param_hdr.module_id = AUDPROC_MODULE_ID_MFC;
4893 param_hdr.instance_id = INSTANCE_ID_0;
4894 param_hdr.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
4895 param_hdr.param_size = sizeof(mfc_cfg);
4896
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304897 mfc_cfg.sampling_rate = sample_rate;
4898 mfc_cfg.bits_per_sample =
4899 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
4900 mfc_cfg.num_channels = num_channels;
4901
4902 /* Currently applying speaker swap for only 2 channel use case */
4903 if (spk_swap) {
4904 mfc_cfg.channel_type[0] =
4905 (uint16_t) PCM_CHANNEL_FR;
4906 mfc_cfg.channel_type[1] =
4907 (uint16_t) PCM_CHANNEL_FL;
4908 } else {
4909 mfc_cfg.channel_type[0] =
4910 (uint16_t) PCM_CHANNEL_FL;
4911 mfc_cfg.channel_type[1] =
4912 (uint16_t) PCM_CHANNEL_FR;
4913 }
4914
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004915 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4916 (u8 *) &mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304917 if (ret < 0) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004918 pr_err("%s: Failed to set swap speaker channels on port[0x%x] failed %d\n",
4919 __func__, port_id, ret);
4920 return ret;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304921 }
4922
4923 pr_debug("%s: mfc_cfg Set params returned success", __func__);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004924 return 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304925}
4926EXPORT_SYMBOL(adm_swap_speaker_channels);
4927
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304928/**
4929 * adm_set_sound_focus -
4930 * Update sound focus info
4931 *
4932 * @port_id: Port ID number
4933 * @copp_idx: copp index assigned
4934 * @soundFocusData: sound focus data to pass
4935 *
4936 * Returns 0 on success or error on failure
4937 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304938int adm_set_sound_focus(int port_id, int copp_idx,
4939 struct sound_focus_param soundFocusData)
4940{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004941 struct adm_param_fluence_soundfocus_t soundfocus_params;
4942 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304943 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304944 int i;
4945
4946 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
4947 __func__, port_id, copp_idx);
4948
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004949 memset(&param_hdr, 0, sizeof(param_hdr));
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07004950 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004951 param_hdr.instance_id = INSTANCE_ID_0;
4952 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
4953 param_hdr.param_size = sizeof(soundfocus_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304954
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004955 memset(&(soundfocus_params), 0xFF, sizeof(soundfocus_params));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304956 for (i = 0; i < MAX_SECTORS; i++) {
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004957 soundfocus_params.start_angles[i] =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304958 soundFocusData.start_angle[i];
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004959 soundfocus_params.enables[i] = soundFocusData.enable[i];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304960 pr_debug("%s: start_angle[%d] = %d\n",
4961 __func__, i, soundFocusData.start_angle[i]);
4962 pr_debug("%s: enable[%d] = %d\n",
4963 __func__, i, soundFocusData.enable[i]);
4964 }
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004965 soundfocus_params.gain_step = soundFocusData.gain_step;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304966 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData.gain_step);
4967
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004968 soundfocus_params.reserved = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304969
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004970 ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
4971 (uint8_t *) &soundfocus_params);
4972 if (ret)
4973 pr_err("%s: Failed to set sound focus params, err %d\n",
4974 __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304975
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304976 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
4977
4978 return ret;
4979}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304980EXPORT_SYMBOL(adm_set_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304981
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304982/**
4983 * adm_get_sound_focus -
4984 * Retrieve sound focus info
4985 *
4986 * @port_id: Port ID number
4987 * @copp_idx: copp index assigned
4988 * @soundFocusData: pointer for sound focus data to be updated with
4989 *
4990 * Returns 0 on success or error on failure
4991 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304992int adm_get_sound_focus(int port_id, int copp_idx,
4993 struct sound_focus_param *soundFocusData)
4994{
4995 int ret = 0, i;
4996 char *params_value;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08004997 uint32_t max_param_size = 0;
4998 struct adm_param_fluence_soundfocus_t *soundfocus_params = NULL;
4999 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305000
5001 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5002 __func__, port_id, copp_idx);
5003
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005004 max_param_size = sizeof(struct adm_param_fluence_soundfocus_t) +
5005 sizeof(union param_hdrs);
5006 params_value = kzalloc(max_param_size, GFP_KERNEL);
5007 if (!params_value)
5008 return -ENOMEM;
5009
5010 memset(&param_hdr, 0, sizeof(param_hdr));
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005011 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005012 param_hdr.instance_id = INSTANCE_ID_0;
5013 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
5014 param_hdr.param_size = max_param_size;
5015 ret = adm_get_pp_params(port_id, copp_idx,
5016 ADM_CLIENT_ID_SOURCE_TRACKING, NULL, &param_hdr,
5017 params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305018 if (ret) {
5019 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305020 ret = -EINVAL;
5021 goto done;
5022 }
5023
5024 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
5025 pr_err("%s - get params returned error [%s]\n",
5026 __func__, adsp_err_get_err_str(
5027 this_adm.sourceTrackingData.apr_cmd_status));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305028 ret = adsp_err_get_lnx_err_code(
5029 this_adm.sourceTrackingData.apr_cmd_status);
5030 goto done;
5031 }
5032
5033 soundfocus_params = (struct adm_param_fluence_soundfocus_t *)
5034 params_value;
5035 for (i = 0; i < MAX_SECTORS; i++) {
5036 soundFocusData->start_angle[i] =
5037 soundfocus_params->start_angles[i];
5038 soundFocusData->enable[i] = soundfocus_params->enables[i];
5039 pr_debug("%s: start_angle[%d] = %d\n",
5040 __func__, i, soundFocusData->start_angle[i]);
5041 pr_debug("%s: enable[%d] = %d\n",
5042 __func__, i, soundFocusData->enable[i]);
5043 }
5044 soundFocusData->gain_step = soundfocus_params->gain_step;
5045 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData->gain_step);
5046
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305047done:
5048 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5049
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005050 kfree(params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305051 return ret;
5052}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305053EXPORT_SYMBOL(adm_get_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305054
5055static int adm_source_tracking_alloc_map_memory(void)
5056{
5057 int ret;
5058
5059 pr_debug("%s: Enter\n", __func__);
5060
Banajit Goswami08bb7362017-11-03 22:48:23 -07005061 ret = msm_audio_ion_alloc(&this_adm.sourceTrackingData.dma_buf,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305062 AUD_PROC_BLOCK_SIZE,
5063 &this_adm.sourceTrackingData.memmap.paddr,
5064 &this_adm.sourceTrackingData.memmap.size,
5065 &this_adm.sourceTrackingData.memmap.kvaddr);
5066 if (ret) {
5067 pr_err("%s: failed to allocate memory\n", __func__);
5068
5069 ret = -EINVAL;
5070 goto done;
5071 }
5072
5073 atomic_set(&this_adm.mem_map_index, ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
5074 ret = adm_memory_map_regions(&this_adm.sourceTrackingData.memmap.paddr,
5075 0,
5076 (uint32_t *)&this_adm.sourceTrackingData.memmap.size,
5077 1);
5078 if (ret < 0) {
5079 pr_err("%s: failed to map memory, paddr = 0x%pK, size = %d\n",
5080 __func__,
5081 (void *)this_adm.sourceTrackingData.memmap.paddr,
5082 (uint32_t)this_adm.sourceTrackingData.memmap.size);
5083
Banajit Goswami08bb7362017-11-03 22:48:23 -07005084 msm_audio_ion_free(this_adm.sourceTrackingData.dma_buf);
5085 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305086 this_adm.sourceTrackingData.memmap.size = 0;
5087 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5088 this_adm.sourceTrackingData.memmap.paddr = 0;
5089 this_adm.sourceTrackingData.apr_cmd_status = -1;
5090 atomic_set(&this_adm.mem_map_handles
5091 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
5092
5093 ret = -EINVAL;
5094 goto done;
5095 }
5096 ret = 0;
5097 pr_debug("%s: paddr = 0x%pK, size = %d, mem_map_handle = 0x%x\n",
5098 __func__, (void *)this_adm.sourceTrackingData.memmap.paddr,
5099 (uint32_t)this_adm.sourceTrackingData.memmap.size,
5100 atomic_read(&this_adm.mem_map_handles
5101 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING]));
5102
5103done:
5104 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5105
5106 return ret;
5107}
5108
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305109/**
5110 * adm_get_source_tracking -
5111 * Retrieve source tracking info
5112 *
5113 * @port_id: Port ID number
5114 * @copp_idx: copp index assigned
5115 * @sourceTrackingData: pointer for source track data to be updated with
5116 *
5117 * Returns 0 on success or error on failure
5118 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305119int adm_get_source_tracking(int port_id, int copp_idx,
5120 struct source_tracking_param *sourceTrackingData)
5121{
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005122 struct adm_param_fluence_sourcetracking_t *source_tracking_params =
5123 NULL;
5124 struct mem_mapping_hdr mem_hdr;
5125 struct param_hdr_v3 param_hdr;
5126 int i = 0;
5127 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305128
5129 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5130 __func__, port_id, copp_idx);
5131
5132 if (!this_adm.sourceTrackingData.memmap.paddr) {
5133 /* Allocate and map shared memory for out of band usage */
5134 ret = adm_source_tracking_alloc_map_memory();
5135 if (ret != 0) {
5136 ret = -EINVAL;
5137 goto done;
5138 }
5139 }
5140
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005141 memset(&mem_hdr, 0, sizeof(mem_hdr));
5142 memset(&param_hdr, 0, sizeof(param_hdr));
5143 mem_hdr.data_payload_addr_lsw =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305144 lower_32_bits(this_adm.sourceTrackingData.memmap.paddr);
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005145 mem_hdr.data_payload_addr_msw = msm_audio_populate_upper_32_bits(
5146 this_adm.sourceTrackingData.memmap.paddr);
5147 mem_hdr.mem_map_handle = atomic_read(
5148 &this_adm.mem_map_handles[ADM_MEM_MAP_INDEX_SOURCE_TRACKING]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305149
Vignesh Kulothungan6f75e7b2018-06-21 18:05:44 -07005150 param_hdr.module_id = VOICEPROC_MODULE_ID_FLUENCE_PRO_VC_TX;
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005151 param_hdr.instance_id = INSTANCE_ID_0;
5152 param_hdr.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOURCETRACKING;
5153 /*
5154 * This size should be the max size of the calibration data + header.
5155 * Use the union size to ensure max size is used.
5156 */
5157 param_hdr.param_size =
5158 sizeof(struct adm_param_fluence_sourcetracking_t) +
5159 sizeof(union param_hdrs);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305160
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005161 /*
5162 * Retrieving parameters out of band, so no need to provide a buffer for
5163 * the returned parameter data as it will be at the memory location
5164 * provided.
5165 */
5166 ret = adm_get_pp_params(port_id, copp_idx,
5167 ADM_CLIENT_ID_SOURCE_TRACKING, &mem_hdr,
5168 &param_hdr, NULL);
5169 if (ret) {
5170 pr_err("%s: Failed to get params, error %d\n", __func__, ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305171 goto done;
5172 }
5173
5174 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
5175 pr_err("%s - get params returned error [%s]\n",
5176 __func__, adsp_err_get_err_str(
5177 this_adm.sourceTrackingData.apr_cmd_status));
5178
5179 ret = adsp_err_get_lnx_err_code(
5180 this_adm.sourceTrackingData.apr_cmd_status);
5181 goto done;
5182 }
5183
Vignesh Kulothungan60cc0352018-01-29 16:21:22 -08005184 /* How do we know what the param data was retrieved with for hdr size */
5185 source_tracking_params =
5186 (struct adm_param_fluence_sourcetracking_t
5187 *) (this_adm.sourceTrackingData.memmap.kvaddr +
5188 sizeof(struct param_hdr_v1));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305189 for (i = 0; i < MAX_SECTORS; i++) {
5190 sourceTrackingData->vad[i] = source_tracking_params->vad[i];
5191 pr_debug("%s: vad[%d] = %d\n",
5192 __func__, i, sourceTrackingData->vad[i]);
5193 }
5194 sourceTrackingData->doa_speech = source_tracking_params->doa_speech;
5195 pr_debug("%s: doa_speech = %d\n",
5196 __func__, sourceTrackingData->doa_speech);
5197
5198 for (i = 0; i < MAX_NOISE_SOURCE_INDICATORS; i++) {
5199 sourceTrackingData->doa_noise[i] =
5200 source_tracking_params->doa_noise[i];
5201 pr_debug("%s: doa_noise[%d] = %d\n",
5202 __func__, i, sourceTrackingData->doa_noise[i]);
5203 }
5204 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
5205 sourceTrackingData->polar_activity[i] =
5206 source_tracking_params->polar_activity[i];
5207 pr_debug("%s: polar_activity[%d] = %d\n",
5208 __func__, i, sourceTrackingData->polar_activity[i]);
5209 }
5210
5211 ret = 0;
5212
5213done:
5214 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
5215
5216 return ret;
5217}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305218EXPORT_SYMBOL(adm_get_source_tracking);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305219
Chaithanya Krishna Bacharaju8c6a1842018-11-16 15:02:39 +05305220/**
5221 * adm_get_doa_tracking_mon -
5222 * Retrieve doa tracking monitor info
5223 *
5224 * @port_id: Port ID number
5225 * @copp_idx: copp index assigned
5226 * @doa_tracking_data: pointer for doa data to be updated with
5227 *
5228 * Returns 0 on success or error on failure
5229 */
5230int adm_get_doa_tracking_mon(int port_id, int copp_idx,
5231 struct doa_tracking_mon_param *doa_tracking_data)
5232{
5233 int ret = 0, i;
5234 char *params_value;
5235 uint32_t max_param_size = 0;
5236 struct adm_param_doa_tracking_mon_t *doa_tracking_params = NULL;
5237 struct param_hdr_v3 param_hdr;
5238
5239 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5240 __func__, port_id, copp_idx);
5241
5242 if (doa_tracking_data == NULL) {
5243 pr_err("%s: Received NULL pointer for doa tracking data\n",
5244 __func__);
5245 return -EINVAL;
5246 }
5247
5248 max_param_size = sizeof(struct adm_param_doa_tracking_mon_t) +
5249 sizeof(union param_hdrs);
5250 params_value = kzalloc(max_param_size, GFP_KERNEL);
5251 if (!params_value)
5252 return -ENOMEM;
5253
5254 memset(&param_hdr, 0, sizeof(param_hdr));
5255 param_hdr.module_id = AUDPROC_MODULE_ID_FFECNS;
5256 param_hdr.instance_id = INSTANCE_ID_0;
5257 param_hdr.param_id = AUDPROC_PARAM_ID_FFV_DOA_TRACKING_MONITOR;
5258 param_hdr.param_size = max_param_size;
5259 ret = adm_get_pp_params(port_id, copp_idx,
5260 ADM_CLIENT_ID_DEFAULT, NULL, &param_hdr,
5261 params_value);
5262 if (ret) {
5263 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
5264 goto done;
5265 }
5266
5267 doa_tracking_params =
5268 (struct adm_param_doa_tracking_mon_t *)params_value;
5269 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
5270 doa_tracking_data->target_angle_L16[i] =
5271 doa_tracking_params->target_angle_L16[i];
5272 pr_debug("%s: target angle[%d] = %d\n",
5273 __func__, i, doa_tracking_data->target_angle_L16[i]);
5274 }
5275
5276 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
5277 doa_tracking_data->interf_angle_L16[i] =
5278 doa_tracking_params->interf_angle_L16[i];
5279 pr_debug("%s: interference angle[%d] = %d\n",
5280 __func__, i, doa_tracking_data->interf_angle_L16[i]);
5281 }
5282
5283 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
5284 doa_tracking_data->polar_activity[i] =
5285 doa_tracking_params->polar_activity[i];
5286 }
5287
5288done:
5289 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5290 kfree(params_value);
5291 return ret;
5292}
5293EXPORT_SYMBOL(adm_get_doa_tracking_mon);
5294
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305295int __init adm_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305296{
5297 int i = 0, j;
5298
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305299 this_adm.ec_ref_rx = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305300 init_waitqueue_head(&this_adm.matrix_map_wait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305301 init_waitqueue_head(&this_adm.adm_wait);
5302
5303 for (i = 0; i < AFE_MAX_PORTS; i++) {
5304 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
5305 atomic_set(&this_adm.copp.id[i][j], RESET_COPP_ID);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305306 init_waitqueue_head(&this_adm.copp.wait[i][j]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305307 init_waitqueue_head(
5308 &this_adm.copp.adm_delay_wait[i][j]);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305309 }
5310 }
5311
5312 if (adm_init_cal_data())
5313 pr_err("%s: could not init cal data!\n", __func__);
5314
Banajit Goswami08bb7362017-11-03 22:48:23 -07005315 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305316 this_adm.sourceTrackingData.memmap.size = 0;
5317 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5318 this_adm.sourceTrackingData.memmap.paddr = 0;
5319 this_adm.sourceTrackingData.apr_cmd_status = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305320
5321 return 0;
5322}
5323
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05305324void adm_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305325{
Laxminath Kasam30ad7512017-11-28 12:40:22 +05305326 if (this_adm.apr)
5327 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305328 adm_delete_cal_data();
5329}