blob: f8aef943439f94e45f0df6c715b7aff05dc6e742 [file] [log] [blame]
Aditya Bavanari5106b562018-01-08 13:16:32 +05301/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/module.h>
13#include <linux/slab.h>
14#include <linux/wait.h>
15#include <linux/sched.h>
16#include <linux/jiffies.h>
17#include <linux/uaccess.h>
18#include <linux/atomic.h>
19#include <linux/wait.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053020#include <sound/asound.h>
Laxminath Kasam8b1366a2017-10-05 01:44:16 +053021#include <dsp/msm-dts-srs-tm-config.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053022#include <dsp/apr_audio-v2.h>
23#include <dsp/q6adm-v2.h>
24#include <dsp/q6audio-v2.h>
25#include <dsp/q6afe-v2.h>
26#include <dsp/audio_cal_utils.h>
27#include <ipc/apr.h>
28#include "adsp_err.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053029
30#define TIMEOUT_MS 1000
31
32#define RESET_COPP_ID 99
33#define INVALID_COPP_ID 0xFF
34/* Used for inband payload copy, max size is 4k */
35/* 2 is to account for module & param ID in payload */
36#define ADM_GET_PARAMETER_LENGTH (4096 - APR_HDR_SIZE - 2 * sizeof(uint32_t))
37
38#define ULL_SUPPORTED_BITS_PER_SAMPLE 16
39#define ULL_SUPPORTED_SAMPLE_RATE 48000
40
41#ifndef CONFIG_DOLBY_DAP
42#undef DOLBY_ADM_COPP_TOPOLOGY_ID
43#define DOLBY_ADM_COPP_TOPOLOGY_ID 0xFFFFFFFE
44#endif
45
46#ifndef CONFIG_DOLBY_DS2
47#undef DS2_ADM_COPP_TOPOLOGY_ID
48#define DS2_ADM_COPP_TOPOLOGY_ID 0xFFFFFFFF
49#endif
50
51/* ENUM for adm_status */
52enum adm_cal_status {
53 ADM_STATUS_CALIBRATION_REQUIRED = 0,
54 ADM_STATUS_MAX,
55};
56
57struct adm_copp {
58
59 atomic_t id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
60 atomic_t cnt[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
61 atomic_t topology[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
62 atomic_t mode[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
63 atomic_t stat[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
64 atomic_t rate[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
65 atomic_t bit_width[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
66 atomic_t channels[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
67 atomic_t app_type[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
68 atomic_t acdb_id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
69 wait_queue_head_t wait[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
70 wait_queue_head_t adm_delay_wait[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
71 atomic_t adm_delay_stat[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
72 uint32_t adm_delay[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
73 unsigned long adm_status[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
74};
75
76struct source_tracking_data {
Banajit Goswami08bb7362017-11-03 22:48:23 -070077 struct dma_buf *dma_buf;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053078 struct param_outband memmap;
79 int apr_cmd_status;
80};
81
82struct adm_ctl {
83 void *apr;
84
85 struct adm_copp copp;
86
87 atomic_t matrix_map_stat;
88 wait_queue_head_t matrix_map_wait;
89
90 atomic_t adm_stat;
91 wait_queue_head_t adm_wait;
92
93 struct cal_type_data *cal_data[ADM_MAX_CAL_TYPES];
94
95 atomic_t mem_map_handles[ADM_MEM_MAP_INDEX_MAX];
96 atomic_t mem_map_index;
97
98 struct param_outband outband_memmap;
99 struct source_tracking_data sourceTrackingData;
100
101 int set_custom_topology;
102 int ec_ref_rx;
103 int num_ec_ref_rx_chans;
104 int ec_ref_rx_bit_width;
105 int ec_ref_rx_sampling_rate;
106};
107
108static struct adm_ctl this_adm;
109
110struct adm_multi_ch_map {
111 bool set_channel_map;
112 char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
113};
114
115#define ADM_MCH_MAP_IDX_PLAYBACK 0
116#define ADM_MCH_MAP_IDX_REC 1
117static struct adm_multi_ch_map multi_ch_maps[2] = {
118 { false,
119 {0, 0, 0, 0, 0, 0, 0, 0}
120 },
121 { false,
122 {0, 0, 0, 0, 0, 0, 0, 0}
123 }
124};
125
126static int adm_get_parameters[MAX_COPPS_PER_PORT * ADM_GET_PARAMETER_LENGTH];
127static int adm_module_topo_list[
128 MAX_COPPS_PER_PORT * ADM_GET_TOPO_MODULE_LIST_LENGTH];
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530129static struct mutex dts_srs_lock;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530130
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530131void msm_dts_srs_acquire_lock(void)
132{
133 mutex_lock(&dts_srs_lock);
134}
135
136void msm_dts_srs_release_lock(void)
137{
138 mutex_unlock(&dts_srs_lock);
139}
140
141/**
142 * adm_validate_and_get_port_index -
143 * validate given port id
144 *
145 * @port_id: Port ID number
146 *
147 * Returns valid index on success or error on failure
148 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530149int adm_validate_and_get_port_index(int port_id)
150{
151 int index;
152 int ret;
153
154 ret = q6audio_validate_port(port_id);
155 if (ret < 0) {
156 pr_err("%s: port validation failed id 0x%x ret %d\n",
157 __func__, port_id, ret);
158 return -EINVAL;
159 }
160
161 index = afe_get_port_index(port_id);
162 if (index < 0 || index >= AFE_MAX_PORTS) {
163 pr_err("%s: Invalid port idx %d port_id 0x%x\n",
164 __func__, index,
165 port_id);
166 return -EINVAL;
167 }
168 pr_debug("%s: port_idx- %d\n", __func__, index);
169 return index;
170}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530171EXPORT_SYMBOL(adm_validate_and_get_port_index);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530172
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530173/**
174 * adm_get_default_copp_idx -
175 * retrieve default copp_idx for given port
176 *
177 * @port_id: Port ID number
178 *
179 * Returns valid value on success or error on failure
180 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530181int adm_get_default_copp_idx(int port_id)
182{
183 int port_idx = adm_validate_and_get_port_index(port_id), idx;
184
185 if (port_idx < 0) {
186 pr_err("%s: Invalid port id: 0x%x", __func__, port_id);
187 return -EINVAL;
188 }
189 pr_debug("%s: port_idx:%d\n", __func__, port_idx);
190 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
191 if (atomic_read(&this_adm.copp.id[port_idx][idx]) !=
192 RESET_COPP_ID)
193 return idx;
194 }
195 return -EINVAL;
196}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530197EXPORT_SYMBOL(adm_get_default_copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530198
199int adm_get_topology_for_port_from_copp_id(int port_id, int copp_id)
200{
201 int port_idx = adm_validate_and_get_port_index(port_id), idx;
202
203 if (port_idx < 0) {
204 pr_err("%s: Invalid port id: 0x%x", __func__, port_id);
205 return 0;
206 }
207 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
208 if (atomic_read(&this_adm.copp.id[port_idx][idx]) == copp_id)
209 return atomic_read(&this_adm.copp.topology[port_idx]
210 [idx]);
211 pr_err("%s: Invalid copp_id %d port_id 0x%x\n",
212 __func__, copp_id, port_id);
213 return 0;
214}
215
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530216/**
217 * adm_get_topology_for_port_copp_idx -
218 * retrieve topology of given port/copp_idx
219 *
220 * @port_id: Port ID number
221 * @copp_idx: copp index of ADM copp
222 *
223 * Returns valid value on success or 0 on failure
224 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530225int adm_get_topology_for_port_copp_idx(int port_id, int copp_idx)
226{
227 int port_idx = adm_validate_and_get_port_index(port_id);
228
229 if (port_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
230 pr_err("%s: Invalid port: 0x%x copp id: 0x%x",
231 __func__, port_id, copp_idx);
232 return 0;
233 }
234 return atomic_read(&this_adm.copp.topology[port_idx][copp_idx]);
235}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530236EXPORT_SYMBOL(adm_get_topology_for_port_copp_idx);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530237
238int adm_get_indexes_from_copp_id(int copp_id, int *copp_idx, int *port_idx)
239{
240 int p_idx, c_idx;
241
242 for (p_idx = 0; p_idx < AFE_MAX_PORTS; p_idx++) {
243 for (c_idx = 0; c_idx < MAX_COPPS_PER_PORT; c_idx++) {
244 if (atomic_read(&this_adm.copp.id[p_idx][c_idx])
245 == copp_id) {
246 if (copp_idx != NULL)
247 *copp_idx = c_idx;
248 if (port_idx != NULL)
249 *port_idx = p_idx;
250 return 0;
251 }
252 }
253 }
254 return -EINVAL;
255}
256
257static int adm_get_copp_id(int port_idx, int copp_idx)
258{
259 pr_debug("%s: port_idx:%d copp_idx:%d\n", __func__, port_idx, copp_idx);
260
261 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
262 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
263 return -EINVAL;
264 }
265 return atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
266}
267
268static int adm_get_idx_if_copp_exists(int port_idx, int topology, int mode,
269 int rate, int bit_width, int app_type)
270{
271 int idx;
272
273 pr_debug("%s: port_idx-%d, topology-0x%x, mode-%d, rate-%d, bit_width-%d\n",
274 __func__, port_idx, topology, mode, rate, bit_width);
275
276 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
277 if ((topology ==
278 atomic_read(&this_adm.copp.topology[port_idx][idx])) &&
279 (mode == atomic_read(&this_adm.copp.mode[port_idx][idx])) &&
280 (rate == atomic_read(&this_adm.copp.rate[port_idx][idx])) &&
281 (bit_width ==
282 atomic_read(&this_adm.copp.bit_width[port_idx][idx])) &&
283 (app_type ==
284 atomic_read(&this_adm.copp.app_type[port_idx][idx])))
285 return idx;
286 return -EINVAL;
287}
288
289static int adm_get_next_available_copp(int port_idx)
290{
291 int idx;
292
293 pr_debug("%s:\n", __func__);
294 for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
295 pr_debug("%s: copp_id:0x%x port_idx:%d idx:%d\n", __func__,
296 atomic_read(&this_adm.copp.id[port_idx][idx]),
297 port_idx, idx);
298 if (atomic_read(&this_adm.copp.id[port_idx][idx]) ==
299 RESET_COPP_ID)
300 break;
301 }
302 return idx;
303}
304
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530305/**
306 * srs_trumedia_open -
307 * command to set SRS trumedia open
308 *
309 * @port_id: Port ID number
310 * @copp_idx: copp index of ADM copp
311 * @srs_tech_id: SRS tech index
312 * @srs_params: params pointer
313 *
314 * Returns 0 on success or error on failure
315 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530316int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id,
317 void *srs_params)
318{
319 struct adm_cmd_set_pp_params_inband_v5 *adm_params = NULL;
320 struct adm_cmd_set_pp_params_v5 *adm_params_ = NULL;
321 __s32 sz = 0, param_id, module_id = SRS_TRUMEDIA_MODULE_ID, outband = 0;
322 int ret = 0, port_idx;
323
324 pr_debug("SRS - %s", __func__);
325
326 port_id = afe_convert_virtual_to_portid(port_id);
327 port_idx = adm_validate_and_get_port_index(port_id);
328 if (port_idx < 0) {
329 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
330 return -EINVAL;
331 }
332 switch (srs_tech_id) {
333 case SRS_ID_GLOBAL: {
334 struct srs_trumedia_params_GLOBAL *glb_params = NULL;
335
336 sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
337 sizeof(struct srs_trumedia_params_GLOBAL);
338 adm_params = kzalloc(sz, GFP_KERNEL);
339 if (!adm_params) {
340 pr_err("%s, adm params memory alloc failed\n",
341 __func__);
342 return -ENOMEM;
343 }
344 adm_params->payload_size =
345 sizeof(struct srs_trumedia_params_GLOBAL) +
346 sizeof(struct adm_param_data_v5);
347 param_id = SRS_TRUMEDIA_PARAMS;
348 adm_params->params.param_size =
349 sizeof(struct srs_trumedia_params_GLOBAL);
350 glb_params = (struct srs_trumedia_params_GLOBAL *)
351 ((u8 *)adm_params +
352 sizeof(struct adm_cmd_set_pp_params_inband_v5));
353 memcpy(glb_params, srs_params,
354 sizeof(struct srs_trumedia_params_GLOBAL));
355 break;
356 }
357 case SRS_ID_WOWHD: {
358 struct srs_trumedia_params_WOWHD *whd_params = NULL;
359
360 sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
361 sizeof(struct srs_trumedia_params_WOWHD);
362 adm_params = kzalloc(sz, GFP_KERNEL);
363 if (!adm_params) {
364 pr_err("%s, adm params memory alloc failed\n",
365 __func__);
366 return -ENOMEM;
367 }
368 adm_params->payload_size =
369 sizeof(struct srs_trumedia_params_WOWHD) +
370 sizeof(struct adm_param_data_v5);
371 param_id = SRS_TRUMEDIA_PARAMS_WOWHD;
372 adm_params->params.param_size =
373 sizeof(struct srs_trumedia_params_WOWHD);
374 whd_params = (struct srs_trumedia_params_WOWHD *)
375 ((u8 *)adm_params +
376 sizeof(struct adm_cmd_set_pp_params_inband_v5));
377 memcpy(whd_params, srs_params,
378 sizeof(struct srs_trumedia_params_WOWHD));
379 break;
380 }
381 case SRS_ID_CSHP: {
382 struct srs_trumedia_params_CSHP *chp_params = NULL;
383
384 sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
385 sizeof(struct srs_trumedia_params_CSHP);
386 adm_params = kzalloc(sz, GFP_KERNEL);
387 if (!adm_params) {
388 pr_err("%s, adm params memory alloc failed\n",
389 __func__);
390 return -ENOMEM;
391 }
392 adm_params->payload_size =
393 sizeof(struct srs_trumedia_params_CSHP) +
394 sizeof(struct adm_param_data_v5);
395 param_id = SRS_TRUMEDIA_PARAMS_CSHP;
396 adm_params->params.param_size =
397 sizeof(struct srs_trumedia_params_CSHP);
398 chp_params = (struct srs_trumedia_params_CSHP *)
399 ((u8 *)adm_params +
400 sizeof(struct adm_cmd_set_pp_params_inband_v5));
401 memcpy(chp_params, srs_params,
402 sizeof(struct srs_trumedia_params_CSHP));
403 break;
404 }
405 case SRS_ID_HPF: {
406 struct srs_trumedia_params_HPF *hpf_params = NULL;
407
408 sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
409 sizeof(struct srs_trumedia_params_HPF);
410 adm_params = kzalloc(sz, GFP_KERNEL);
411 if (!adm_params) {
412 pr_err("%s, adm params memory alloc failed\n",
413 __func__);
414 return -ENOMEM;
415 }
416 adm_params->payload_size =
417 sizeof(struct srs_trumedia_params_HPF) +
418 sizeof(struct adm_param_data_v5);
419 param_id = SRS_TRUMEDIA_PARAMS_HPF;
420 adm_params->params.param_size =
421 sizeof(struct srs_trumedia_params_HPF);
422 hpf_params = (struct srs_trumedia_params_HPF *)
423 ((u8 *)adm_params +
424 sizeof(struct adm_cmd_set_pp_params_inband_v5));
425 memcpy(hpf_params, srs_params,
426 sizeof(struct srs_trumedia_params_HPF));
427 break;
428 }
429 case SRS_ID_AEQ: {
430 int *update_params_ptr = (int *)this_adm.outband_memmap.kvaddr;
431
432 outband = 1;
433 adm_params = kzalloc(sizeof(struct adm_cmd_set_pp_params_v5),
434 GFP_KERNEL);
435 adm_params_ = (struct adm_cmd_set_pp_params_v5 *)adm_params;
436 if (!adm_params_) {
437 pr_err("%s, adm params memory alloc failed\n",
438 __func__);
439 return -ENOMEM;
440 }
441
442 sz = sizeof(struct srs_trumedia_params_AEQ);
443 if (update_params_ptr == NULL) {
444 pr_err("ADM_SRS_TRUMEDIA - %s: null memmap for AEQ params\n",
445 __func__);
446 ret = -EINVAL;
447 goto fail_cmd;
448 }
449 param_id = SRS_TRUMEDIA_PARAMS_AEQ;
450 *update_params_ptr++ = module_id;
451 *update_params_ptr++ = param_id;
452 *update_params_ptr++ = sz;
453 memcpy(update_params_ptr, srs_params, sz);
454
455 adm_params_->payload_size = sz + 12;
456
457 break;
458 }
459 case SRS_ID_HL: {
460 struct srs_trumedia_params_HL *hl_params = NULL;
461
462 sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
463 sizeof(struct srs_trumedia_params_HL);
464 adm_params = kzalloc(sz, GFP_KERNEL);
465 if (!adm_params) {
466 pr_err("%s, adm params memory alloc failed\n",
467 __func__);
468 return -ENOMEM;
469 }
470 adm_params->payload_size =
471 sizeof(struct srs_trumedia_params_HL) +
472 sizeof(struct adm_param_data_v5);
473 param_id = SRS_TRUMEDIA_PARAMS_HL;
474 adm_params->params.param_size =
475 sizeof(struct srs_trumedia_params_HL);
476 hl_params = (struct srs_trumedia_params_HL *)
477 ((u8 *)adm_params +
478 sizeof(struct adm_cmd_set_pp_params_inband_v5));
479 memcpy(hl_params, srs_params,
480 sizeof(struct srs_trumedia_params_HL));
481 break;
482 }
483 case SRS_ID_GEQ: {
484 struct srs_trumedia_params_GEQ *geq_params = NULL;
485
486 sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
487 sizeof(struct srs_trumedia_params_GEQ);
488 adm_params = kzalloc(sz, GFP_KERNEL);
489 if (!adm_params) {
490 pr_err("%s, adm params memory alloc failed\n",
491 __func__);
492 return -ENOMEM;
493 }
494 adm_params->payload_size =
495 sizeof(struct srs_trumedia_params_GEQ) +
496 sizeof(struct adm_param_data_v5);
497 param_id = SRS_TRUMEDIA_PARAMS_GEQ;
498 adm_params->params.param_size =
499 sizeof(struct srs_trumedia_params_GEQ);
500 geq_params = (struct srs_trumedia_params_GEQ *)
501 ((u8 *)adm_params +
502 sizeof(struct adm_cmd_set_pp_params_inband_v5));
503 memcpy(geq_params, srs_params,
504 sizeof(struct srs_trumedia_params_GEQ));
505 pr_debug("SRS - %s: GEQ params prepared\n", __func__);
506 break;
507 }
508 default:
509 goto fail_cmd;
510 }
511
512 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
513 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
514 adm_params->hdr.src_svc = APR_SVC_ADM;
515 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
516 adm_params->hdr.src_port = port_id;
517 adm_params->hdr.dest_svc = APR_SVC_ADM;
518 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
519 adm_params->hdr.dest_port =
520 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
521 adm_params->hdr.token = port_idx << 16 | copp_idx;
522 adm_params->hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
523 if (outband && this_adm.outband_memmap.paddr) {
524 adm_params->hdr.pkt_size =
525 sizeof(struct adm_cmd_set_pp_params_v5);
526 adm_params->payload_addr_lsw = lower_32_bits(
527 this_adm.outband_memmap.paddr);
528 adm_params->payload_addr_msw = msm_audio_populate_upper_32_bits(
529 this_adm.outband_memmap.paddr);
530 adm_params->mem_map_handle = atomic_read(&this_adm.
531 mem_map_handles[ADM_SRS_TRUMEDIA]);
532 } else {
533 adm_params->hdr.pkt_size = sz;
534 adm_params->payload_addr_lsw = 0;
535 adm_params->payload_addr_msw = 0;
536 adm_params->mem_map_handle = 0;
537
538 adm_params->params.module_id = module_id;
539 adm_params->params.param_id = param_id;
540 adm_params->params.reserved = 0;
541 }
542
543 pr_debug("SRS - %s: Command was sent now check Q6 - port id = %d, size %d, module id %x, param id %x.\n",
544 __func__, adm_params->hdr.dest_port,
545 adm_params->payload_size, module_id, param_id);
546
547 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
548 ret = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
549 if (ret < 0) {
550 pr_err("SRS - %s: ADM enable for port %d failed\n", __func__,
551 port_id);
552 ret = -EINVAL;
553 goto fail_cmd;
554 }
555 /* Wait for the callback with copp id */
556 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
557 atomic_read(&this_adm.copp.stat
558 [port_idx][copp_idx]) >= 0,
559 msecs_to_jiffies(TIMEOUT_MS));
560 if (!ret) {
561 pr_err("%s: SRS set params timed out port = %d\n",
562 __func__, port_id);
563 ret = -EINVAL;
564 goto fail_cmd;
565 } else if (atomic_read(&this_adm.copp.stat
566 [port_idx][copp_idx]) > 0) {
567 pr_err("%s: DSP returned error[%s]\n",
568 __func__, adsp_err_get_err_str(
569 atomic_read(&this_adm.copp.stat
570 [port_idx][copp_idx])));
571 ret = adsp_err_get_lnx_err_code(
572 atomic_read(&this_adm.copp.stat
573 [port_idx][copp_idx]));
574 goto fail_cmd;
575 }
576
577fail_cmd:
578 kfree(adm_params);
579 return ret;
580}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530581EXPORT_SYMBOL(srs_trumedia_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530582
583static int adm_populate_channel_weight(u16 *ptr,
584 struct msm_pcm_channel_mixer *ch_mixer,
585 int channel_index)
586{
587 u16 i, j, start_index = 0;
588
589 if (channel_index > ch_mixer->output_channel) {
590 pr_err("%s: channel index %d is larger than output_channel %d\n",
591 __func__, channel_index, ch_mixer->output_channel);
592 return -EINVAL;
593 }
594
595 for (i = 0; i < ch_mixer->output_channel; i++) {
596 pr_debug("%s: weight for output %d:", __func__, i);
597 for (j = 0; j < ADM_MAX_CHANNELS; j++)
598 pr_debug(" %d",
599 ch_mixer->channel_weight[i][j]);
600 pr_debug("\n");
601 }
602
603 for (i = 0; i < channel_index; ++i)
604 start_index += ch_mixer->input_channels[i];
605
606 for (i = 0; i < ch_mixer->output_channel; ++i) {
607 for (j = start_index;
608 j < start_index +
609 ch_mixer->input_channels[channel_index]; j++) {
610 *ptr = ch_mixer->channel_weight[i][j];
611 pr_debug("%s: ptr[%d][%d] = %d\n",
612 __func__, i, j, *ptr);
613 ptr++;
614 }
615 }
616
617 return 0;
618}
619
620/*
621 * adm_programable_channel_mixer
622 *
623 * Receives port_id, copp_idx, session_id, session_type, ch_mixer
624 * and channel_index to send ADM command to mix COPP data.
625 *
626 * port_id - Passed value, port_id for which backend is wanted
627 * copp_idx - Passed value, copp_idx for which COPP is wanted
628 * session_id - Passed value, session_id for which session is needed
629 * session_type - Passed value, session_type for RX or TX
630 * ch_mixer - Passed value, ch_mixer for which channel mixer config is needed
631 * channel_index - Passed value, channel_index for which channel is needed
632 */
633int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
634 int session_type,
635 struct msm_pcm_channel_mixer *ch_mixer,
636 int channel_index)
637{
638 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
639 struct adm_param_data_v5 data_v5;
640 int ret = 0, port_idx, sz = 0, param_size = 0;
641 u16 *adm_pspd_params;
642 u16 *ptr;
643 int index = 0;
644
645 pr_debug("%s: port_id = %d\n", __func__, port_id);
646 port_id = afe_convert_virtual_to_portid(port_id);
647 port_idx = adm_validate_and_get_port_index(port_id);
648 if (port_idx < 0) {
649 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
650 return -EINVAL;
651 }
652 /*
653 * First 8 bytes are 4 bytes as rule number, 2 bytes as output
654 * channel and 2 bytes as input channel.
655 * 2 * ch_mixer->output_channel means output channel mapping.
656 * 2 * ch_mixer->input_channels[channel_index]) means input
657 * channel mapping.
658 * 2 * ch_mixer->input_channels[channel_index] *
659 * ch_mixer->output_channel) means the channel mixer weighting
660 * coefficients.
661 * param_size needs to be a multiple of 4 bytes.
662 */
663
664 param_size = 2 * (4 + ch_mixer->output_channel +
665 ch_mixer->input_channels[channel_index] +
666 ch_mixer->input_channels[channel_index] *
667 ch_mixer->output_channel);
668 roundup(param_size, 4);
669
670 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
671 sizeof(struct default_chmixer_param_id_coeff) +
672 sizeof(struct adm_param_data_v5) + param_size;
673 pr_debug("%s: sz = %d\n", __func__, sz);
674 adm_params = kzalloc(sz, GFP_KERNEL);
675 if (!adm_params)
676 return -ENOMEM;
677
678 adm_params->payload_addr_lsw = 0;
679 adm_params->payload_addr_msw = 0;
680 adm_params->mem_map_handle = 0;
681 adm_params->direction = session_type;
682 adm_params->sessionid = session_id;
683 pr_debug("%s: copp_id = %d, session id %d\n", __func__,
684 atomic_read(&this_adm.copp.id[port_idx][copp_idx]),
685 session_id);
686 adm_params->deviceid = atomic_read(
687 &this_adm.copp.id[port_idx][copp_idx]);
688 adm_params->reserved = 0;
689
690 data_v5.module_id = MTMX_MODULE_ID_DEFAULT_CHMIXER;
691 data_v5.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
692 data_v5.reserved = 0;
693 data_v5.param_size = param_size;
694 adm_params->payload_size =
695 sizeof(struct default_chmixer_param_id_coeff) +
696 sizeof(struct adm_param_data_v5) + data_v5.param_size;
697 adm_pspd_params = (u16 *)((u8 *)adm_params +
698 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5));
699 memcpy(adm_pspd_params, &data_v5, sizeof(data_v5));
700
701 adm_pspd_params = (u16 *)((u8 *)adm_params +
702 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)
703 + sizeof(data_v5));
704
705 adm_pspd_params[0] = ch_mixer->rule;
706 adm_pspd_params[2] = ch_mixer->output_channel;
707 adm_pspd_params[3] = ch_mixer->input_channels[channel_index];
708 index = 4;
709
710 if (ch_mixer->output_channel == 1) {
711 adm_pspd_params[index] = PCM_CHANNEL_FC;
712 } else if (ch_mixer->output_channel == 2) {
713 adm_pspd_params[index] = PCM_CHANNEL_FL;
714 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
715 } else if (ch_mixer->output_channel == 3) {
716 adm_pspd_params[index] = PCM_CHANNEL_FL;
717 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
718 adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
719 } else if (ch_mixer->output_channel == 4) {
720 adm_pspd_params[index] = PCM_CHANNEL_FL;
721 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
722 adm_pspd_params[index + 2] = PCM_CHANNEL_LS;
723 adm_pspd_params[index + 3] = PCM_CHANNEL_RS;
724 } else if (ch_mixer->output_channel == 5) {
725 adm_pspd_params[index] = PCM_CHANNEL_FL;
726 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
727 adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
728 adm_pspd_params[index + 3] = PCM_CHANNEL_LS;
729 adm_pspd_params[index + 4] = PCM_CHANNEL_RS;
730 } else if (ch_mixer->output_channel == 6) {
731 adm_pspd_params[index] = PCM_CHANNEL_FL;
732 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
733 adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
734 adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
735 adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
736 adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
737 } else if (ch_mixer->output_channel == 8) {
738 adm_pspd_params[index] = PCM_CHANNEL_FL;
739 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
740 adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
741 adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
742 adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
743 adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
744 adm_pspd_params[index + 6] = PCM_CHANNEL_LB;
745 adm_pspd_params[index + 7] = PCM_CHANNEL_RB;
746 }
747
748 index = index + ch_mixer->output_channel;
749 if (ch_mixer->input_channels[channel_index] == 1) {
750 adm_pspd_params[index] = PCM_CHANNEL_FC;
751 } else if (ch_mixer->input_channels[channel_index] == 2) {
752 adm_pspd_params[index] = PCM_CHANNEL_FL;
753 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
754 } else if (ch_mixer->input_channels[channel_index] == 3) {
755 adm_pspd_params[index] = PCM_CHANNEL_FL;
756 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
757 adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
758 } else if (ch_mixer->input_channels[channel_index] == 4) {
759 adm_pspd_params[index] = PCM_CHANNEL_FL;
760 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
761 adm_pspd_params[index + 2] = PCM_CHANNEL_LS;
762 adm_pspd_params[index + 3] = PCM_CHANNEL_RS;
763 } else if (ch_mixer->input_channels[channel_index] == 5) {
764 adm_pspd_params[index] = PCM_CHANNEL_FL;
765 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
766 adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
767 adm_pspd_params[index + 3] = PCM_CHANNEL_LS;
768 adm_pspd_params[index + 4] = PCM_CHANNEL_RS;
769 } else if (ch_mixer->input_channels[channel_index] == 6) {
770 adm_pspd_params[index] = PCM_CHANNEL_FL;
771 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
772 adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
773 adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
774 adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
775 adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
776 } else if (ch_mixer->input_channels[channel_index] == 8) {
777 adm_pspd_params[index] = PCM_CHANNEL_FL;
778 adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
779 adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
780 adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
781 adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
782 adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
783 adm_pspd_params[index + 6] = PCM_CHANNEL_LB;
784 adm_pspd_params[index + 7] = PCM_CHANNEL_RB;
785 }
786
787 index = index + ch_mixer->input_channels[channel_index];
788 ret = adm_populate_channel_weight(&adm_pspd_params[index],
789 ch_mixer, channel_index);
790 if (!ret) {
791 pr_err("%s: fail to get channel weight with error %d\n",
792 __func__, ret);
793 goto fail_cmd;
794 }
795
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.src_svc = APR_SVC_ADM;
799 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
800 adm_params->hdr.src_port = port_id;
801 adm_params->hdr.dest_svc = APR_SVC_ADM;
802 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
803 adm_params->hdr.dest_port =
804 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
805 adm_params->hdr.token = port_idx << 16 | copp_idx;
806 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
807 adm_params->hdr.pkt_size = sz;
808 adm_params->payload_addr_lsw = 0;
809 adm_params->payload_addr_msw = 0;
810 adm_params->mem_map_handle = 0;
811 adm_params->reserved = 0;
812
813 ptr = (u16 *)adm_params;
814 for (index = 0; index < (sz / 2); index++)
815 pr_debug("%s: adm_params[%d] = 0x%x\n",
816 __func__, index, (unsigned int)ptr[index]);
817
818 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], 0);
819 ret = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
820 if (ret < 0) {
821 pr_err("%s: Set params failed port %d rc %d\n", __func__,
822 port_id, ret);
823 ret = -EINVAL;
824 goto fail_cmd;
825 }
826
827 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
828 atomic_read(
829 &this_adm.copp.stat[port_idx][copp_idx]) >= 0,
830 msecs_to_jiffies(TIMEOUT_MS));
831 if (!ret) {
832 pr_err("%s: set params timed out port = %d\n",
833 __func__, port_id);
834 ret = -ETIMEDOUT;
835 goto fail_cmd;
836 }
837 ret = 0;
838fail_cmd:
839 kfree(adm_params);
840
841 return ret;
842}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530843EXPORT_SYMBOL(adm_programable_channel_mixer);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530844
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530845/**
846 * adm_set_stereo_to_custom_stereo -
847 * command to update custom stereo
848 *
849 * @port_id: Port ID number
850 * @copp_idx: copp index of ADM copp
851 * @session_id: session id to be updated
852 * @params: params pointer
853 * @param_length: length of params
854 *
855 * Returns 0 on success or error on failure
856 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530857int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx,
858 unsigned int session_id, char *params,
859 uint32_t params_length)
860{
861 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
862 int sz, rc = 0, port_idx;
863
864 pr_debug("%s:\n", __func__);
865 port_id = afe_convert_virtual_to_portid(port_id);
866 port_idx = adm_validate_and_get_port_index(port_id);
867 if (port_idx < 0) {
868 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
869 return -EINVAL;
870 }
871
872 sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
873 params_length;
874 adm_params = kzalloc(sz, GFP_KERNEL);
875 if (!adm_params) {
876 pr_err("%s, adm params memory alloc failed\n", __func__);
877 return -ENOMEM;
878 }
879
880 memcpy(((u8 *)adm_params +
881 sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)),
882 params, params_length);
883 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
884 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
885 adm_params->hdr.pkt_size = sz;
886 adm_params->hdr.src_svc = APR_SVC_ADM;
887 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
888 adm_params->hdr.src_port = port_id;
889 adm_params->hdr.dest_svc = APR_SVC_ADM;
890 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
891 adm_params->hdr.dest_port = 0; /* Ignored */;
892 adm_params->hdr.token = port_idx << 16 | copp_idx;
893 adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
894 adm_params->payload_addr_lsw = 0;
895 adm_params->payload_addr_msw = 0;
896 adm_params->mem_map_handle = 0;
897 adm_params->payload_size = params_length;
898 /* direction RX as 0 */
899 adm_params->direction = ADM_MATRIX_ID_AUDIO_RX;
900 /* session id for this cmd to be applied on */
901 adm_params->sessionid = session_id;
902 adm_params->deviceid =
903 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
904 adm_params->reserved = 0;
905 pr_debug("%s: deviceid %d, session_id %d, src_port %d, dest_port %d\n",
906 __func__, adm_params->deviceid, adm_params->sessionid,
907 adm_params->hdr.src_port, adm_params->hdr.dest_port);
908 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
909 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
910 if (rc < 0) {
911 pr_err("%s: Set params failed port = 0x%x rc %d\n",
912 __func__, port_id, rc);
913 rc = -EINVAL;
914 goto set_stereo_to_custom_stereo_return;
915 }
916 /* Wait for the callback */
917 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
918 atomic_read(&this_adm.copp.stat
919 [port_idx][copp_idx]) >= 0,
920 msecs_to_jiffies(TIMEOUT_MS));
921 if (!rc) {
922 pr_err("%s: Set params timed out port = 0x%x\n", __func__,
923 port_id);
924 rc = -EINVAL;
925 goto set_stereo_to_custom_stereo_return;
926 } else if (atomic_read(&this_adm.copp.stat
927 [port_idx][copp_idx]) > 0) {
928 pr_err("%s: DSP returned error[%s]\n", __func__,
929 adsp_err_get_err_str(atomic_read(
930 &this_adm.copp.stat
931 [port_idx][copp_idx])));
932 rc = adsp_err_get_lnx_err_code(
933 atomic_read(&this_adm.copp.stat
934 [port_idx][copp_idx]));
935 goto set_stereo_to_custom_stereo_return;
936 }
937 rc = 0;
938set_stereo_to_custom_stereo_return:
939 kfree(adm_params);
940 return rc;
941}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530942EXPORT_SYMBOL(adm_set_stereo_to_custom_stereo);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530943
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530944/**
945 * adm_dolby_dap_send_params -
946 * command to send dolby dap params
947 *
948 * @port_id: Port ID number
949 * @copp_idx: copp index of ADM copp
950 * @params: params pointer
951 * @param_length: length of params
952 *
953 * Returns 0 on success or error on failure
954 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530955int adm_dolby_dap_send_params(int port_id, int copp_idx, char *params,
956 uint32_t params_length)
957{
958 struct adm_cmd_set_pp_params_v5 *adm_params = NULL;
959 int sz, rc = 0;
960 int port_idx;
961
962 pr_debug("%s:\n", __func__);
963 port_id = afe_convert_virtual_to_portid(port_id);
964 port_idx = adm_validate_and_get_port_index(port_id);
965 if (port_idx < 0) {
966 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
967 return -EINVAL;
968 }
969
970 sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
971 adm_params = kzalloc(sz, GFP_KERNEL);
972 if (!adm_params) {
973 pr_err("%s, adm params memory alloc failed", __func__);
974 return -ENOMEM;
975 }
976
977 memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
978 params, params_length);
979 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
980 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
981 adm_params->hdr.pkt_size = sz;
982 adm_params->hdr.src_svc = APR_SVC_ADM;
983 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
984 adm_params->hdr.src_port = port_id;
985 adm_params->hdr.dest_svc = APR_SVC_ADM;
986 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
987 adm_params->hdr.dest_port =
988 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
989 adm_params->hdr.token = port_idx << 16 | copp_idx;
990 adm_params->hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
991 adm_params->payload_addr_lsw = 0;
992 adm_params->payload_addr_msw = 0;
993 adm_params->mem_map_handle = 0;
994 adm_params->payload_size = params_length;
995
996 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
997 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
998 if (rc < 0) {
999 pr_err("%s: Set params failed port = 0x%x rc %d\n",
1000 __func__, port_id, rc);
1001 rc = -EINVAL;
1002 goto dolby_dap_send_param_return;
1003 }
1004 /* Wait for the callback */
1005 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1006 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
1007 msecs_to_jiffies(TIMEOUT_MS));
1008 if (!rc) {
1009 pr_err("%s: Set params timed out port = 0x%x\n",
1010 __func__, port_id);
1011 rc = -EINVAL;
1012 goto dolby_dap_send_param_return;
1013 } else if (atomic_read(&this_adm.copp.stat
1014 [port_idx][copp_idx]) > 0) {
1015 pr_err("%s: DSP returned error[%s]\n",
1016 __func__, adsp_err_get_err_str(
1017 atomic_read(&this_adm.copp.stat
1018 [port_idx][copp_idx])));
1019 rc = adsp_err_get_lnx_err_code(
1020 atomic_read(&this_adm.copp.stat
1021 [port_idx][copp_idx]));
1022 goto dolby_dap_send_param_return;
1023 }
1024 rc = 0;
1025dolby_dap_send_param_return:
1026 kfree(adm_params);
1027 return rc;
1028}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301029EXPORT_SYMBOL(adm_dolby_dap_send_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301030
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301031/**
1032 * adm_get_params_v5 -
1033 * command to retrieve ADM params for given module
1034 *
1035 * @port_id: Port ID number
1036 * @copp_idx: copp index of ADM copp
1037 * @params: params pointer
1038 * @param_length: length of params
1039 *
1040 * Returns 0 on success or error on failure
1041 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301042int adm_send_params_v5(int port_id, int copp_idx, char *params,
1043 uint32_t params_length)
1044{
1045 struct adm_cmd_set_pp_params_v5 *adm_params = NULL;
1046 int rc = 0;
1047 int sz, port_idx;
1048
1049 pr_debug("%s:\n", __func__);
1050 port_id = afe_convert_virtual_to_portid(port_id);
1051 port_idx = adm_validate_and_get_port_index(port_id);
1052 if (port_idx < 0) {
1053 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1054 return -EINVAL;
1055 }
1056
1057 sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
1058 adm_params = kzalloc(sz, GFP_KERNEL);
1059 if (!adm_params) {
1060 pr_err("%s, adm params memory alloc failed", __func__);
1061 return -ENOMEM;
1062 }
1063
1064 memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
1065 params, params_length);
1066 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1067 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1068 adm_params->hdr.pkt_size = sz;
1069 adm_params->hdr.src_svc = APR_SVC_ADM;
1070 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
1071 adm_params->hdr.src_port = port_id;
1072 adm_params->hdr.dest_svc = APR_SVC_ADM;
1073 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
1074 adm_params->hdr.dest_port =
1075 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1076 adm_params->hdr.token = port_idx << 16 | copp_idx;
1077 adm_params->hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
1078 adm_params->payload_addr_lsw = 0;
1079 adm_params->payload_addr_msw = 0;
1080 adm_params->mem_map_handle = 0;
1081 adm_params->payload_size = params_length;
1082
1083 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
1084 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
1085 if (rc < 0) {
1086 pr_err("%s: Set params failed port = 0x%x rc %d\n",
1087 __func__, port_id, rc);
1088 rc = -EINVAL;
1089 goto send_param_return;
1090 }
1091 /* Wait for the callback */
1092 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1093 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
1094 msecs_to_jiffies(TIMEOUT_MS));
1095 if (!rc) {
1096 pr_err("%s: Set params timed out port = 0x%x\n",
1097 __func__, port_id);
1098 rc = -EINVAL;
1099 goto send_param_return;
1100 } else if (atomic_read(&this_adm.copp.stat
1101 [port_idx][copp_idx]) > 0) {
1102 pr_err("%s: DSP returned error[%s]\n",
1103 __func__, adsp_err_get_err_str(
1104 atomic_read(&this_adm.copp.stat
1105 [port_idx][copp_idx])));
1106 rc = adsp_err_get_lnx_err_code(
1107 atomic_read(&this_adm.copp.stat
1108 [port_idx][copp_idx]));
1109 goto send_param_return;
1110 }
1111 rc = 0;
1112send_param_return:
1113 kfree(adm_params);
1114 return rc;
1115}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301116EXPORT_SYMBOL(adm_send_params_v5);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301117
1118int adm_get_params_v2(int port_id, int copp_idx, uint32_t module_id,
1119 uint32_t param_id, uint32_t params_length,
1120 char *params, uint32_t client_id)
1121{
1122 struct adm_cmd_get_pp_params_v5 *adm_params = NULL;
1123 int rc = 0, i = 0;
1124 int port_idx, idx;
1125 int *params_data = (int *)params;
1126 uint64_t sz = 0;
1127
1128 port_id = afe_convert_virtual_to_portid(port_id);
1129 port_idx = adm_validate_and_get_port_index(port_id);
1130 if (port_idx < 0) {
1131 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1132 return -EINVAL;
1133 }
1134
1135 sz = (uint64_t)sizeof(struct adm_cmd_get_pp_params_v5) +
1136 (uint64_t)params_length;
1137 /*
1138 * Check if the value of "sz" (which is ultimately assigned to
1139 * "hdr.pkt_size") crosses U16_MAX.
1140 */
1141 if (sz > U16_MAX) {
1142 pr_err("%s: Invalid params_length\n", __func__);
1143 return -EINVAL;
1144 }
1145 adm_params = kzalloc(sz, GFP_KERNEL);
1146 if (!adm_params) {
1147 pr_err("%s: adm params memory alloc failed", __func__);
1148 return -ENOMEM;
1149 }
1150
1151 memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_get_pp_params_v5)),
1152 params, params_length);
1153 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1154 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1155 adm_params->hdr.pkt_size = sz;
1156 adm_params->hdr.src_svc = APR_SVC_ADM;
1157 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
1158 adm_params->hdr.src_port = port_id;
1159 adm_params->hdr.dest_svc = APR_SVC_ADM;
1160 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
1161 adm_params->hdr.dest_port =
1162 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1163 adm_params->hdr.token = port_idx << 16 | client_id << 8 | copp_idx;
1164 adm_params->hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
1165 adm_params->data_payload_addr_lsw = 0;
1166 adm_params->data_payload_addr_msw = 0;
1167 adm_params->mem_map_handle = 0;
1168 adm_params->module_id = module_id;
1169 adm_params->param_id = param_id;
1170 adm_params->param_max_size = params_length;
1171 adm_params->reserved = 0;
1172
1173 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
1174 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
1175 if (rc < 0) {
1176 pr_err("%s: Failed to Get Params on port_id 0x%x %d\n",
1177 __func__, port_id, rc);
1178 rc = -EINVAL;
1179 goto adm_get_param_return;
1180 }
1181 /* Wait for the callback with copp id */
1182 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1183 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
1184 msecs_to_jiffies(TIMEOUT_MS));
1185 if (!rc) {
1186 pr_err("%s: get params timed out port_id = 0x%x\n", __func__,
1187 port_id);
1188 rc = -EINVAL;
1189 goto adm_get_param_return;
1190 } else if (atomic_read(&this_adm.copp.stat
1191 [port_idx][copp_idx]) > 0) {
1192 pr_err("%s: DSP returned error[%s]\n",
1193 __func__, adsp_err_get_err_str(
1194 atomic_read(&this_adm.copp.stat
1195 [port_idx][copp_idx])));
1196 rc = adsp_err_get_lnx_err_code(
1197 atomic_read(&this_adm.copp.stat
1198 [port_idx][copp_idx]));
1199 goto adm_get_param_return;
1200 }
1201 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
1202
1203 if (adm_get_parameters[idx] < 0) {
1204 pr_err("%s: Size is invalid %d\n", __func__,
1205 adm_get_parameters[idx]);
1206 rc = -EINVAL;
1207 goto adm_get_param_return;
1208 }
1209 if ((params_data) &&
1210 (ARRAY_SIZE(adm_get_parameters) >
1211 idx) &&
1212 (ARRAY_SIZE(adm_get_parameters) >=
1213 1+adm_get_parameters[idx]+idx) &&
1214 (params_length/sizeof(uint32_t) >=
1215 adm_get_parameters[idx])) {
1216 for (i = 0; i < adm_get_parameters[idx]; i++)
1217 params_data[i] = adm_get_parameters[1+i+idx];
1218
1219 } else {
1220 pr_err("%s: Get param data not copied! get_param array size %zd, index %d, params array size %zd, index %d\n",
1221 __func__, ARRAY_SIZE(adm_get_parameters),
1222 (1+adm_get_parameters[idx]+idx),
1223 params_length/sizeof(int),
1224 adm_get_parameters[idx]);
1225 }
1226 rc = 0;
1227adm_get_param_return:
1228 kfree(adm_params);
1229
1230 return rc;
1231}
1232
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301233/**
1234 * adm_get_params -
1235 * command to retrieve ADM params for given module
1236 *
1237 * @port_id: Port ID number
1238 * @copp_idx: copp index of ADM copp
1239 * @module_id: module ID
1240 * @param_id: Param index
1241 * @param_length: length of params
1242 * @params: params pointer
1243 *
1244 * Returns 0 on success or error on failure
1245 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301246int adm_get_params(int port_id, int copp_idx, uint32_t module_id,
1247 uint32_t param_id, uint32_t params_length, char *params)
1248{
1249 return adm_get_params_v2(port_id, copp_idx, module_id, param_id,
1250 params_length, params, 0);
1251}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301252EXPORT_SYMBOL(adm_get_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301253
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301254/**
1255 * adm_get_pp_topo_module_list -
1256 * command to update PP top module list
1257 *
1258 * @port_id: Port ID number
1259 * @copp_idx: copp index of ADM copp
1260 * @param_length: length of params
1261 * @params: pointer with PP top module params
1262 *
1263 * Returns 0 on success or error on failure
1264 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301265int adm_get_pp_topo_module_list(int port_id, int copp_idx, int32_t param_length,
1266 char *params)
1267{
1268 struct adm_cmd_get_pp_topo_module_list_t *adm_pp_module_list = NULL;
1269 int sz, rc = 0, i = 0;
1270 int port_idx, idx;
1271 int32_t *params_data = (int32_t *)params;
1272 int *topo_list;
1273
1274 pr_debug("%s : port_id %x", __func__, port_id);
1275 port_id = afe_convert_virtual_to_portid(port_id);
1276 port_idx = adm_validate_and_get_port_index(port_id);
1277 if (port_idx < 0) {
1278 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
1279 return -EINVAL;
1280 }
1281
1282 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1283 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
1284 return -EINVAL;
1285 }
1286
1287 sz = sizeof(struct adm_cmd_get_pp_topo_module_list_t) + param_length;
1288 adm_pp_module_list = kzalloc(sz, GFP_KERNEL);
1289 if (!adm_pp_module_list) {
1290 pr_err("%s, adm params memory alloc failed", __func__);
1291 return -ENOMEM;
1292 }
1293
1294 memcpy(((u8 *)adm_pp_module_list +
1295 sizeof(struct adm_cmd_get_pp_topo_module_list_t)),
1296 params, param_length);
1297 adm_pp_module_list->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1298 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1299 adm_pp_module_list->hdr.pkt_size = sz;
1300 adm_pp_module_list->hdr.src_svc = APR_SVC_ADM;
1301 adm_pp_module_list->hdr.src_domain = APR_DOMAIN_APPS;
1302 adm_pp_module_list->hdr.src_port = port_id;
1303 adm_pp_module_list->hdr.dest_svc = APR_SVC_ADM;
1304 adm_pp_module_list->hdr.dest_domain = APR_DOMAIN_ADSP;
1305 adm_pp_module_list->hdr.dest_port =
1306 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
1307 adm_pp_module_list->hdr.token = port_idx << 16 | copp_idx;
1308 adm_pp_module_list->hdr.opcode = ADM_CMD_GET_PP_TOPO_MODULE_LIST;
1309 adm_pp_module_list->param_max_size = param_length;
1310 /* Payload address and mmap handle set to zero by kzalloc */
1311
1312 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
1313
1314 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_pp_module_list);
1315 if (rc < 0) {
1316 pr_err("%s: Failed to Get Params on port %d\n", __func__,
1317 port_id);
1318 rc = -EINVAL;
1319 goto adm_pp_module_list_l;
1320 }
1321 /* Wait for the callback with copp id */
1322 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
1323 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
1324 msecs_to_jiffies(TIMEOUT_MS));
1325 if (!rc) {
1326 pr_err("%s: get params timed out port = %d\n", __func__,
1327 port_id);
1328 rc = -EINVAL;
1329 goto adm_pp_module_list_l;
1330 } else if (atomic_read(&this_adm.copp.stat
1331 [port_idx][copp_idx]) > 0) {
1332 pr_err("%s: DSP returned error[%s]\n",
1333 __func__, adsp_err_get_err_str(
1334 atomic_read(&this_adm.copp.stat
1335 [port_idx][copp_idx])));
1336 rc = adsp_err_get_lnx_err_code(
1337 atomic_read(&this_adm.copp.stat
1338 [port_idx][copp_idx]));
1339 goto adm_pp_module_list_l;
1340 }
1341 if (params_data) {
1342 idx = ADM_GET_TOPO_MODULE_LIST_LENGTH * copp_idx;
1343 topo_list = (int *)(adm_module_topo_list + idx);
1344 if (param_length <= ADM_GET_TOPO_MODULE_LIST_LENGTH &&
1345 idx <
1346 (MAX_COPPS_PER_PORT * ADM_GET_TOPO_MODULE_LIST_LENGTH))
1347 memcpy(params_data, topo_list, param_length);
1348 else
1349 pr_debug("%s: i/p size:%d > MAX param size:%d\n",
1350 __func__, param_length,
1351 (int)ADM_GET_TOPO_MODULE_LIST_LENGTH);
1352 for (i = 1; i <= params_data[0]; i++)
1353 pr_debug("module = 0x%x\n", params_data[i]);
1354 }
1355 rc = 0;
1356adm_pp_module_list_l:
1357 kfree(adm_pp_module_list);
1358 pr_debug("%s : rc = %d ", __func__, rc);
1359 return rc;
1360}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301361EXPORT_SYMBOL(adm_get_pp_topo_module_list);
1362
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301363static void adm_callback_debug_print(struct apr_client_data *data)
1364{
1365 uint32_t *payload;
1366
1367 payload = data->payload;
1368
1369 if (data->payload_size >= 8)
1370 pr_debug("%s: code = 0x%x PL#0[0x%x], PL#1[0x%x], size = %d\n",
1371 __func__, data->opcode, payload[0], payload[1],
1372 data->payload_size);
1373 else if (data->payload_size >= 4)
1374 pr_debug("%s: code = 0x%x PL#0[0x%x], size = %d\n",
1375 __func__, data->opcode, payload[0],
1376 data->payload_size);
1377 else
1378 pr_debug("%s: code = 0x%x, size = %d\n",
1379 __func__, data->opcode, data->payload_size);
1380}
1381
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301382/**
1383 * adm_set_multi_ch_map -
1384 * Update multi channel map info
1385 *
1386 * @channel_map: pointer with channel map info
1387 * @path: direction or ADM path type
1388 *
1389 * Returns 0 on success or error on failure
1390 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301391int adm_set_multi_ch_map(char *channel_map, int path)
1392{
1393 int idx;
1394
1395 if (path == ADM_PATH_PLAYBACK) {
1396 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1397 } else if (path == ADM_PATH_LIVE_REC) {
1398 idx = ADM_MCH_MAP_IDX_REC;
1399 } else {
1400 pr_err("%s: invalid attempt to set path %d\n", __func__, path);
1401 return -EINVAL;
1402 }
1403
1404 memcpy(multi_ch_maps[idx].channel_mapping, channel_map,
1405 PCM_FORMAT_MAX_NUM_CHANNEL);
1406 multi_ch_maps[idx].set_channel_map = true;
1407
1408 return 0;
1409}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301410EXPORT_SYMBOL(adm_set_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301411
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301412/**
1413 * adm_get_multi_ch_map -
1414 * Retrieves multi channel map info
1415 *
1416 * @channel_map: pointer to be updated with channel map
1417 * @path: direction or ADM path type
1418 *
1419 * Returns 0 on success or error on failure
1420 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301421int adm_get_multi_ch_map(char *channel_map, int path)
1422{
1423 int idx;
1424
1425 if (path == ADM_PATH_PLAYBACK) {
1426 idx = ADM_MCH_MAP_IDX_PLAYBACK;
1427 } else if (path == ADM_PATH_LIVE_REC) {
1428 idx = ADM_MCH_MAP_IDX_REC;
1429 } else {
1430 pr_err("%s: invalid attempt to get path %d\n", __func__, path);
1431 return -EINVAL;
1432 }
1433
1434 if (multi_ch_maps[idx].set_channel_map) {
1435 memcpy(channel_map, multi_ch_maps[idx].channel_mapping,
1436 PCM_FORMAT_MAX_NUM_CHANNEL);
1437 }
1438
1439 return 0;
1440}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301441EXPORT_SYMBOL(adm_get_multi_ch_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301442
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301443static void adm_reset_data(void)
1444{
1445 int i, j;
1446
1447 apr_reset(this_adm.apr);
1448 for (i = 0; i < AFE_MAX_PORTS; i++) {
1449 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
1450 atomic_set(&this_adm.copp.id[i][j],
1451 RESET_COPP_ID);
1452 atomic_set(&this_adm.copp.cnt[i][j], 0);
1453 atomic_set(
1454 &this_adm.copp.topology[i][j], 0);
1455 atomic_set(&this_adm.copp.mode[i][j],
1456 0);
1457 atomic_set(&this_adm.copp.stat[i][j],
1458 0);
1459 atomic_set(&this_adm.copp.rate[i][j],
1460 0);
1461 atomic_set(
1462 &this_adm.copp.channels[i][j],
1463 0);
1464 atomic_set(
1465 &this_adm.copp.bit_width[i][j], 0);
1466 atomic_set(
1467 &this_adm.copp.app_type[i][j], 0);
1468 atomic_set(
1469 &this_adm.copp.acdb_id[i][j], 0);
1470 this_adm.copp.adm_status[i][j] =
1471 ADM_STATUS_CALIBRATION_REQUIRED;
1472 }
1473 }
1474 this_adm.apr = NULL;
1475 cal_utils_clear_cal_block_q6maps(ADM_MAX_CAL_TYPES,
1476 this_adm.cal_data);
1477 mutex_lock(&this_adm.cal_data
1478 [ADM_CUSTOM_TOP_CAL]->lock);
1479 this_adm.set_custom_topology = 1;
1480 mutex_unlock(&this_adm.cal_data[
1481 ADM_CUSTOM_TOP_CAL]->lock);
1482 rtac_clear_mapping(ADM_RTAC_CAL);
1483 /*
1484 * Free the ION memory and clear the map handles
1485 * for Source Tracking
1486 */
1487 if (this_adm.sourceTrackingData.memmap.paddr != 0) {
1488 msm_audio_ion_free(
1489 this_adm.sourceTrackingData.dma_buf);
1490 this_adm.sourceTrackingData.dma_buf = NULL;
1491 this_adm.sourceTrackingData.memmap.size = 0;
1492 this_adm.sourceTrackingData.memmap.kvaddr =
1493 NULL;
1494 this_adm.sourceTrackingData.memmap.paddr = 0;
1495 this_adm.sourceTrackingData.apr_cmd_status = -1;
1496 atomic_set(&this_adm.mem_map_handles[
1497 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
1498 }
1499}
1500
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301501static int32_t adm_callback(struct apr_client_data *data, void *priv)
1502{
1503 uint32_t *payload;
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301504 int i, port_idx, copp_idx, idx, client_id;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301505
1506 if (data == NULL) {
1507 pr_err("%s: data parameter is null\n", __func__);
1508 return -EINVAL;
1509 }
1510
1511 payload = data->payload;
1512
1513 if (data->opcode == RESET_EVENTS) {
1514 pr_debug("%s: Reset event is received: %d %d apr[%pK]\n",
1515 __func__,
1516 data->reset_event, data->reset_proc, this_adm.apr);
Laxminath Kasam30ad7512017-11-28 12:40:22 +05301517 if (this_adm.apr)
1518 adm_reset_data();
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301519 return 0;
1520 }
1521
1522 adm_callback_debug_print(data);
1523 if (data->payload_size) {
1524 copp_idx = (data->token) & 0XFF;
1525 port_idx = ((data->token) >> 16) & 0xFF;
1526 client_id = ((data->token) >> 8) & 0xFF;
1527 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
1528 pr_err("%s: Invalid port idx %d token %d\n",
1529 __func__, port_idx, data->token);
1530 return 0;
1531 }
1532 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
1533 pr_err("%s: Invalid copp idx %d token %d\n",
1534 __func__, copp_idx, data->token);
1535 return 0;
1536 }
1537 if (client_id < 0 || client_id >= ADM_CLIENT_ID_MAX) {
1538 pr_err("%s: Invalid client id %d\n", __func__,
1539 client_id);
1540 return 0;
1541 }
1542 if (data->opcode == APR_BASIC_RSP_RESULT) {
1543 pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
1544 __func__, payload[0]);
1545 if (payload[1] != 0) {
1546 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
1547 __func__, payload[0], payload[1]);
1548 }
1549 switch (payload[0]) {
1550 case ADM_CMD_SET_PP_PARAMS_V5:
1551 pr_debug("%s: ADM_CMD_SET_PP_PARAMS_V5\n",
1552 __func__);
1553 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1554 this_adm.sourceTrackingData.
1555 apr_cmd_status = payload[1];
1556 else if (rtac_make_adm_callback(payload,
1557 data->payload_size))
1558 break;
1559 /*
1560 * if soft volume is called and already
1561 * interrupted break out of the sequence here
1562 */
1563 case ADM_CMD_DEVICE_OPEN_V5:
1564 case ADM_CMD_DEVICE_CLOSE_V5:
1565 case ADM_CMD_DEVICE_OPEN_V6:
1566 pr_debug("%s: Basic callback received, wake up.\n",
1567 __func__);
1568 atomic_set(&this_adm.copp.stat[port_idx]
1569 [copp_idx], payload[1]);
1570 wake_up(
1571 &this_adm.copp.wait[port_idx][copp_idx]);
1572 break;
1573 case ADM_CMD_ADD_TOPOLOGIES:
1574 pr_debug("%s: callback received, ADM_CMD_ADD_TOPOLOGIES.\n",
1575 __func__);
1576 atomic_set(&this_adm.adm_stat, payload[1]);
1577 wake_up(&this_adm.adm_wait);
1578 break;
1579 case ADM_CMD_MATRIX_MAP_ROUTINGS_V5:
1580 case ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5:
1581 pr_debug("%s: Basic callback received, wake up.\n",
1582 __func__);
1583 atomic_set(&this_adm.matrix_map_stat,
1584 payload[1]);
1585 wake_up(&this_adm.matrix_map_wait);
1586 break;
1587 case ADM_CMD_SHARED_MEM_UNMAP_REGIONS:
1588 pr_debug("%s: ADM_CMD_SHARED_MEM_UNMAP_REGIONS\n",
1589 __func__);
1590 atomic_set(&this_adm.adm_stat, payload[1]);
1591 wake_up(&this_adm.adm_wait);
1592 break;
1593 case ADM_CMD_SHARED_MEM_MAP_REGIONS:
1594 pr_debug("%s: ADM_CMD_SHARED_MEM_MAP_REGIONS\n",
1595 __func__);
1596 /* Should only come here if there is an APR */
1597 /* error or malformed APR packet. Otherwise */
1598 /* response will be returned as */
1599 if (payload[1] != 0) {
1600 pr_err("%s: ADM map error, resuming\n",
1601 __func__);
1602 atomic_set(&this_adm.adm_stat,
1603 payload[1]);
1604 wake_up(&this_adm.adm_wait);
1605 }
1606 break;
1607 case ADM_CMD_GET_PP_PARAMS_V5:
1608 pr_debug("%s: ADM_CMD_GET_PP_PARAMS_V5\n",
1609 __func__);
1610 /* Should only come here if there is an APR */
1611 /* error or malformed APR packet. Otherwise */
1612 /* response will be returned as */
1613 /* ADM_CMDRSP_GET_PP_PARAMS_V5 */
1614 if (client_id ==
1615 ADM_CLIENT_ID_SOURCE_TRACKING) {
1616 this_adm.sourceTrackingData.
1617 apr_cmd_status = payload[1];
1618 if (payload[1] != 0)
1619 pr_err("%s: ADM get param error = %d\n",
1620 __func__, payload[1]);
1621
1622 atomic_set(&this_adm.copp.stat
1623 [port_idx][copp_idx],
1624 payload[1]);
1625 wake_up(&this_adm.copp.wait
1626 [port_idx][copp_idx]);
1627 } else {
1628 if (payload[1] != 0) {
1629 pr_err("%s: ADM get param error = %d, resuming\n",
1630 __func__, payload[1]);
1631
1632 rtac_make_adm_callback(payload,
1633 data->payload_size);
1634 }
1635 }
1636 break;
1637 case ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5:
1638 pr_debug("%s: ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5\n",
1639 __func__);
1640 atomic_set(&this_adm.copp.stat[port_idx]
1641 [copp_idx], payload[1]);
1642 wake_up(
1643 &this_adm.copp.wait[port_idx][copp_idx]);
1644 break;
1645 case ADM_CMD_GET_PP_TOPO_MODULE_LIST:
1646 pr_debug("%s:ADM_CMD_GET_PP_TOPO_MODULE_LIST\n",
1647 __func__);
1648 if (payload[1] != 0)
1649 pr_err("%s: ADM get topo list error = %d,\n",
1650 __func__, payload[1]);
1651 break;
1652 default:
1653 pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
1654 payload[0]);
1655 break;
1656 }
1657 return 0;
1658 }
1659
1660 switch (data->opcode) {
1661 case ADM_CMDRSP_DEVICE_OPEN_V5:
1662 case ADM_CMDRSP_DEVICE_OPEN_V6: {
1663 struct adm_cmd_rsp_device_open_v5 *open =
1664 (struct adm_cmd_rsp_device_open_v5 *)data->payload;
1665
1666 if (open->copp_id == INVALID_COPP_ID) {
1667 pr_err("%s: invalid coppid rxed %d\n",
1668 __func__, open->copp_id);
1669 atomic_set(&this_adm.copp.stat[port_idx]
1670 [copp_idx], ADSP_EBADPARAM);
1671 wake_up(
1672 &this_adm.copp.wait[port_idx][copp_idx]);
1673 break;
1674 }
1675 atomic_set(&this_adm.copp.stat
1676 [port_idx][copp_idx], payload[0]);
1677 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
1678 open->copp_id);
1679 pr_debug("%s: coppid rxed=%d\n", __func__,
1680 open->copp_id);
1681 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1682 }
1683 break;
1684 case ADM_CMDRSP_GET_PP_PARAMS_V5:
1685 pr_debug("%s: ADM_CMDRSP_GET_PP_PARAMS_V5\n", __func__);
1686 if (payload[0] != 0)
1687 pr_err("%s: ADM_CMDRSP_GET_PP_PARAMS_V5 returned error = 0x%x\n",
1688 __func__, payload[0]);
1689 if (client_id == ADM_CLIENT_ID_SOURCE_TRACKING)
1690 this_adm.sourceTrackingData.apr_cmd_status =
1691 payload[0];
1692 else if (rtac_make_adm_callback(payload,
1693 data->payload_size))
1694 break;
1695
1696 idx = ADM_GET_PARAMETER_LENGTH * copp_idx;
1697 if ((payload[0] == 0) && (data->payload_size >
1698 (4 * sizeof(*payload))) &&
1699 (data->payload_size - 4 >=
1700 payload[3]) &&
1701 (ARRAY_SIZE(adm_get_parameters) >
1702 idx) &&
1703 (ARRAY_SIZE(adm_get_parameters)-idx-1 >=
1704 payload[3])) {
1705 adm_get_parameters[idx] = payload[3] /
1706 sizeof(uint32_t);
1707 /*
1708 * payload[3] is param_size which is
1709 * expressed in number of bytes
1710 */
1711 pr_debug("%s: GET_PP PARAM:received parameter length: 0x%x\n",
1712 __func__, adm_get_parameters[idx]);
1713 /* storing param size then params */
1714 for (i = 0; i < payload[3] /
1715 sizeof(uint32_t); i++)
1716 adm_get_parameters[idx+1+i] =
1717 payload[4+i];
1718 } else if (payload[0] == 0) {
1719 adm_get_parameters[idx] = -1;
1720 pr_err("%s: Out of band case, setting size to %d\n",
1721 __func__, adm_get_parameters[idx]);
1722 } else {
1723 adm_get_parameters[idx] = -1;
1724 pr_err("%s: GET_PP_PARAMS failed, setting size to %d\n",
1725 __func__, adm_get_parameters[idx]);
1726 }
1727 atomic_set(&this_adm.copp.stat
1728 [port_idx][copp_idx], payload[0]);
1729 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1730 break;
1731 case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST:
1732 pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n",
1733 __func__);
1734 if (payload[0] != 0) {
1735 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST",
1736 __func__);
1737 pr_err(":err = 0x%x\n", payload[0]);
1738 } else if (payload[1] >
1739 ((ADM_GET_TOPO_MODULE_LIST_LENGTH /
1740 sizeof(uint32_t)) - 1)) {
1741 pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST",
1742 __func__);
1743 pr_err(":size = %d\n", payload[1]);
1744 } else {
1745 idx = ADM_GET_TOPO_MODULE_LIST_LENGTH *
1746 copp_idx;
1747 pr_debug("%s:Num modules payload[1] %d\n",
1748 __func__, payload[1]);
1749 adm_module_topo_list[idx] = payload[1];
1750 for (i = 1; i <= payload[1]; i++) {
1751 adm_module_topo_list[idx+i] =
1752 payload[1+i];
1753 pr_debug("%s:payload[%d] = %x\n",
1754 __func__, (i+1), payload[1+i]);
1755 }
1756 }
1757 atomic_set(&this_adm.copp.stat
1758 [port_idx][copp_idx], payload[0]);
1759 wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
1760 break;
1761 case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
1762 pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
1763 __func__);
1764 atomic_set(&this_adm.mem_map_handles[
1765 atomic_read(&this_adm.mem_map_index)],
1766 *payload);
1767 atomic_set(&this_adm.adm_stat, 0);
1768 wake_up(&this_adm.adm_wait);
1769 break;
1770 default:
1771 pr_err("%s: Unknown cmd:0x%x\n", __func__,
1772 data->opcode);
1773 break;
1774 }
1775 }
1776 return 0;
1777}
1778
1779static int adm_memory_map_regions(phys_addr_t *buf_add, uint32_t mempool_id,
1780 uint32_t *bufsz, uint32_t bufcnt)
1781{
1782 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
1783 struct avs_shared_map_region_payload *mregions = NULL;
1784 void *mmap_region_cmd = NULL;
1785 void *payload = NULL;
1786 int ret = 0;
1787 int i = 0;
1788 int cmd_size = 0;
1789
1790 pr_debug("%s:\n", __func__);
1791 if (this_adm.apr == NULL) {
1792 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
1793 0xFFFFFFFF, &this_adm);
1794 if (this_adm.apr == NULL) {
1795 pr_err("%s: Unable to register ADM\n", __func__);
1796 ret = -ENODEV;
1797 return ret;
1798 }
1799 rtac_set_adm_handle(this_adm.apr);
1800 }
1801
1802 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
1803 + sizeof(struct avs_shared_map_region_payload)
1804 * bufcnt;
1805
1806 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1807 if (!mmap_region_cmd)
1808 return -ENOMEM;
1809
1810 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)mmap_region_cmd;
1811 mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1812 APR_HDR_LEN(APR_HDR_SIZE),
1813 APR_PKT_VER);
1814 mmap_regions->hdr.pkt_size = cmd_size;
1815 mmap_regions->hdr.src_port = 0;
1816
1817 mmap_regions->hdr.dest_port = 0;
1818 mmap_regions->hdr.token = 0;
1819 mmap_regions->hdr.opcode = ADM_CMD_SHARED_MEM_MAP_REGIONS;
1820 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL & 0x00ff;
1821 mmap_regions->num_regions = bufcnt & 0x00ff;
1822 mmap_regions->property_flag = 0x00;
1823
1824 pr_debug("%s: map_regions->num_regions = %d\n", __func__,
1825 mmap_regions->num_regions);
1826 payload = ((u8 *) mmap_region_cmd +
1827 sizeof(struct avs_cmd_shared_mem_map_regions));
1828 mregions = (struct avs_shared_map_region_payload *)payload;
1829
1830 for (i = 0; i < bufcnt; i++) {
1831 mregions->shm_addr_lsw = lower_32_bits(buf_add[i]);
1832 mregions->shm_addr_msw =
1833 msm_audio_populate_upper_32_bits(buf_add[i]);
1834 mregions->mem_size_bytes = bufsz[i];
1835 ++mregions;
1836 }
1837
1838 atomic_set(&this_adm.adm_stat, -1);
1839 ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
1840 if (ret < 0) {
1841 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1842 mmap_regions->hdr.opcode, ret);
1843 ret = -EINVAL;
1844 goto fail_cmd;
1845 }
1846
1847 ret = wait_event_timeout(this_adm.adm_wait,
1848 atomic_read(&this_adm.adm_stat) >= 0,
1849 5 * HZ);
1850 if (!ret) {
1851 pr_err("%s: timeout. waited for memory_map\n", __func__);
1852 ret = -EINVAL;
1853 goto fail_cmd;
1854 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1855 pr_err("%s: DSP returned error[%s]\n",
1856 __func__, adsp_err_get_err_str(
1857 atomic_read(&this_adm.adm_stat)));
1858 ret = adsp_err_get_lnx_err_code(
1859 atomic_read(&this_adm.adm_stat));
1860 goto fail_cmd;
1861 }
1862fail_cmd:
1863 kfree(mmap_region_cmd);
1864 return ret;
1865}
1866
1867static int adm_memory_unmap_regions(void)
1868{
1869 struct avs_cmd_shared_mem_unmap_regions unmap_regions;
1870 int ret = 0;
1871
1872 pr_debug("%s:\n", __func__);
1873 if (this_adm.apr == NULL) {
1874 pr_err("%s: APR handle NULL\n", __func__);
1875 return -EINVAL;
1876 }
1877
1878 unmap_regions.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1879 APR_HDR_LEN(APR_HDR_SIZE),
1880 APR_PKT_VER);
1881 unmap_regions.hdr.pkt_size = sizeof(unmap_regions);
1882 unmap_regions.hdr.src_port = 0;
1883 unmap_regions.hdr.dest_port = 0;
1884 unmap_regions.hdr.token = 0;
1885 unmap_regions.hdr.opcode = ADM_CMD_SHARED_MEM_UNMAP_REGIONS;
1886 unmap_regions.mem_map_handle = atomic_read(&this_adm.
1887 mem_map_handles[atomic_read(&this_adm.mem_map_index)]);
1888 atomic_set(&this_adm.adm_stat, -1);
1889 ret = apr_send_pkt(this_adm.apr, (uint32_t *) &unmap_regions);
1890 if (ret < 0) {
1891 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1892 unmap_regions.hdr.opcode, ret);
1893 ret = -EINVAL;
1894 goto fail_cmd;
1895 }
1896
1897 ret = wait_event_timeout(this_adm.adm_wait,
1898 atomic_read(&this_adm.adm_stat) >= 0,
1899 5 * HZ);
1900 if (!ret) {
1901 pr_err("%s: timeout. waited for memory_unmap\n",
1902 __func__);
1903 ret = -EINVAL;
1904 goto fail_cmd;
1905 } else if (atomic_read(&this_adm.adm_stat) > 0) {
1906 pr_err("%s: DSP returned error[%s]\n",
1907 __func__, adsp_err_get_err_str(
1908 atomic_read(&this_adm.adm_stat)));
1909 ret = adsp_err_get_lnx_err_code(
1910 atomic_read(&this_adm.adm_stat));
1911 goto fail_cmd;
1912 } else {
1913 pr_debug("%s: Unmap handle 0x%x succeeded\n", __func__,
1914 unmap_regions.mem_map_handle);
1915 }
1916fail_cmd:
1917 return ret;
1918}
1919
1920static int remap_cal_data(struct cal_block_data *cal_block, int cal_index)
1921{
1922 int ret = 0;
1923
Banajit Goswami08bb7362017-11-03 22:48:23 -07001924 if (cal_block->map_data.dma_buf == NULL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301925 pr_err("%s: No ION allocation for cal index %d!\n",
1926 __func__, cal_index);
1927 ret = -EINVAL;
1928 goto done;
1929 }
1930
1931 if ((cal_block->map_data.map_size > 0) &&
1932 (cal_block->map_data.q6map_handle == 0)) {
1933 atomic_set(&this_adm.mem_map_index, cal_index);
1934 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
1935 (uint32_t *)&cal_block->map_data.map_size, 1);
1936 if (ret < 0) {
1937 pr_err("%s: ADM mmap did not work! size = %zd ret %d\n",
1938 __func__,
1939 cal_block->map_data.map_size, ret);
1940 pr_debug("%s: ADM mmap did not work! addr = 0x%pK, size = %zd ret %d\n",
1941 __func__,
1942 &cal_block->cal_data.paddr,
1943 cal_block->map_data.map_size, ret);
1944 goto done;
1945 }
1946 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
1947 mem_map_handles[cal_index]);
1948 }
1949done:
1950 return ret;
1951}
1952
1953static void send_adm_custom_topology(void)
1954{
1955 struct cal_block_data *cal_block = NULL;
1956 struct cmd_set_topologies adm_top;
1957 int cal_index = ADM_CUSTOM_TOP_CAL;
1958 int result;
1959
1960 if (this_adm.cal_data[cal_index] == NULL)
1961 goto done;
1962
1963 mutex_lock(&this_adm.cal_data[cal_index]->lock);
1964 if (!this_adm.set_custom_topology)
1965 goto unlock;
1966 this_adm.set_custom_topology = 0;
1967
1968 cal_block = cal_utils_get_only_cal_block(this_adm.cal_data[cal_index]);
1969 if (cal_block == NULL)
1970 goto unlock;
1971
1972 pr_debug("%s: Sending cal_index %d\n", __func__, cal_index);
1973
1974 result = remap_cal_data(cal_block, cal_index);
1975 if (result) {
1976 pr_err("%s: Remap_cal_data failed for cal %d!\n",
1977 __func__, cal_index);
1978 goto unlock;
1979 }
1980 atomic_set(&this_adm.mem_map_index, cal_index);
1981 atomic_set(&this_adm.mem_map_handles[cal_index],
1982 cal_block->map_data.q6map_handle);
1983
1984 if (cal_block->cal_data.size == 0) {
1985 pr_debug("%s: No ADM cal to send\n", __func__);
1986 goto unlock;
1987 }
1988
1989 adm_top.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1990 APR_HDR_LEN(20), APR_PKT_VER);
1991 adm_top.hdr.pkt_size = sizeof(adm_top);
1992 adm_top.hdr.src_svc = APR_SVC_ADM;
1993 adm_top.hdr.src_domain = APR_DOMAIN_APPS;
1994 adm_top.hdr.src_port = 0;
1995 adm_top.hdr.dest_svc = APR_SVC_ADM;
1996 adm_top.hdr.dest_domain = APR_DOMAIN_ADSP;
1997 adm_top.hdr.dest_port = 0;
1998 adm_top.hdr.token = 0;
1999 adm_top.hdr.opcode = ADM_CMD_ADD_TOPOLOGIES;
2000 adm_top.payload_addr_lsw = lower_32_bits(cal_block->cal_data.paddr);
2001 adm_top.payload_addr_msw = msm_audio_populate_upper_32_bits(
2002 cal_block->cal_data.paddr);
2003 adm_top.mem_map_handle = cal_block->map_data.q6map_handle;
2004 adm_top.payload_size = cal_block->cal_data.size;
2005
2006 atomic_set(&this_adm.adm_stat, -1);
2007 pr_debug("%s: Sending ADM_CMD_ADD_TOPOLOGIES payload = 0x%pK, size = %d\n",
2008 __func__, &cal_block->cal_data.paddr,
2009 adm_top.payload_size);
2010 result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_top);
2011 if (result < 0) {
2012 pr_err("%s: Set topologies failed payload size = %zd result %d\n",
2013 __func__, cal_block->cal_data.size, result);
2014 goto unlock;
2015 }
2016 /* Wait for the callback */
2017 result = wait_event_timeout(this_adm.adm_wait,
2018 atomic_read(&this_adm.adm_stat) >= 0,
2019 msecs_to_jiffies(TIMEOUT_MS));
2020 if (!result) {
2021 pr_err("%s: Set topologies timed out payload size = %zd\n",
2022 __func__, cal_block->cal_data.size);
2023 goto unlock;
2024 } else if (atomic_read(&this_adm.adm_stat) > 0) {
2025 pr_err("%s: DSP returned error[%s]\n",
2026 __func__, adsp_err_get_err_str(
2027 atomic_read(&this_adm.adm_stat)));
2028 result = adsp_err_get_lnx_err_code(
2029 atomic_read(&this_adm.adm_stat));
2030 goto unlock;
2031 }
2032unlock:
2033 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2034done:
2035 return;
2036}
2037
2038static int send_adm_cal_block(int port_id, int copp_idx,
2039 struct cal_block_data *cal_block, int perf_mode,
2040 int app_type, int acdb_id, int sample_rate)
2041{
2042 s32 result = 0;
2043 struct adm_cmd_set_pp_params_v5 adm_params;
2044 int port_idx;
2045
2046 pr_debug("%s: Port id 0x%x sample_rate %d ,\n", __func__,
2047 port_id, sample_rate);
2048 port_id = afe_convert_virtual_to_portid(port_id);
2049 port_idx = adm_validate_and_get_port_index(port_id);
2050 if (port_idx < 0) {
2051 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2052 return -EINVAL;
2053 }
2054 if (!cal_block) {
2055 pr_debug("%s: No ADM cal to send for port_id = 0x%x!\n",
2056 __func__, port_id);
2057 result = -EINVAL;
2058 goto done;
2059 }
2060 if (cal_block->cal_data.size <= 0) {
2061 pr_debug("%s: No ADM cal send for port_id = 0x%x!\n",
2062 __func__, port_id);
2063 result = -EINVAL;
2064 goto done;
2065 }
2066
2067 if (perf_mode == LEGACY_PCM_MODE &&
2068 ((atomic_read(&this_adm.copp.topology[port_idx][copp_idx])) ==
2069 DS2_ADM_COPP_TOPOLOGY_ID)) {
2070 pr_err("%s: perf_mode %d, topology 0x%x\n", __func__, perf_mode,
2071 atomic_read(
2072 &this_adm.copp.topology[port_idx][copp_idx]));
2073 goto done;
2074 }
2075
2076 adm_params.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2077 APR_HDR_LEN(20), APR_PKT_VER);
2078 adm_params.hdr.pkt_size = sizeof(adm_params);
2079 adm_params.hdr.src_svc = APR_SVC_ADM;
2080 adm_params.hdr.src_domain = APR_DOMAIN_APPS;
2081 adm_params.hdr.src_port = port_id;
2082 adm_params.hdr.dest_svc = APR_SVC_ADM;
2083 adm_params.hdr.dest_domain = APR_DOMAIN_ADSP;
2084
2085 adm_params.hdr.token = port_idx << 16 | copp_idx;
2086 adm_params.hdr.dest_port =
2087 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
2088 adm_params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
2089 adm_params.payload_addr_lsw = lower_32_bits(cal_block->cal_data.paddr);
2090 adm_params.payload_addr_msw = msm_audio_populate_upper_32_bits(
2091 cal_block->cal_data.paddr);
2092 adm_params.mem_map_handle = cal_block->map_data.q6map_handle;
2093 adm_params.payload_size = cal_block->cal_data.size;
2094
2095 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
2096 pr_debug("%s: Sending SET_PARAMS payload = 0x%pK, size = %d\n",
2097 __func__, &cal_block->cal_data.paddr,
2098 adm_params.payload_size);
2099 result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_params);
2100 if (result < 0) {
2101 pr_err("%s: Set params failed port 0x%x result %d\n",
2102 __func__, port_id, result);
2103 pr_debug("%s: Set params failed port = 0x%x payload = 0x%pK result %d\n",
2104 __func__, port_id, &cal_block->cal_data.paddr, result);
2105 result = -EINVAL;
2106 goto done;
2107 }
2108 /* Wait for the callback */
2109 result = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
2110 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
2111 msecs_to_jiffies(TIMEOUT_MS));
2112 if (!result) {
2113 pr_err("%s: Set params timed out port = 0x%x\n",
2114 __func__, port_id);
2115 pr_debug("%s: Set params timed out port = 0x%x, payload = 0x%pK\n",
2116 __func__, port_id, &cal_block->cal_data.paddr);
2117 result = -EINVAL;
2118 goto done;
2119 } else if (atomic_read(&this_adm.copp.stat
2120 [port_idx][copp_idx]) > 0) {
2121 pr_err("%s: DSP returned error[%s]\n",
2122 __func__, adsp_err_get_err_str(
2123 atomic_read(&this_adm.copp.stat
2124 [port_idx][copp_idx])));
2125 result = adsp_err_get_lnx_err_code(
2126 atomic_read(&this_adm.copp.stat
2127 [port_idx][copp_idx]));
2128 goto done;
2129 }
2130
2131done:
2132 return result;
2133}
2134
2135static struct cal_block_data *adm_find_cal_by_path(int cal_index, int path)
2136{
2137 struct list_head *ptr, *next;
2138 struct cal_block_data *cal_block = NULL;
2139 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2140 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2141
2142 pr_debug("%s:\n", __func__);
2143
2144 list_for_each_safe(ptr, next,
2145 &this_adm.cal_data[cal_index]->cal_blocks) {
2146
2147 cal_block = list_entry(ptr,
2148 struct cal_block_data, list);
2149
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302150 if (cal_index == ADM_AUDPROC_CAL ||
2151 cal_index == ADM_LSM_AUDPROC_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302152 audproc_cal_info = cal_block->cal_info;
2153 if ((audproc_cal_info->path == path) &&
2154 (cal_block->cal_data.size > 0))
2155 return cal_block;
2156 } else if (cal_index == ADM_AUDVOL_CAL) {
2157 audvol_cal_info = cal_block->cal_info;
2158 if ((audvol_cal_info->path == path) &&
2159 (cal_block->cal_data.size > 0))
2160 return cal_block;
2161 }
2162 }
2163 pr_debug("%s: Can't find ADM cal for cal_index %d, path %d\n",
2164 __func__, cal_index, path);
2165 return NULL;
2166}
2167
2168static struct cal_block_data *adm_find_cal_by_app_type(int cal_index, int path,
2169 int app_type)
2170{
2171 struct list_head *ptr, *next;
2172 struct cal_block_data *cal_block = NULL;
2173 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2174 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2175
2176 pr_debug("%s\n", __func__);
2177
2178 list_for_each_safe(ptr, next,
2179 &this_adm.cal_data[cal_index]->cal_blocks) {
2180
2181 cal_block = list_entry(ptr,
2182 struct cal_block_data, list);
2183
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302184 if (cal_index == ADM_AUDPROC_CAL ||
2185 cal_index == ADM_LSM_AUDPROC_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302186 audproc_cal_info = cal_block->cal_info;
2187 if ((audproc_cal_info->path == path) &&
2188 (audproc_cal_info->app_type == app_type) &&
2189 (cal_block->cal_data.size > 0))
2190 return cal_block;
2191 } else if (cal_index == ADM_AUDVOL_CAL) {
2192 audvol_cal_info = cal_block->cal_info;
2193 if ((audvol_cal_info->path == path) &&
2194 (audvol_cal_info->app_type == app_type) &&
2195 (cal_block->cal_data.size > 0))
2196 return cal_block;
2197 }
2198 }
2199 pr_debug("%s: Can't find ADM cali for cal_index %d, path %d, app %d, defaulting to search by path\n",
2200 __func__, cal_index, path, app_type);
2201 return adm_find_cal_by_path(cal_index, path);
2202}
2203
2204
2205static struct cal_block_data *adm_find_cal(int cal_index, int path,
2206 int app_type, int acdb_id,
2207 int sample_rate)
2208{
2209 struct list_head *ptr, *next;
2210 struct cal_block_data *cal_block = NULL;
2211 struct audio_cal_info_audproc *audproc_cal_info = NULL;
2212 struct audio_cal_info_audvol *audvol_cal_info = NULL;
2213
2214 pr_debug("%s:\n", __func__);
2215
2216 list_for_each_safe(ptr, next,
2217 &this_adm.cal_data[cal_index]->cal_blocks) {
2218
2219 cal_block = list_entry(ptr,
2220 struct cal_block_data, list);
2221
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302222 if (cal_index == ADM_AUDPROC_CAL ||
2223 cal_index == ADM_LSM_AUDPROC_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302224 audproc_cal_info = cal_block->cal_info;
2225 if ((audproc_cal_info->path == path) &&
2226 (audproc_cal_info->app_type == app_type) &&
2227 (audproc_cal_info->acdb_id == acdb_id) &&
2228 (audproc_cal_info->sample_rate == sample_rate) &&
2229 (cal_block->cal_data.size > 0))
2230 return cal_block;
2231 } else if (cal_index == ADM_AUDVOL_CAL) {
2232 audvol_cal_info = cal_block->cal_info;
2233 if ((audvol_cal_info->path == path) &&
2234 (audvol_cal_info->app_type == app_type) &&
2235 (audvol_cal_info->acdb_id == acdb_id) &&
2236 (cal_block->cal_data.size > 0))
2237 return cal_block;
2238 }
2239 }
2240 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",
2241 __func__, cal_index, path, app_type, acdb_id, sample_rate);
2242 return adm_find_cal_by_app_type(cal_index, path, app_type);
2243}
2244
2245static int adm_remap_and_send_cal_block(int cal_index, int port_id,
2246 int copp_idx, struct cal_block_data *cal_block, int perf_mode,
2247 int app_type, int acdb_id, int sample_rate)
2248{
2249 int ret = 0;
2250
2251 pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
2252 ret = remap_cal_data(cal_block, cal_index);
2253 if (ret) {
2254 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2255 __func__, cal_index);
2256 goto done;
2257 }
2258 ret = send_adm_cal_block(port_id, copp_idx, cal_block, perf_mode,
2259 app_type, acdb_id, sample_rate);
2260 if (ret < 0)
2261 pr_debug("%s: No cal sent for cal_index %d, port_id = 0x%x! ret %d sample_rate %d\n",
2262 __func__, cal_index, port_id, ret, sample_rate);
2263done:
2264 return ret;
2265}
2266
2267static void send_adm_cal_type(int cal_index, int path, int port_id,
2268 int copp_idx, int perf_mode, int app_type,
2269 int acdb_id, int sample_rate)
2270{
2271 struct cal_block_data *cal_block = NULL;
2272 int ret;
2273
2274 pr_debug("%s: cal index %d\n", __func__, cal_index);
2275
2276 if (this_adm.cal_data[cal_index] == NULL) {
2277 pr_debug("%s: cal_index %d not allocated!\n",
2278 __func__, cal_index);
2279 goto done;
2280 }
2281
2282 mutex_lock(&this_adm.cal_data[cal_index]->lock);
2283 cal_block = adm_find_cal(cal_index, path, app_type, acdb_id,
2284 sample_rate);
2285 if (cal_block == NULL)
2286 goto unlock;
2287
2288 ret = adm_remap_and_send_cal_block(cal_index, port_id, copp_idx,
2289 cal_block, perf_mode, app_type, acdb_id, sample_rate);
2290unlock:
2291 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
2292done:
2293 return;
2294}
2295
2296static int get_cal_path(int path)
2297{
2298 if (path == 0x1)
2299 return RX_DEVICE;
2300 else
2301 return TX_DEVICE;
2302}
2303
2304static void send_adm_cal(int port_id, int copp_idx, int path, int perf_mode,
Aditya Bavanari5106b562018-01-08 13:16:32 +05302305 int app_type, int acdb_id, int sample_rate,
2306 int passthr_mode)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302307{
2308 pr_debug("%s: port id 0x%x copp_idx %d\n", __func__, port_id, copp_idx);
2309
Aditya Bavanari5106b562018-01-08 13:16:32 +05302310 if (passthr_mode != LISTEN)
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05302311 send_adm_cal_type(ADM_AUDPROC_CAL, path, port_id, copp_idx,
2312 perf_mode, app_type, acdb_id, sample_rate);
2313 else
2314 send_adm_cal_type(ADM_LSM_AUDPROC_CAL, path, port_id, copp_idx,
2315 perf_mode, app_type, acdb_id, sample_rate);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302316 send_adm_cal_type(ADM_AUDVOL_CAL, path, port_id, copp_idx, perf_mode,
2317 app_type, acdb_id, sample_rate);
2318}
2319
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302320/**
2321 * adm_connect_afe_port -
2322 * command to send ADM connect AFE port
2323 *
2324 * @mode: value of mode for ADM connect AFE
2325 * @session_id: session active to connect
2326 * @port_id: Port ID number
2327 *
2328 * Returns 0 on success or error on failure
2329 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302330int adm_connect_afe_port(int mode, int session_id, int port_id)
2331{
2332 struct adm_cmd_connect_afe_port_v5 cmd;
2333 int ret = 0;
2334 int port_idx, copp_idx = 0;
2335
2336 pr_debug("%s: port_id: 0x%x session id:%d mode:%d\n", __func__,
2337 port_id, session_id, mode);
2338
2339 port_id = afe_convert_virtual_to_portid(port_id);
2340 port_idx = adm_validate_and_get_port_index(port_id);
2341 if (port_idx < 0) {
2342 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2343 return -EINVAL;
2344 }
2345
2346 if (this_adm.apr == NULL) {
2347 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
2348 0xFFFFFFFF, &this_adm);
2349 if (this_adm.apr == NULL) {
2350 pr_err("%s: Unable to register ADM\n", __func__);
2351 ret = -ENODEV;
2352 return ret;
2353 }
2354 rtac_set_adm_handle(this_adm.apr);
2355 }
2356 pr_debug("%s: Port ID 0x%x, index %d\n", __func__, port_id, port_idx);
2357
2358 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2359 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2360 cmd.hdr.pkt_size = sizeof(cmd);
2361 cmd.hdr.src_svc = APR_SVC_ADM;
2362 cmd.hdr.src_domain = APR_DOMAIN_APPS;
2363 cmd.hdr.src_port = port_id;
2364 cmd.hdr.dest_svc = APR_SVC_ADM;
2365 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
2366 cmd.hdr.dest_port = 0; /* Ignored */
2367 cmd.hdr.token = port_idx << 16 | copp_idx;
2368 cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V5;
2369
2370 cmd.mode = mode;
2371 cmd.session_id = session_id;
2372 cmd.afe_port_id = port_id;
2373
2374 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
2375 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
2376 if (ret < 0) {
2377 pr_err("%s: ADM enable for port_id: 0x%x failed ret %d\n",
2378 __func__, port_id, ret);
2379 ret = -EINVAL;
2380 goto fail_cmd;
2381 }
2382 /* Wait for the callback with copp id */
2383 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
2384 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
2385 msecs_to_jiffies(TIMEOUT_MS));
2386 if (!ret) {
2387 pr_err("%s: ADM connect timedout for port_id: 0x%x\n",
2388 __func__, port_id);
2389 ret = -EINVAL;
2390 goto fail_cmd;
2391 } else if (atomic_read(&this_adm.copp.stat
2392 [port_idx][copp_idx]) > 0) {
2393 pr_err("%s: DSP returned error[%s]\n",
2394 __func__, adsp_err_get_err_str(
2395 atomic_read(&this_adm.copp.stat
2396 [port_idx][copp_idx])));
2397 ret = adsp_err_get_lnx_err_code(
2398 atomic_read(&this_adm.copp.stat
2399 [port_idx][copp_idx]));
2400 goto fail_cmd;
2401 }
2402 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
2403 return 0;
2404
2405fail_cmd:
2406
2407 return ret;
2408}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302409EXPORT_SYMBOL(adm_connect_afe_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302410
2411int adm_arrange_mch_map(struct adm_cmd_device_open_v5 *open, int path,
2412 int channel_mode)
2413{
2414 int rc = 0, idx;
2415
2416 memset(open->dev_channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
2417 switch (path) {
2418 case ADM_PATH_PLAYBACK:
2419 idx = ADM_MCH_MAP_IDX_PLAYBACK;
2420 break;
2421 case ADM_PATH_LIVE_REC:
2422 case ADM_PATH_NONLIVE_REC:
2423 idx = ADM_MCH_MAP_IDX_REC;
2424 break;
2425 default:
2426 goto non_mch_path;
2427 };
2428 if ((open->dev_num_channel > 2) && multi_ch_maps[idx].set_channel_map) {
2429 memcpy(open->dev_channel_mapping,
2430 multi_ch_maps[idx].channel_mapping,
2431 PCM_FORMAT_MAX_NUM_CHANNEL);
2432 } else {
2433 if (channel_mode == 1) {
2434 open->dev_channel_mapping[0] = PCM_CHANNEL_FC;
2435 } else if (channel_mode == 2) {
2436 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2437 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2438 } else if (channel_mode == 3) {
2439 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2440 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2441 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2442 } else if (channel_mode == 4) {
2443 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2444 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2445 open->dev_channel_mapping[2] = PCM_CHANNEL_LS;
2446 open->dev_channel_mapping[3] = PCM_CHANNEL_RS;
2447 } else if (channel_mode == 5) {
2448 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2449 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2450 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2451 open->dev_channel_mapping[3] = PCM_CHANNEL_LS;
2452 open->dev_channel_mapping[4] = PCM_CHANNEL_RS;
2453 } else if (channel_mode == 6) {
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_LFE;
2457 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2458 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2459 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2460 } else if (channel_mode == 7) {
2461 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2462 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2463 open->dev_channel_mapping[2] = PCM_CHANNEL_FC;
2464 open->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
2465 open->dev_channel_mapping[4] = PCM_CHANNEL_LB;
2466 open->dev_channel_mapping[5] = PCM_CHANNEL_RB;
2467 open->dev_channel_mapping[6] = PCM_CHANNEL_CS;
2468 } else if (channel_mode == 8) {
2469 open->dev_channel_mapping[0] = PCM_CHANNEL_FL;
2470 open->dev_channel_mapping[1] = PCM_CHANNEL_FR;
2471 open->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
2472 open->dev_channel_mapping[3] = PCM_CHANNEL_FC;
2473 open->dev_channel_mapping[4] = PCM_CHANNEL_LS;
2474 open->dev_channel_mapping[5] = PCM_CHANNEL_RS;
2475 open->dev_channel_mapping[6] = PCM_CHANNEL_LB;
2476 open->dev_channel_mapping[7] = PCM_CHANNEL_RB;
2477 } else {
2478 pr_err("%s: invalid num_chan %d\n", __func__,
2479 channel_mode);
2480 rc = -EINVAL;
2481 goto inval_ch_mod;
2482 }
2483 }
2484
2485non_mch_path:
2486inval_ch_mod:
2487 return rc;
2488}
2489
2490int adm_arrange_mch_ep2_map(struct adm_cmd_device_open_v6 *open_v6,
2491 int channel_mode)
2492{
2493 int rc = 0;
2494
2495 memset(open_v6->dev_channel_mapping_eid2, 0,
2496 PCM_FORMAT_MAX_NUM_CHANNEL);
2497
2498 if (channel_mode == 1) {
2499 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FC;
2500 } else if (channel_mode == 2) {
2501 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2502 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2503 } else if (channel_mode == 3) {
2504 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2505 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2506 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2507 } else if (channel_mode == 4) {
2508 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2509 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2510 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LS;
2511 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_RS;
2512 } else if (channel_mode == 5) {
2513 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2514 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2515 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
2516 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_LS;
2517 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_RS;
2518 } else if (channel_mode == 6) {
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_LFE;
2522 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2523 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2524 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2525 } else if (channel_mode == 8) {
2526 open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
2527 open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
2528 open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
2529 open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
2530 open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
2531 open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
2532 open_v6->dev_channel_mapping_eid2[6] = PCM_CHANNEL_LB;
2533 open_v6->dev_channel_mapping_eid2[7] = PCM_CHANNEL_RB;
2534 } else {
2535 pr_err("%s: invalid num_chan %d\n", __func__,
2536 channel_mode);
2537 rc = -EINVAL;
2538 }
2539
2540 return rc;
2541}
2542
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302543/**
2544 * adm_open -
2545 * command to send ADM open
2546 *
2547 * @port_id: port id number
2548 * @path: direction or ADM path type
2549 * @rate: sample rate of session
2550 * @channel_mode: number of channels set
2551 * @topology: topology active for this session
2552 * @perf_mode: performance mode like LL/ULL/..
2553 * @bit_width: bit width to set for copp
2554 * @app_type: App type used for this session
2555 * @acdb_id: ACDB ID of this device
2556 *
2557 * Returns 0 on success or error on failure
2558 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302559int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
2560 int perf_mode, uint16_t bit_width, int app_type, int acdb_id)
2561{
2562 struct adm_cmd_device_open_v5 open;
2563 struct adm_cmd_device_open_v6 open_v6;
2564 int ret = 0;
Asish Bhattacharya34504582017-08-08 12:55:01 +05302565 int port_idx, flags;
2566 int copp_idx = -1;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302567 int tmp_port = q6audio_get_port_id(port_id);
2568
2569 pr_debug("%s:port %#x path:%d rate:%d mode:%d perf_mode:%d,topo_id %d\n",
2570 __func__, port_id, path, rate, channel_mode, perf_mode,
2571 topology);
2572
2573 port_id = q6audio_convert_virtual_to_portid(port_id);
2574 port_idx = adm_validate_and_get_port_index(port_id);
2575 if (port_idx < 0) {
2576 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
2577 return -EINVAL;
2578 }
2579
2580 if (this_adm.apr == NULL) {
2581 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
2582 0xFFFFFFFF, &this_adm);
2583 if (this_adm.apr == NULL) {
2584 pr_err("%s: Unable to register ADM\n", __func__);
2585 return -ENODEV;
2586 }
2587 rtac_set_adm_handle(this_adm.apr);
2588 }
2589
2590 if (perf_mode == ULL_POST_PROCESSING_PCM_MODE) {
2591 flags = ADM_ULL_POST_PROCESSING_DEVICE_SESSION;
2592 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
2593 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
2594 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
2595 topology = DEFAULT_COPP_TOPOLOGY;
2596 } else if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
2597 flags = ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
2598 topology = NULL_COPP_TOPOLOGY;
2599 rate = ULL_SUPPORTED_SAMPLE_RATE;
2600 bit_width = ULL_SUPPORTED_BITS_PER_SAMPLE;
2601 } else if (perf_mode == LOW_LATENCY_PCM_MODE) {
2602 flags = ADM_LOW_LATENCY_DEVICE_SESSION;
2603 if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) ||
2604 (topology == DS2_ADM_COPP_TOPOLOGY_ID) ||
2605 (topology == SRS_TRUMEDIA_TOPOLOGY_ID))
2606 topology = DEFAULT_COPP_TOPOLOGY;
2607 } else {
2608 if ((path == ADM_PATH_COMPRESSED_RX) ||
2609 (path == ADM_PATH_COMPRESSED_TX))
2610 flags = 0;
2611 else
2612 flags = ADM_LEGACY_DEVICE_SESSION;
2613 }
2614
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05302615 if ((topology == VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY) ||
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302616 (topology == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY) ||
2617 (topology == VPM_TX_DM_RFECNS_COPP_TOPOLOGY))
2618 rate = 16000;
2619
Asish Bhattacharya34504582017-08-08 12:55:01 +05302620 /*
2621 * Routing driver reuses the same adm for streams with the same
2622 * app_type, sample_rate etc.
2623 * This isn't allowed for ULL streams as per the DSP interface
2624 */
2625 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE)
2626 copp_idx = adm_get_idx_if_copp_exists(port_idx, topology,
2627 perf_mode,
2628 rate, bit_width,
2629 app_type);
2630
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302631 if (copp_idx < 0) {
2632 copp_idx = adm_get_next_available_copp(port_idx);
2633 if (copp_idx >= MAX_COPPS_PER_PORT) {
2634 pr_err("%s: exceeded copp id %d\n",
2635 __func__, copp_idx);
2636 return -EINVAL;
2637 }
2638 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
2639 atomic_set(&this_adm.copp.topology[port_idx][copp_idx],
2640 topology);
2641 atomic_set(&this_adm.copp.mode[port_idx][copp_idx],
2642 perf_mode);
2643 atomic_set(&this_adm.copp.rate[port_idx][copp_idx],
2644 rate);
2645 atomic_set(&this_adm.copp.channels[port_idx][copp_idx],
2646 channel_mode);
2647 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx],
2648 bit_width);
2649 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx],
2650 app_type);
2651 atomic_set(&this_adm.copp.acdb_id[port_idx][copp_idx],
2652 acdb_id);
2653 set_bit(ADM_STATUS_CALIBRATION_REQUIRED,
2654 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
2655 if ((path != ADM_PATH_COMPRESSED_RX) &&
2656 (path != ADM_PATH_COMPRESSED_TX))
2657 send_adm_custom_topology();
2658 }
2659
2660 if (this_adm.copp.adm_delay[port_idx][copp_idx] &&
2661 perf_mode == LEGACY_PCM_MODE) {
2662 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
2663 1);
2664 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
2665 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
2666 }
2667
2668 /* Create a COPP if port id are not enabled */
2669 if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) {
2670 pr_debug("%s: open ADM: port_idx: %d, copp_idx: %d\n", __func__,
2671 port_idx, copp_idx);
2672 if ((topology == SRS_TRUMEDIA_TOPOLOGY_ID) &&
2673 perf_mode == LEGACY_PCM_MODE) {
2674 int res;
2675
2676 atomic_set(&this_adm.mem_map_index, ADM_SRS_TRUMEDIA);
2677 msm_dts_srs_tm_ion_memmap(&this_adm.outband_memmap);
2678 res = adm_memory_map_regions(&this_adm.outband_memmap.paddr, 0,
2679 (uint32_t *)&this_adm.outband_memmap.size, 1);
2680 if (res < 0) {
2681 pr_err("%s: SRS adm_memory_map_regions failed ! addr = 0x%pK, size = %d\n",
2682 __func__, (void *)this_adm.outband_memmap.paddr,
2683 (uint32_t)this_adm.outband_memmap.size);
2684 }
2685 }
2686 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2687 APR_HDR_LEN(APR_HDR_SIZE),
2688 APR_PKT_VER);
2689 open.hdr.pkt_size = sizeof(open);
2690 open.hdr.src_svc = APR_SVC_ADM;
2691 open.hdr.src_domain = APR_DOMAIN_APPS;
2692 open.hdr.src_port = tmp_port;
2693 open.hdr.dest_svc = APR_SVC_ADM;
2694 open.hdr.dest_domain = APR_DOMAIN_ADSP;
2695 open.hdr.dest_port = tmp_port;
2696 open.hdr.token = port_idx << 16 | copp_idx;
2697 open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
2698 open.flags = flags;
2699 open.mode_of_operation = path;
2700 open.endpoint_id_1 = tmp_port;
2701 open.endpoint_id_2 = 0xFFFF;
2702
2703 if (this_adm.ec_ref_rx && (path != 1)) {
2704 open.endpoint_id_2 = this_adm.ec_ref_rx;
2705 this_adm.ec_ref_rx = -1;
2706 }
2707
2708 open.topology_id = topology;
2709
2710 open.dev_num_channel = channel_mode & 0x00FF;
2711 open.bit_width = bit_width;
2712 WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
2713 (rate != ULL_SUPPORTED_SAMPLE_RATE));
2714 open.sample_rate = rate;
2715
2716 ret = adm_arrange_mch_map(&open, path, channel_mode);
2717
2718 if (ret)
2719 return ret;
2720
2721 pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
2722 __func__, open.endpoint_id_1, open.sample_rate,
2723 open.topology_id);
2724
2725 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
2726
2727 if ((this_adm.num_ec_ref_rx_chans != 0) && (path != 1) &&
2728 (open.endpoint_id_2 != 0xFFFF)) {
2729 memset(&open_v6, 0,
2730 sizeof(struct adm_cmd_device_open_v6));
2731 memcpy(&open_v6, &open,
2732 sizeof(struct adm_cmd_device_open_v5));
2733 open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
2734 open_v6.hdr.pkt_size = sizeof(open_v6);
2735 open_v6.dev_num_channel_eid2 =
2736 this_adm.num_ec_ref_rx_chans;
2737 this_adm.num_ec_ref_rx_chans = 0;
2738
2739 if (this_adm.ec_ref_rx_bit_width != 0) {
2740 open_v6.bit_width_eid2 =
2741 this_adm.ec_ref_rx_bit_width;
2742 this_adm.ec_ref_rx_bit_width = 0;
2743 } else {
2744 open_v6.bit_width_eid2 = bit_width;
2745 }
2746
2747 if (this_adm.ec_ref_rx_sampling_rate != 0) {
2748 open_v6.sample_rate_eid2 =
2749 this_adm.ec_ref_rx_sampling_rate;
2750 this_adm.ec_ref_rx_sampling_rate = 0;
2751 } else {
2752 open_v6.sample_rate_eid2 = rate;
2753 }
2754
2755 pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
2756 __func__, open_v6.dev_num_channel_eid2,
2757 open_v6.bit_width_eid2,
2758 open_v6.sample_rate_eid2);
2759
2760 ret = adm_arrange_mch_ep2_map(&open_v6,
2761 open_v6.dev_num_channel_eid2);
2762
2763 if (ret)
2764 return ret;
2765
2766 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open_v6);
2767 } else {
2768 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
2769 }
2770 if (ret < 0) {
2771 pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
2772 __func__, tmp_port, port_id, ret);
2773 return -EINVAL;
2774 }
2775 /* Wait for the callback with copp id */
2776 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
2777 atomic_read(&this_adm.copp.stat
2778 [port_idx][copp_idx]) >= 0,
2779 msecs_to_jiffies(TIMEOUT_MS));
2780 if (!ret) {
2781 pr_err("%s: ADM open timedout for port_id: 0x%x for [0x%x]\n",
2782 __func__, tmp_port, port_id);
2783 return -EINVAL;
2784 } else if (atomic_read(&this_adm.copp.stat
2785 [port_idx][copp_idx]) > 0) {
2786 pr_err("%s: DSP returned error[%s]\n",
2787 __func__, adsp_err_get_err_str(
2788 atomic_read(&this_adm.copp.stat
2789 [port_idx][copp_idx])));
2790 return adsp_err_get_lnx_err_code(
2791 atomic_read(&this_adm.copp.stat
2792 [port_idx][copp_idx]));
2793 }
2794 }
2795 atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
2796 return copp_idx;
2797}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302798EXPORT_SYMBOL(adm_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302799
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302800/**
2801 * adm_copp_mfc_cfg -
2802 * command to send ADM MFC config
2803 *
2804 * @port_id: Port ID number
2805 * @copp_idx: copp index assigned
2806 * @dst_sample_rate: sink sample rate
2807 *
2808 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302809void adm_copp_mfc_cfg(int port_id, int copp_idx, int dst_sample_rate)
2810{
2811 struct audproc_mfc_output_media_fmt mfc_cfg;
2812 struct adm_cmd_device_open_v5 open;
2813 int port_idx;
2814 int sz = 0;
2815 int rc = 0;
2816 int i = 0;
2817
2818 port_id = q6audio_convert_virtual_to_portid(port_id);
2819 port_idx = adm_validate_and_get_port_index(port_id);
2820
2821 if (port_idx < 0) {
2822 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
2823 goto fail_cmd;
2824 }
2825
2826 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
2827 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
2828 goto fail_cmd;
2829 }
2830
2831 sz = sizeof(struct audproc_mfc_output_media_fmt);
2832
2833 mfc_cfg.params.hdr.hdr_field =
2834 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2835 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2836 mfc_cfg.params.hdr.pkt_size = sz;
2837 mfc_cfg.params.hdr.src_svc = APR_SVC_ADM;
2838 mfc_cfg.params.hdr.src_domain = APR_DOMAIN_APPS;
2839 mfc_cfg.params.hdr.src_port = port_id;
2840 mfc_cfg.params.hdr.dest_svc = APR_SVC_ADM;
2841 mfc_cfg.params.hdr.dest_domain = APR_DOMAIN_ADSP;
2842 mfc_cfg.params.hdr.dest_port =
2843 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
2844 mfc_cfg.params.hdr.token = port_idx << 16 | copp_idx;
2845 mfc_cfg.params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
2846 mfc_cfg.params.payload_addr_lsw = 0;
2847 mfc_cfg.params.payload_addr_msw = 0;
2848 mfc_cfg.params.mem_map_handle = 0;
2849 mfc_cfg.params.payload_size = sizeof(mfc_cfg) -
2850 sizeof(mfc_cfg.params);
2851 mfc_cfg.data.module_id = AUDPROC_MODULE_ID_MFC;
2852 mfc_cfg.data.param_id =
2853 AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
2854 mfc_cfg.data.param_size = mfc_cfg.params.payload_size -
2855 sizeof(mfc_cfg.data);
2856 mfc_cfg.data.reserved = 0;
2857 mfc_cfg.sampling_rate = dst_sample_rate;
2858 mfc_cfg.bits_per_sample =
2859 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
2860 open.dev_num_channel = mfc_cfg.num_channels =
2861 atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
2862
2863 rc = adm_arrange_mch_map(&open, ADM_PATH_PLAYBACK,
2864 mfc_cfg.num_channels);
2865 if (rc < 0) {
2866 pr_err("%s: unable to get channal map\n", __func__);
2867 goto fail_cmd;
2868 }
2869
2870 for (i = 0; i < mfc_cfg.num_channels; i++)
2871 mfc_cfg.channel_type[i] =
2872 (uint16_t) open.dev_channel_mapping[i];
2873
2874 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
2875
2876 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",
2877 __func__, port_idx, copp_idx,
2878 atomic_read(&this_adm.copp.rate[port_idx][copp_idx]),
2879 mfc_cfg.bits_per_sample, mfc_cfg.num_channels,
2880 mfc_cfg.sampling_rate);
2881
2882 rc = apr_send_pkt(this_adm.apr, (uint32_t *)&mfc_cfg);
2883
2884 if (rc < 0) {
2885 pr_err("%s: port_id: for[0x%x] failed %d\n",
2886 __func__, port_id, rc);
2887 goto fail_cmd;
2888 }
2889 /* Wait for the callback with copp id */
2890 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
2891 atomic_read(&this_adm.copp.stat
2892 [port_idx][copp_idx]) >= 0,
2893 msecs_to_jiffies(TIMEOUT_MS));
2894 if (!rc) {
2895 pr_err("%s: mfc_cfg Set params timed out for port_id: for [0x%x]\n",
2896 __func__, port_id);
2897 goto fail_cmd;
2898 } else if (atomic_read(&this_adm.copp.stat
2899 [port_idx][copp_idx]) > 0) {
2900 pr_err("%s: DSP returned error[%s]\n",
2901 __func__, adsp_err_get_err_str(
2902 atomic_read(&this_adm.copp.stat
2903 [port_idx][copp_idx])));
2904 goto fail_cmd;
2905 }
2906 rc = 0;
2907fail_cmd:
2908 return;
2909}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302910EXPORT_SYMBOL(adm_copp_mfc_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302911
2912static void route_set_opcode_matrix_id(
2913 struct adm_cmd_matrix_map_routings_v5 **route_addr,
2914 int path, uint32_t passthr_mode)
2915{
2916 struct adm_cmd_matrix_map_routings_v5 *route = *route_addr;
2917
2918 switch (path) {
2919 case ADM_PATH_PLAYBACK:
2920 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
2921 route->matrix_id = ADM_MATRIX_ID_AUDIO_RX;
2922 break;
2923 case ADM_PATH_LIVE_REC:
2924 if (passthr_mode == LISTEN) {
2925 route->hdr.opcode =
2926 ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
2927 route->matrix_id = ADM_MATRIX_ID_LISTEN_TX;
2928 break;
2929 }
2930 /* fall through to set matrix id for non-listen case */
2931 case ADM_PATH_NONLIVE_REC:
2932 route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5;
2933 route->matrix_id = ADM_MATRIX_ID_AUDIO_TX;
2934 break;
2935 case ADM_PATH_COMPRESSED_RX:
2936 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
2937 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_RX;
2938 break;
2939 case ADM_PATH_COMPRESSED_TX:
2940 route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5;
2941 route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_TX;
2942 break;
2943 default:
2944 pr_err("%s: Wrong path set[%d]\n", __func__, path);
2945 break;
2946 }
2947 pr_debug("%s: opcode 0x%x, matrix id %d\n",
2948 __func__, route->hdr.opcode, route->matrix_id);
2949}
2950
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302951/**
2952 * adm_matrix_map -
2953 * command to send ADM matrix map for ADM copp list
2954 *
2955 * @path: direction or ADM path type
2956 * @payload_map: have info of session id and associated copp_idx/num_copps
2957 * @perf_mode: performance mode like LL/ULL/..
2958 * @passthr_mode: flag to indicate passthrough mode
2959 *
2960 * Returns 0 on success or error on failure
2961 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302962int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode,
2963 uint32_t passthr_mode)
2964{
2965 struct adm_cmd_matrix_map_routings_v5 *route;
2966 struct adm_session_map_node_v5 *node;
2967 uint16_t *copps_list;
2968 int cmd_size = 0;
2969 int ret = 0, i = 0;
2970 void *payload = NULL;
2971 void *matrix_map = NULL;
2972 int port_idx, copp_idx;
2973
2974 /* Assumes port_ids have already been validated during adm_open */
2975 cmd_size = (sizeof(struct adm_cmd_matrix_map_routings_v5) +
2976 sizeof(struct adm_session_map_node_v5) +
2977 (sizeof(uint32_t) * payload_map.num_copps));
2978 matrix_map = kzalloc(cmd_size, GFP_KERNEL);
2979 if (matrix_map == NULL) {
2980 pr_err("%s: Mem alloc failed\n", __func__);
2981 ret = -EINVAL;
2982 return ret;
2983 }
2984 route = (struct adm_cmd_matrix_map_routings_v5 *)matrix_map;
2985
2986 route->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2987 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2988 route->hdr.pkt_size = cmd_size;
2989 route->hdr.src_svc = 0;
2990 route->hdr.src_domain = APR_DOMAIN_APPS;
2991 route->hdr.src_port = 0; /* Ignored */;
2992 route->hdr.dest_svc = APR_SVC_ADM;
2993 route->hdr.dest_domain = APR_DOMAIN_ADSP;
2994 route->hdr.dest_port = 0; /* Ignored */;
2995 route->hdr.token = 0;
2996 route->num_sessions = 1;
2997 route_set_opcode_matrix_id(&route, path, passthr_mode);
2998
2999 payload = ((u8 *)matrix_map +
3000 sizeof(struct adm_cmd_matrix_map_routings_v5));
3001 node = (struct adm_session_map_node_v5 *)payload;
3002
3003 node->session_id = payload_map.session_id;
3004 node->num_copps = payload_map.num_copps;
3005 payload = (u8 *)node + sizeof(struct adm_session_map_node_v5);
3006 copps_list = (uint16_t *)payload;
3007 for (i = 0; i < payload_map.num_copps; i++) {
3008 port_idx =
3009 adm_validate_and_get_port_index(payload_map.port_id[i]);
3010 if (port_idx < 0) {
3011 pr_err("%s: Invalid port_id 0x%x\n", __func__,
3012 payload_map.port_id[i]);
3013 ret = -EINVAL;
3014 goto fail_cmd;
3015 }
3016 copp_idx = payload_map.copp_idx[i];
3017 copps_list[i] = atomic_read(&this_adm.copp.id[port_idx]
3018 [copp_idx]);
3019 }
3020 atomic_set(&this_adm.matrix_map_stat, -1);
3021
3022 ret = apr_send_pkt(this_adm.apr, (uint32_t *)matrix_map);
3023 if (ret < 0) {
3024 pr_err("%s: routing for syream %d failed ret %d\n",
3025 __func__, payload_map.session_id, ret);
3026 ret = -EINVAL;
3027 goto fail_cmd;
3028 }
3029 ret = wait_event_timeout(this_adm.matrix_map_wait,
3030 atomic_read(&this_adm.matrix_map_stat) >= 0,
3031 msecs_to_jiffies(TIMEOUT_MS));
3032 if (!ret) {
3033 pr_err("%s: routing for syream %d failed\n", __func__,
3034 payload_map.session_id);
3035 ret = -EINVAL;
3036 goto fail_cmd;
3037 } else if (atomic_read(&this_adm.matrix_map_stat) > 0) {
3038 pr_err("%s: DSP returned error[%s]\n", __func__,
3039 adsp_err_get_err_str(atomic_read(
3040 &this_adm.matrix_map_stat)));
3041 ret = adsp_err_get_lnx_err_code(
3042 atomic_read(&this_adm.matrix_map_stat));
3043 goto fail_cmd;
3044 }
3045
3046 if ((perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) &&
3047 (path != ADM_PATH_COMPRESSED_RX)) {
3048 for (i = 0; i < payload_map.num_copps; i++) {
3049 port_idx = afe_get_port_index(payload_map.port_id[i]);
3050 copp_idx = payload_map.copp_idx[i];
3051 if (port_idx < 0 || copp_idx < 0 ||
3052 (copp_idx > MAX_COPPS_PER_PORT - 1)) {
3053 pr_err("%s: Invalid idx port_idx %d copp_idx %d\n",
3054 __func__, port_idx, copp_idx);
3055 continue;
3056 }
3057 rtac_add_adm_device(payload_map.port_id[i],
3058 atomic_read(&this_adm.copp.id
3059 [port_idx][copp_idx]),
3060 get_cal_path(path),
3061 payload_map.session_id,
3062 payload_map.app_type[i],
3063 payload_map.acdb_dev_id[i]);
3064
3065 if (!test_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3066 (void *)&this_adm.copp.adm_status[port_idx]
3067 [copp_idx])) {
3068 pr_debug("%s: adm copp[0x%x][%d] already sent",
3069 __func__, port_idx, copp_idx);
3070 continue;
3071 }
3072 send_adm_cal(payload_map.port_id[i], copp_idx,
3073 get_cal_path(path), perf_mode,
3074 payload_map.app_type[i],
3075 payload_map.acdb_dev_id[i],
Aditya Bavanari5106b562018-01-08 13:16:32 +05303076 payload_map.sample_rate[i],
3077 passthr_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303078 /* ADM COPP calibration is already sent */
3079 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3080 (void *)&this_adm.copp.
3081 adm_status[port_idx][copp_idx]);
3082 pr_debug("%s: copp_id: %d\n", __func__,
3083 atomic_read(&this_adm.copp.id[port_idx]
3084 [copp_idx]));
3085 }
3086 }
3087
3088fail_cmd:
3089 kfree(matrix_map);
3090 return ret;
3091}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303092EXPORT_SYMBOL(adm_matrix_map);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303093
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303094/**
3095 * adm_ec_ref_rx_id -
3096 * Update EC ref port ID
3097 *
3098 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303099void adm_ec_ref_rx_id(int port_id)
3100{
3101 this_adm.ec_ref_rx = port_id;
3102 pr_debug("%s: ec_ref_rx:%d\n", __func__, this_adm.ec_ref_rx);
3103}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303104EXPORT_SYMBOL(adm_ec_ref_rx_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303105
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303106/**
3107 * adm_num_ec_ref_rx_chans -
3108 * Update EC ref number of channels
3109 *
3110 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303111void adm_num_ec_ref_rx_chans(int num_chans)
3112{
3113 this_adm.num_ec_ref_rx_chans = num_chans;
3114 pr_debug("%s: num_ec_ref_rx_chans:%d\n",
3115 __func__, this_adm.num_ec_ref_rx_chans);
3116}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303117EXPORT_SYMBOL(adm_num_ec_ref_rx_chans);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303118
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303119/**
3120 * adm_ec_ref_rx_bit_width -
3121 * Update EC ref bit_width
3122 *
3123 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303124void adm_ec_ref_rx_bit_width(int bit_width)
3125{
3126 this_adm.ec_ref_rx_bit_width = bit_width;
3127 pr_debug("%s: ec_ref_rx_bit_width:%d\n",
3128 __func__, this_adm.ec_ref_rx_bit_width);
3129}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303130EXPORT_SYMBOL(adm_ec_ref_rx_bit_width);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303131
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303132/**
3133 * adm_ec_ref_rx_sampling_rate -
3134 * Update EC ref sample rate
3135 *
3136 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303137void adm_ec_ref_rx_sampling_rate(int sampling_rate)
3138{
3139 this_adm.ec_ref_rx_sampling_rate = sampling_rate;
3140 pr_debug("%s: ec_ref_rx_sampling_rate:%d\n",
3141 __func__, this_adm.ec_ref_rx_sampling_rate);
3142}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303143EXPORT_SYMBOL(adm_ec_ref_rx_sampling_rate);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303144
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303145/**
3146 * adm_close -
3147 * command to close ADM copp
3148 *
3149 * @port_id: Port ID number
3150 * @perf_mode: performance mode like LL/ULL/..
3151 * @copp_idx: copp index assigned
3152 *
3153 * Returns 0 on success or error on failure
3154 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303155int adm_close(int port_id, int perf_mode, int copp_idx)
3156{
3157 struct apr_hdr close;
3158
3159 int ret = 0, port_idx;
3160 int copp_id = RESET_COPP_ID;
3161
3162 pr_debug("%s: port_id=0x%x perf_mode: %d copp_idx: %d\n", __func__,
3163 port_id, perf_mode, copp_idx);
3164
3165 port_id = q6audio_convert_virtual_to_portid(port_id);
3166 port_idx = adm_validate_and_get_port_index(port_id);
3167 if (port_idx < 0) {
3168 pr_err("%s: Invalid port_id 0x%x\n",
3169 __func__, port_id);
3170 return -EINVAL;
3171 }
3172
3173 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
3174 pr_err("%s: Invalid copp idx: %d\n", __func__, copp_idx);
3175 return -EINVAL;
3176 }
3177
3178 if (this_adm.copp.adm_delay[port_idx][copp_idx] && perf_mode
3179 == LEGACY_PCM_MODE) {
3180 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
3181 1);
3182 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
3183 wake_up(&this_adm.copp.adm_delay_wait[port_idx][copp_idx]);
3184 }
3185
3186 atomic_dec(&this_adm.copp.cnt[port_idx][copp_idx]);
3187 if (!(atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]))) {
3188 copp_id = adm_get_copp_id(port_idx, copp_idx);
3189 pr_debug("%s: Closing ADM port_idx:%d copp_idx:%d copp_id:0x%x\n",
3190 __func__, port_idx, copp_idx, copp_id);
3191 if ((!perf_mode) && (this_adm.outband_memmap.paddr != 0) &&
3192 (atomic_read(&this_adm.copp.topology[port_idx][copp_idx]) ==
3193 SRS_TRUMEDIA_TOPOLOGY_ID)) {
3194 atomic_set(&this_adm.mem_map_index,
3195 ADM_SRS_TRUMEDIA);
3196 ret = adm_memory_unmap_regions();
3197 if (ret < 0) {
3198 pr_err("%s: adm mem unmmap err %d",
3199 __func__, ret);
3200 } else {
3201 atomic_set(&this_adm.mem_map_handles
3202 [ADM_SRS_TRUMEDIA], 0);
3203 }
3204 }
3205
3206
3207 if ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) &&
3208 this_adm.sourceTrackingData.memmap.paddr) {
3209 atomic_set(&this_adm.mem_map_index,
3210 ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
3211 ret = adm_memory_unmap_regions();
3212 if (ret < 0) {
3213 pr_err("%s: adm mem unmmap err %d",
3214 __func__, ret);
3215 }
3216 msm_audio_ion_free(
Banajit Goswami08bb7362017-11-03 22:48:23 -07003217 this_adm.sourceTrackingData.dma_buf);
3218 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303219 this_adm.sourceTrackingData.memmap.size = 0;
3220 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
3221 this_adm.sourceTrackingData.memmap.paddr = 0;
3222 this_adm.sourceTrackingData.apr_cmd_status = -1;
3223 atomic_set(&this_adm.mem_map_handles[
3224 ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
3225 }
3226
3227 close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3228 APR_HDR_LEN(APR_HDR_SIZE),
3229 APR_PKT_VER);
3230 close.pkt_size = sizeof(close);
3231 close.src_svc = APR_SVC_ADM;
3232 close.src_domain = APR_DOMAIN_APPS;
3233 close.src_port = port_id;
3234 close.dest_svc = APR_SVC_ADM;
3235 close.dest_domain = APR_DOMAIN_ADSP;
3236 close.dest_port = copp_id;
3237 close.token = port_idx << 16 | copp_idx;
3238 close.opcode = ADM_CMD_DEVICE_CLOSE_V5;
3239
3240 atomic_set(&this_adm.copp.id[port_idx][copp_idx],
3241 RESET_COPP_ID);
3242 atomic_set(&this_adm.copp.cnt[port_idx][copp_idx], 0);
3243 atomic_set(&this_adm.copp.topology[port_idx][copp_idx], 0);
3244 atomic_set(&this_adm.copp.mode[port_idx][copp_idx], 0);
3245 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3246 atomic_set(&this_adm.copp.rate[port_idx][copp_idx], 0);
3247 atomic_set(&this_adm.copp.channels[port_idx][copp_idx], 0);
3248 atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx], 0);
3249 atomic_set(&this_adm.copp.app_type[port_idx][copp_idx], 0);
3250
3251 clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
3252 (void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
3253
3254 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
3255 if (ret < 0) {
3256 pr_err("%s: ADM close failed %d\n", __func__, ret);
3257 return -EINVAL;
3258 }
3259
3260 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3261 atomic_read(&this_adm.copp.stat
3262 [port_idx][copp_idx]) >= 0,
3263 msecs_to_jiffies(TIMEOUT_MS));
3264 if (!ret) {
3265 pr_err("%s: ADM cmd Route timedout for port 0x%x\n",
3266 __func__, port_id);
3267 return -EINVAL;
3268 } else if (atomic_read(&this_adm.copp.stat
3269 [port_idx][copp_idx]) > 0) {
3270 pr_err("%s: DSP returned error[%s]\n",
3271 __func__, adsp_err_get_err_str(
3272 atomic_read(&this_adm.copp.stat
3273 [port_idx][copp_idx])));
3274 return adsp_err_get_lnx_err_code(
3275 atomic_read(&this_adm.copp.stat
3276 [port_idx][copp_idx]));
3277 }
3278 }
3279
3280 if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
3281 pr_debug("%s: remove adm device from rtac\n", __func__);
3282 rtac_remove_adm_device(port_id, copp_id);
3283 }
3284 return 0;
3285}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303286EXPORT_SYMBOL(adm_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303287
3288int send_rtac_audvol_cal(void)
3289{
3290 int ret = 0;
3291 int ret2 = 0;
3292 int i = 0;
3293 int copp_idx, port_idx, acdb_id, app_id, path;
3294 struct cal_block_data *cal_block = NULL;
3295 struct audio_cal_info_audvol *audvol_cal_info = NULL;
3296 struct rtac_adm rtac_adm_data;
3297
3298 mutex_lock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
3299
3300 cal_block = cal_utils_get_only_cal_block(
3301 this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]);
3302 if (cal_block == NULL) {
3303 pr_err("%s: can't find cal block!\n", __func__);
3304 goto unlock;
3305 }
3306
3307 audvol_cal_info = cal_block->cal_info;
3308 if (audvol_cal_info == NULL) {
3309 pr_err("%s: audvol_cal_info is NULL!\n", __func__);
3310 goto unlock;
3311 }
3312
3313 get_rtac_adm_data(&rtac_adm_data);
3314 for (; i < rtac_adm_data.num_of_dev; i++) {
3315
3316 acdb_id = rtac_adm_data.device[i].acdb_dev_id;
3317 if (acdb_id == 0)
3318 acdb_id = audvol_cal_info->acdb_id;
3319
3320 app_id = rtac_adm_data.device[i].app_type;
3321 if (app_id == 0)
3322 app_id = audvol_cal_info->app_type;
3323
3324 path = afe_get_port_type(rtac_adm_data.device[i].afe_port);
3325 if ((acdb_id == audvol_cal_info->acdb_id) &&
3326 (app_id == audvol_cal_info->app_type) &&
3327 (path == audvol_cal_info->path)) {
3328
3329 if (adm_get_indexes_from_copp_id(rtac_adm_data.
3330 device[i].copp, &copp_idx, &port_idx) != 0) {
3331 pr_debug("%s: Copp Id %d is not active\n",
3332 __func__,
3333 rtac_adm_data.device[i].copp);
3334 continue;
3335 }
3336
3337 ret2 = adm_remap_and_send_cal_block(ADM_RTAC_AUDVOL_CAL,
3338 rtac_adm_data.device[i].afe_port,
3339 copp_idx, cal_block,
3340 atomic_read(&this_adm.copp.
3341 mode[port_idx][copp_idx]),
3342 audvol_cal_info->app_type,
3343 audvol_cal_info->acdb_id,
3344 atomic_read(&this_adm.copp.
3345 rate[port_idx][copp_idx]));
3346 if (ret2 < 0) {
3347 pr_debug("%s: remap and send failed for copp Id %d, acdb id %d, app type %d, path %d\n",
3348 __func__, rtac_adm_data.device[i].copp,
3349 audvol_cal_info->acdb_id,
3350 audvol_cal_info->app_type,
3351 audvol_cal_info->path);
3352 ret = ret2;
3353 }
3354 }
3355 }
3356unlock:
3357 mutex_unlock(&this_adm.cal_data[ADM_RTAC_AUDVOL_CAL]->lock);
3358 return ret;
3359}
3360
3361int adm_map_rtac_block(struct rtac_cal_block_data *cal_block)
3362{
3363 int result = 0;
3364
3365 pr_debug("%s:\n", __func__);
3366
3367 if (cal_block == NULL) {
3368 pr_err("%s: cal_block is NULL!\n",
3369 __func__);
3370 result = -EINVAL;
3371 goto done;
3372 }
3373
3374 if (cal_block->cal_data.paddr == 0) {
3375 pr_debug("%s: No address to map!\n",
3376 __func__);
3377 result = -EINVAL;
3378 goto done;
3379 }
3380
3381 if (cal_block->map_data.map_size == 0) {
3382 pr_debug("%s: map size is 0!\n",
3383 __func__);
3384 result = -EINVAL;
3385 goto done;
3386 }
3387
3388 /* valid port ID needed for callback use primary I2S */
3389 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
3390 result = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
3391 &cal_block->map_data.map_size, 1);
3392 if (result < 0) {
3393 pr_err("%s: RTAC mmap did not work! size = %d result %d\n",
3394 __func__,
3395 cal_block->map_data.map_size, result);
3396 pr_debug("%s: RTAC mmap did not work! addr = 0x%pK, size = %d\n",
3397 __func__,
3398 &cal_block->cal_data.paddr,
3399 cal_block->map_data.map_size);
3400 goto done;
3401 }
3402
3403 cal_block->map_data.map_handle = atomic_read(
3404 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]);
3405done:
3406 return result;
3407}
3408
3409int adm_unmap_rtac_block(uint32_t *mem_map_handle)
3410{
3411 int result = 0;
3412
3413 pr_debug("%s:\n", __func__);
3414
3415 if (mem_map_handle == NULL) {
3416 pr_debug("%s: Map handle is NULL, nothing to unmap\n",
3417 __func__);
3418 goto done;
3419 }
3420
3421 if (*mem_map_handle == 0) {
3422 pr_debug("%s: Map handle is 0, nothing to unmap\n",
3423 __func__);
3424 goto done;
3425 }
3426
3427 if (*mem_map_handle != atomic_read(
3428 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL])) {
3429 pr_err("%s: Map handles do not match! Unmapping RTAC, RTAC map 0x%x, ADM map 0x%x\n",
3430 __func__, *mem_map_handle, atomic_read(
3431 &this_adm.mem_map_handles[ADM_RTAC_APR_CAL]));
3432
3433 /* if mismatch use handle passed in to unmap */
3434 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL],
3435 *mem_map_handle);
3436 }
3437
3438 /* valid port ID needed for callback use primary I2S */
3439 atomic_set(&this_adm.mem_map_index, ADM_RTAC_APR_CAL);
3440 result = adm_memory_unmap_regions();
3441 if (result < 0) {
3442 pr_debug("%s: adm_memory_unmap_regions failed, error %d\n",
3443 __func__, result);
3444 } else {
3445 atomic_set(&this_adm.mem_map_handles[ADM_RTAC_APR_CAL], 0);
3446 *mem_map_handle = 0;
3447 }
3448done:
3449 return result;
3450}
3451
3452static int get_cal_type_index(int32_t cal_type)
3453{
3454 int ret = -EINVAL;
3455
3456 switch (cal_type) {
3457 case ADM_AUDPROC_CAL_TYPE:
3458 ret = ADM_AUDPROC_CAL;
3459 break;
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05303460 case ADM_LSM_AUDPROC_CAL_TYPE:
3461 ret = ADM_LSM_AUDPROC_CAL;
3462 break;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303463 case ADM_AUDVOL_CAL_TYPE:
3464 ret = ADM_AUDVOL_CAL;
3465 break;
3466 case ADM_CUST_TOPOLOGY_CAL_TYPE:
3467 ret = ADM_CUSTOM_TOP_CAL;
3468 break;
3469 case ADM_RTAC_INFO_CAL_TYPE:
3470 ret = ADM_RTAC_INFO_CAL;
3471 break;
3472 case ADM_RTAC_APR_CAL_TYPE:
3473 ret = ADM_RTAC_APR_CAL;
3474 break;
3475 case ADM_RTAC_AUDVOL_CAL_TYPE:
3476 ret = ADM_RTAC_AUDVOL_CAL;
3477 break;
3478 default:
3479 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
3480 }
3481 return ret;
3482}
3483
3484static int adm_alloc_cal(int32_t cal_type, size_t data_size, void *data)
3485{
3486 int ret = 0;
3487 int cal_index;
3488
3489 pr_debug("%s:\n", __func__);
3490
3491 cal_index = get_cal_type_index(cal_type);
3492 if (cal_index < 0) {
3493 pr_err("%s: could not get cal index %d!\n",
3494 __func__, cal_index);
3495 ret = -EINVAL;
3496 goto done;
3497 }
3498
3499 ret = cal_utils_alloc_cal(data_size, data,
3500 this_adm.cal_data[cal_index], 0, NULL);
3501 if (ret < 0) {
3502 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
3503 __func__, ret, cal_type);
3504 ret = -EINVAL;
3505 goto done;
3506 }
3507done:
3508 return ret;
3509}
3510
3511static int adm_dealloc_cal(int32_t cal_type, size_t data_size, void *data)
3512{
3513 int ret = 0;
3514 int cal_index;
3515
3516 pr_debug("%s:\n", __func__);
3517
3518 cal_index = get_cal_type_index(cal_type);
3519 if (cal_index < 0) {
3520 pr_err("%s: could not get cal index %d!\n",
3521 __func__, cal_index);
3522 ret = -EINVAL;
3523 goto done;
3524 }
3525
3526 ret = cal_utils_dealloc_cal(data_size, data,
3527 this_adm.cal_data[cal_index]);
3528 if (ret < 0) {
3529 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
3530 __func__, ret, cal_type);
3531 ret = -EINVAL;
3532 goto done;
3533 }
3534done:
3535 return ret;
3536}
3537
3538static int adm_set_cal(int32_t cal_type, size_t data_size, void *data)
3539{
3540 int ret = 0;
3541 int cal_index;
3542
3543 pr_debug("%s:\n", __func__);
3544
3545 cal_index = get_cal_type_index(cal_type);
3546 if (cal_index < 0) {
3547 pr_err("%s: could not get cal index %d!\n",
3548 __func__, cal_index);
3549 ret = -EINVAL;
3550 goto done;
3551 }
3552
3553 ret = cal_utils_set_cal(data_size, data,
3554 this_adm.cal_data[cal_index], 0, NULL);
3555 if (ret < 0) {
3556 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
3557 __func__, ret, cal_type);
3558 ret = -EINVAL;
3559 goto done;
3560 }
3561
3562 if (cal_index == ADM_CUSTOM_TOP_CAL) {
3563 mutex_lock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
3564 this_adm.set_custom_topology = 1;
3565 mutex_unlock(&this_adm.cal_data[ADM_CUSTOM_TOP_CAL]->lock);
3566 } else if (cal_index == ADM_RTAC_AUDVOL_CAL) {
3567 send_rtac_audvol_cal();
3568 }
3569done:
3570 return ret;
3571}
3572
3573static int adm_map_cal_data(int32_t cal_type,
3574 struct cal_block_data *cal_block)
3575{
3576 int ret = 0;
3577 int cal_index;
3578
3579 pr_debug("%s:\n", __func__);
3580
3581 cal_index = get_cal_type_index(cal_type);
3582 if (cal_index < 0) {
3583 pr_err("%s: could not get cal index %d!\n",
3584 __func__, cal_index);
3585 ret = -EINVAL;
3586 goto done;
3587 }
3588
3589 atomic_set(&this_adm.mem_map_index, cal_index);
3590 ret = adm_memory_map_regions(&cal_block->cal_data.paddr, 0,
3591 (uint32_t *)&cal_block->map_data.map_size, 1);
3592 if (ret < 0) {
3593 pr_err("%s: map did not work! cal_type %i ret %d\n",
3594 __func__, cal_index, ret);
3595 ret = -ENODEV;
3596 goto done;
3597 }
3598 cal_block->map_data.q6map_handle = atomic_read(&this_adm.
3599 mem_map_handles[cal_index]);
3600done:
3601 return ret;
3602}
3603
3604static int adm_unmap_cal_data(int32_t cal_type,
3605 struct cal_block_data *cal_block)
3606{
3607 int ret = 0;
3608 int cal_index;
3609
3610 pr_debug("%s:\n", __func__);
3611
3612 cal_index = get_cal_type_index(cal_type);
3613 if (cal_index < 0) {
3614 pr_err("%s: could not get cal index %d!\n",
3615 __func__, cal_index);
3616 ret = -EINVAL;
3617 goto done;
3618 }
3619
3620 if (cal_block == NULL) {
3621 pr_err("%s: Cal block is NULL!\n",
3622 __func__);
3623 goto done;
3624 }
3625
3626 if (cal_block->map_data.q6map_handle == 0) {
3627 pr_err("%s: Map handle is NULL, nothing to unmap\n",
3628 __func__);
3629 goto done;
3630 }
3631
3632 atomic_set(&this_adm.mem_map_handles[cal_index],
3633 cal_block->map_data.q6map_handle);
3634 atomic_set(&this_adm.mem_map_index, cal_index);
3635 ret = adm_memory_unmap_regions();
3636 if (ret < 0) {
3637 pr_err("%s: unmap did not work! cal_type %i ret %d\n",
3638 __func__, cal_index, ret);
3639 ret = -ENODEV;
3640 goto done;
3641 }
3642 cal_block->map_data.q6map_handle = 0;
3643done:
3644 return ret;
3645}
3646
3647static void adm_delete_cal_data(void)
3648{
3649 pr_debug("%s:\n", __func__);
3650
3651 cal_utils_destroy_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data);
3652}
3653
3654static int adm_init_cal_data(void)
3655{
3656 int ret = 0;
3657 struct cal_type_info cal_type_info[] = {
3658 {{ADM_CUST_TOPOLOGY_CAL_TYPE,
3659 {adm_alloc_cal, adm_dealloc_cal, NULL,
3660 adm_set_cal, NULL, NULL} },
3661 {adm_map_cal_data, adm_unmap_cal_data,
3662 cal_utils_match_buf_num} },
3663
3664 {{ADM_AUDPROC_CAL_TYPE,
3665 {adm_alloc_cal, adm_dealloc_cal, NULL,
3666 adm_set_cal, NULL, NULL} },
3667 {adm_map_cal_data, adm_unmap_cal_data,
3668 cal_utils_match_buf_num} },
3669
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05303670 {{ADM_LSM_AUDPROC_CAL_TYPE,
3671 {adm_alloc_cal, adm_dealloc_cal, NULL,
3672 adm_set_cal, NULL, NULL} },
3673 {adm_map_cal_data, adm_unmap_cal_data,
3674 cal_utils_match_buf_num} },
3675
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303676 {{ADM_AUDVOL_CAL_TYPE,
3677 {adm_alloc_cal, adm_dealloc_cal, NULL,
3678 adm_set_cal, NULL, NULL} },
3679 {adm_map_cal_data, adm_unmap_cal_data,
3680 cal_utils_match_buf_num} },
3681
3682 {{ADM_RTAC_INFO_CAL_TYPE,
3683 {NULL, NULL, NULL, NULL, NULL, NULL} },
3684 {NULL, NULL, cal_utils_match_buf_num} },
3685
3686 {{ADM_RTAC_APR_CAL_TYPE,
3687 {NULL, NULL, NULL, NULL, NULL, NULL} },
3688 {NULL, NULL, cal_utils_match_buf_num} },
3689
3690 {{SRS_TRUMEDIA_CAL_TYPE,
3691 {NULL, NULL, NULL, NULL, NULL, NULL} },
3692 {NULL, NULL, cal_utils_match_buf_num} },
3693
3694 {{ADM_RTAC_AUDVOL_CAL_TYPE,
3695 {adm_alloc_cal, adm_dealloc_cal, NULL,
3696 adm_set_cal, NULL, NULL} },
3697 {adm_map_cal_data, adm_unmap_cal_data,
3698 cal_utils_match_buf_num} },
3699 };
3700 pr_debug("%s:\n", __func__);
3701
3702 ret = cal_utils_create_cal_types(ADM_MAX_CAL_TYPES, this_adm.cal_data,
3703 cal_type_info);
3704 if (ret < 0) {
3705 pr_err("%s: could not create cal type! ret %d\n",
3706 __func__, ret);
3707 ret = -EINVAL;
3708 goto err;
3709 }
3710
3711 return ret;
3712err:
3713 adm_delete_cal_data();
3714 return ret;
3715}
3716
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303717/**
3718 * adm_set_volume -
3719 * command to set volume on ADM copp
3720 *
3721 * @port_id: Port ID number
3722 * @copp_idx: copp index assigned
3723 * @volume: gain value to set
3724 *
3725 * Returns 0 on success or error on failure
3726 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303727int adm_set_volume(int port_id, int copp_idx, int volume)
3728{
3729 struct audproc_volume_ctrl_master_gain audproc_vol;
3730 int sz = 0;
3731 int rc = 0;
3732 int port_idx;
3733
3734 pr_debug("%s: port_id %d, volume %d\n", __func__, port_id, volume);
3735 port_id = afe_convert_virtual_to_portid(port_id);
3736 port_idx = adm_validate_and_get_port_index(port_id);
3737 if (port_idx < 0) {
3738 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
3739 rc = -EINVAL;
3740 goto fail_cmd;
3741 }
3742
3743 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
3744 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
3745 return -EINVAL;
3746 }
3747
3748 sz = sizeof(struct audproc_volume_ctrl_master_gain);
3749 audproc_vol.params.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3750 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3751 audproc_vol.params.hdr.pkt_size = sz;
3752 audproc_vol.params.hdr.src_svc = APR_SVC_ADM;
3753 audproc_vol.params.hdr.src_domain = APR_DOMAIN_APPS;
3754 audproc_vol.params.hdr.src_port = port_id;
3755 audproc_vol.params.hdr.dest_svc = APR_SVC_ADM;
3756 audproc_vol.params.hdr.dest_domain = APR_DOMAIN_ADSP;
3757 audproc_vol.params.hdr.dest_port =
3758 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
3759 audproc_vol.params.hdr.token = port_idx << 16 | copp_idx;
3760 audproc_vol.params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
3761 audproc_vol.params.payload_addr_lsw = 0;
3762 audproc_vol.params.payload_addr_msw = 0;
3763 audproc_vol.params.mem_map_handle = 0;
3764 audproc_vol.params.payload_size = sizeof(audproc_vol) -
3765 sizeof(audproc_vol.params);
3766 audproc_vol.data.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
3767 audproc_vol.data.param_id = AUDPROC_PARAM_ID_VOL_CTRL_MASTER_GAIN;
3768 audproc_vol.data.param_size = audproc_vol.params.payload_size -
3769 sizeof(audproc_vol.data);
3770 audproc_vol.data.reserved = 0;
3771 audproc_vol.master_gain = volume;
3772
3773 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3774 rc = apr_send_pkt(this_adm.apr, (uint32_t *)&audproc_vol);
3775 if (rc < 0) {
3776 pr_err("%s: Set params failed port = %#x\n",
3777 __func__, port_id);
3778 rc = -EINVAL;
3779 goto fail_cmd;
3780 }
3781 /* Wait for the callback */
3782 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3783 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
3784 msecs_to_jiffies(TIMEOUT_MS));
3785 if (!rc) {
3786 pr_err("%s: Vol cntrl Set params timed out port = %#x\n",
3787 __func__, port_id);
3788 rc = -EINVAL;
3789 goto fail_cmd;
3790 } else if (atomic_read(&this_adm.copp.stat
3791 [port_idx][copp_idx]) > 0) {
3792 pr_err("%s: DSP returned error[%s]\n",
3793 __func__, adsp_err_get_err_str(
3794 atomic_read(&this_adm.copp.stat
3795 [port_idx][copp_idx])));
3796 rc = adsp_err_get_lnx_err_code(
3797 atomic_read(&this_adm.copp.stat
3798 [port_idx][copp_idx]));
3799 goto fail_cmd;
3800 }
3801 rc = 0;
3802fail_cmd:
3803 return rc;
3804}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303805EXPORT_SYMBOL(adm_set_volume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303806
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303807/**
3808 * adm_set_softvolume -
3809 * command to set softvolume
3810 *
3811 * @port_id: Port ID number
3812 * @copp_idx: copp index assigned
3813 * @softvol_param: Params to set for softvolume
3814 *
3815 * Returns 0 on success or error on failure
3816 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303817int adm_set_softvolume(int port_id, int copp_idx,
3818 struct audproc_softvolume_params *softvol_param)
3819{
3820 struct audproc_soft_step_volume_params audproc_softvol;
3821 int sz = 0;
3822 int rc = 0;
3823 int port_idx;
3824
3825 pr_debug("%s: period %d step %d curve %d\n", __func__,
3826 softvol_param->period, softvol_param->step,
3827 softvol_param->rampingcurve);
3828
3829 port_id = afe_convert_virtual_to_portid(port_id);
3830 port_idx = adm_validate_and_get_port_index(port_id);
3831 if (port_idx < 0) {
3832 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
3833 rc = -EINVAL;
3834 goto fail_cmd;
3835 }
3836
3837 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
3838 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
3839 return -EINVAL;
3840 }
3841
3842 sz = sizeof(struct audproc_soft_step_volume_params);
3843
3844 audproc_softvol.params.hdr.hdr_field =
3845 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3846 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3847 audproc_softvol.params.hdr.pkt_size = sz;
3848 audproc_softvol.params.hdr.src_svc = APR_SVC_ADM;
3849 audproc_softvol.params.hdr.src_domain = APR_DOMAIN_APPS;
3850 audproc_softvol.params.hdr.src_port = port_id;
3851 audproc_softvol.params.hdr.dest_svc = APR_SVC_ADM;
3852 audproc_softvol.params.hdr.dest_domain = APR_DOMAIN_ADSP;
3853 audproc_softvol.params.hdr.dest_port =
3854 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
3855 audproc_softvol.params.hdr.token = port_idx << 16 | copp_idx;
3856 audproc_softvol.params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
3857 audproc_softvol.params.payload_addr_lsw = 0;
3858 audproc_softvol.params.payload_addr_msw = 0;
3859 audproc_softvol.params.mem_map_handle = 0;
3860 audproc_softvol.params.payload_size = sizeof(audproc_softvol) -
3861 sizeof(audproc_softvol.params);
3862 audproc_softvol.data.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
3863 audproc_softvol.data.param_id =
3864 AUDPROC_PARAM_ID_SOFT_VOL_STEPPING_PARAMETERS;
3865 audproc_softvol.data.param_size = audproc_softvol.params.payload_size -
3866 sizeof(audproc_softvol.data);
3867 audproc_softvol.data.reserved = 0;
3868 audproc_softvol.period = softvol_param->period;
3869 audproc_softvol.step = softvol_param->step;
3870 audproc_softvol.ramping_curve = softvol_param->rampingcurve;
3871
3872 pr_debug("%s: period %d, step %d, curve %d\n", __func__,
3873 audproc_softvol.period, audproc_softvol.step,
3874 audproc_softvol.ramping_curve);
3875
3876 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3877 rc = apr_send_pkt(this_adm.apr, (uint32_t *)&audproc_softvol);
3878 if (rc < 0) {
3879 pr_err("%s: Set params failed port = %#x\n",
3880 __func__, port_id);
3881 rc = -EINVAL;
3882 goto fail_cmd;
3883 }
3884 /* Wait for the callback */
3885 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3886 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
3887 msecs_to_jiffies(TIMEOUT_MS));
3888 if (!rc) {
3889 pr_err("%s: Soft volume Set params timed out port = %#x\n",
3890 __func__, port_id);
3891 rc = -EINVAL;
3892 goto fail_cmd;
3893 } else if (atomic_read(&this_adm.copp.stat
3894 [port_idx][copp_idx]) > 0) {
3895 pr_err("%s: DSP returned error[%s]\n",
3896 __func__, adsp_err_get_err_str(
3897 atomic_read(&this_adm.copp.stat
3898 [port_idx][copp_idx])));
3899 rc = adsp_err_get_lnx_err_code(
3900 atomic_read(&this_adm.copp.stat
3901 [port_idx][copp_idx]));
3902 goto fail_cmd;
3903 }
3904 rc = 0;
3905fail_cmd:
3906 return rc;
3907}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303908EXPORT_SYMBOL(adm_set_softvolume);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303909
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303910/**
3911 * adm_set_mic_gain -
3912 * command to set MIC gain
3913 *
3914 * @port_id: Port ID number
3915 * @copp_idx: copp index assigned
3916 * @volume: gain value to set
3917 *
3918 * Returns 0 on success or error on failure
3919 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303920int adm_set_mic_gain(int port_id, int copp_idx, int volume)
3921{
3922 struct adm_set_mic_gain_params mic_gain_params;
3923 int rc = 0;
3924 int sz, port_idx;
3925
3926 pr_debug("%s:\n", __func__);
3927 port_id = afe_convert_virtual_to_portid(port_id);
3928 port_idx = adm_validate_and_get_port_index(port_id);
3929 if (port_idx < 0) {
3930 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
3931 return -EINVAL;
3932 }
3933
3934 sz = sizeof(struct adm_set_mic_gain_params);
3935
3936 mic_gain_params.params.hdr.hdr_field =
3937 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3938 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3939 mic_gain_params.params.hdr.pkt_size = sz;
3940 mic_gain_params.params.hdr.src_svc = APR_SVC_ADM;
3941 mic_gain_params.params.hdr.src_domain = APR_DOMAIN_APPS;
3942 mic_gain_params.params.hdr.src_port = port_id;
3943 mic_gain_params.params.hdr.dest_svc = APR_SVC_ADM;
3944 mic_gain_params.params.hdr.dest_domain = APR_DOMAIN_ADSP;
3945 mic_gain_params.params.hdr.dest_port =
3946 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
3947 mic_gain_params.params.hdr.token = port_idx << 16 | copp_idx;
3948 mic_gain_params.params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
3949 mic_gain_params.params.payload_addr_lsw = 0;
3950 mic_gain_params.params.payload_addr_msw = 0;
3951 mic_gain_params.params.mem_map_handle = 0;
3952 mic_gain_params.params.payload_size =
3953 sizeof(struct adm_param_data_v5) +
3954 sizeof(struct admx_mic_gain);
3955 mic_gain_params.data.module_id = ADM_MODULE_IDX_MIC_GAIN_CTRL;
3956 mic_gain_params.data.param_id = ADM_PARAM_IDX_MIC_GAIN;
3957 mic_gain_params.data.param_size =
3958 sizeof(struct admx_mic_gain);
3959 mic_gain_params.data.reserved = 0;
3960 mic_gain_params.mic_gain_data.tx_mic_gain = volume;
3961 mic_gain_params.mic_gain_data.reserved = 0;
3962 pr_debug("%s: Mic Gain set to %d at port_id 0x%x\n",
3963 __func__, volume, port_id);
3964
3965 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
3966 rc = apr_send_pkt(this_adm.apr, (uint32_t *)&mic_gain_params);
3967 if (rc < 0) {
3968 pr_err("%s: Set params failed port = %#x\n",
3969 __func__, port_id);
3970 rc = -EINVAL;
3971 goto fail_cmd;
3972 }
3973 /* Wait for the callback */
3974 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
3975 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
3976 msecs_to_jiffies(TIMEOUT_MS));
3977 if (!rc) {
3978 pr_err("%s: Mic Gain Set params timed out port = %#x\n",
3979 __func__, port_id);
3980 rc = -EINVAL;
3981 goto fail_cmd;
3982 } else if (atomic_read(&this_adm.copp.stat
3983 [port_idx][copp_idx]) > 0) {
3984 pr_err("%s: DSP returned error[%s]\n",
3985 __func__, adsp_err_get_err_str(
3986 atomic_read(&this_adm.copp.stat
3987 [port_idx][copp_idx])));
3988 rc = adsp_err_get_lnx_err_code(
3989 atomic_read(&this_adm.copp.stat
3990 [port_idx][copp_idx]));
3991 goto fail_cmd;
3992 }
3993 rc = 0;
3994fail_cmd:
3995 return rc;
3996}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303997EXPORT_SYMBOL(adm_set_mic_gain);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303998
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05303999/**
4000 * adm_send_set_multichannel_ec_primary_mic_ch -
4001 * command to set multi-ch EC primary mic
4002 *
4003 * @port_id: Port ID number
4004 * @copp_idx: copp index assigned
4005 * @primary_mic_ch: channel number of primary mic
4006 *
4007 * Returns 0 on success or error on failure
4008 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304009int adm_send_set_multichannel_ec_primary_mic_ch(int port_id, int copp_idx,
4010 int primary_mic_ch)
4011{
4012 struct adm_set_sec_primary_ch_params sec_primary_ch_params;
4013 int rc = 0;
4014 int sz, port_idx;
4015
4016 pr_debug("%s port_id 0x%x, copp_idx 0x%x, primary_mic_ch %d\n",
4017 __func__, port_id, copp_idx, primary_mic_ch);
4018 port_id = afe_convert_virtual_to_portid(port_id);
4019 port_idx = adm_validate_and_get_port_index(port_id);
4020 if (port_idx < 0) {
4021 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
4022 return -EINVAL;
4023 }
4024
4025 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4026 pr_err("%s: Invalid copp_idx 0x%x\n", __func__, copp_idx);
4027 return -EINVAL;
4028 }
4029
4030 sz = sizeof(struct adm_set_sec_primary_ch_params);
4031
4032 sec_primary_ch_params.params.hdr.hdr_field =
4033 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4034 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4035 sec_primary_ch_params.params.hdr.pkt_size = sz;
4036 sec_primary_ch_params.params.hdr.src_svc = APR_SVC_ADM;
4037 sec_primary_ch_params.params.hdr.src_domain = APR_DOMAIN_APPS;
4038 sec_primary_ch_params.params.hdr.src_port = port_id;
4039 sec_primary_ch_params.params.hdr.dest_svc = APR_SVC_ADM;
4040 sec_primary_ch_params.params.hdr.dest_domain = APR_DOMAIN_ADSP;
4041 sec_primary_ch_params.params.hdr.dest_port =
4042 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
4043 sec_primary_ch_params.params.hdr.token = port_idx << 16 | copp_idx;
4044 sec_primary_ch_params.params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
4045 sec_primary_ch_params.params.payload_addr_lsw = 0;
4046 sec_primary_ch_params.params.payload_addr_msw = 0;
4047 sec_primary_ch_params.params.mem_map_handle = 0;
4048 sec_primary_ch_params.params.payload_size =
4049 sizeof(struct adm_param_data_v5) +
4050 sizeof(struct admx_sec_primary_mic_ch);
4051 sec_primary_ch_params.data.module_id =
4052 AUDPROC_MODULE_ID_VOICE_TX_SECNS;
4053 sec_primary_ch_params.data.param_id =
4054 AUDPROC_PARAM_IDX_SEC_PRIMARY_MIC_CH;
4055 sec_primary_ch_params.data.param_size =
4056 sizeof(struct admx_sec_primary_mic_ch);
4057 sec_primary_ch_params.data.reserved = 0;
4058 sec_primary_ch_params.sec_primary_mic_ch_data.version = 0;
4059 sec_primary_ch_params.sec_primary_mic_ch_data.reserved = 0;
4060 sec_primary_ch_params.sec_primary_mic_ch_data.sec_primary_mic_ch =
4061 primary_mic_ch;
4062 sec_primary_ch_params.sec_primary_mic_ch_data.reserved1 = 0;
4063
4064 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
4065 rc = apr_send_pkt(this_adm.apr, (uint32_t *)&sec_primary_ch_params);
4066 if (rc < 0) {
4067 pr_err("%s: Set params failed port = %#x\n",
4068 __func__, port_id);
4069 rc = -EINVAL;
4070 goto fail_cmd;
4071 }
4072 /* Wait for the callback */
4073 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
4074 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
4075 msecs_to_jiffies(TIMEOUT_MS));
4076 if (!rc) {
4077 pr_err("%s: Mic Set params timed out port = %#x\n",
4078 __func__, port_id);
4079 rc = -EINVAL;
4080 goto fail_cmd;
4081 } else if (atomic_read(&this_adm.copp.stat
4082 [port_idx][copp_idx]) > 0) {
4083 pr_err("%s: DSP returned error[%s]\n",
4084 __func__, adsp_err_get_err_str(
4085 atomic_read(&this_adm.copp.stat
4086 [port_idx][copp_idx])));
4087 rc = adsp_err_get_lnx_err_code(
4088 atomic_read(&this_adm.copp.stat
4089 [port_idx][copp_idx]));
4090 goto fail_cmd;
4091 }
4092 rc = 0;
4093fail_cmd:
4094 return rc;
4095}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304096EXPORT_SYMBOL(adm_send_set_multichannel_ec_primary_mic_ch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304097
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304098/**
4099 * adm_param_enable -
4100 * command to send params to ADM for given module
4101 *
4102 * @port_id: Port ID number
4103 * @copp_idx: copp index assigned
4104 * @module_id: ADM module
4105 * @enable: flag to enable or disable module
4106 *
4107 * Returns 0 on success or error on failure
4108 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304109int adm_param_enable(int port_id, int copp_idx, int module_id, int enable)
4110{
4111 struct audproc_enable_param_t adm_mod_enable;
4112 int sz = 0;
4113 int rc = 0;
4114 int port_idx;
4115
4116 pr_debug("%s port_id %d, module_id 0x%x, enable %d\n",
4117 __func__, port_id, module_id, enable);
4118 port_id = afe_convert_virtual_to_portid(port_id);
4119 port_idx = adm_validate_and_get_port_index(port_id);
4120 if (port_idx < 0) {
4121 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4122 rc = -EINVAL;
4123 goto fail_cmd;
4124 }
4125
4126 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4127 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4128 return -EINVAL;
4129 }
4130
4131 sz = sizeof(struct audproc_enable_param_t);
4132
4133 adm_mod_enable.pp_params.hdr.hdr_field =
4134 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4135 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4136 adm_mod_enable.pp_params.hdr.pkt_size = sz;
4137 adm_mod_enable.pp_params.hdr.src_svc = APR_SVC_ADM;
4138 adm_mod_enable.pp_params.hdr.src_domain = APR_DOMAIN_APPS;
4139 adm_mod_enable.pp_params.hdr.src_port = port_id;
4140 adm_mod_enable.pp_params.hdr.dest_svc = APR_SVC_ADM;
4141 adm_mod_enable.pp_params.hdr.dest_domain = APR_DOMAIN_ADSP;
4142 adm_mod_enable.pp_params.hdr.dest_port =
4143 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
4144 adm_mod_enable.pp_params.hdr.token = port_idx << 16 | copp_idx;
4145 adm_mod_enable.pp_params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
4146 adm_mod_enable.pp_params.payload_addr_lsw = 0;
4147 adm_mod_enable.pp_params.payload_addr_msw = 0;
4148 adm_mod_enable.pp_params.mem_map_handle = 0;
4149 adm_mod_enable.pp_params.payload_size = sizeof(adm_mod_enable) -
4150 sizeof(adm_mod_enable.pp_params) +
4151 sizeof(adm_mod_enable.pp_params.params);
4152 adm_mod_enable.pp_params.params.module_id = module_id;
4153 adm_mod_enable.pp_params.params.param_id = AUDPROC_PARAM_ID_ENABLE;
4154 adm_mod_enable.pp_params.params.param_size =
4155 adm_mod_enable.pp_params.payload_size -
4156 sizeof(adm_mod_enable.pp_params.params);
4157 adm_mod_enable.pp_params.params.reserved = 0;
4158 adm_mod_enable.enable = enable;
4159
4160 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
4161
4162 rc = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_mod_enable);
4163 if (rc < 0) {
4164 pr_err("%s: Set params failed port = %#x\n",
4165 __func__, port_id);
4166 rc = -EINVAL;
4167 goto fail_cmd;
4168 }
4169 /* Wait for the callback */
4170 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
4171 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
4172 msecs_to_jiffies(TIMEOUT_MS));
4173 if (!rc) {
4174 pr_err("%s: module %x enable %d timed out on port = %#x\n",
4175 __func__, module_id, enable, port_id);
4176 rc = -EINVAL;
4177 goto fail_cmd;
4178 } else if (atomic_read(&this_adm.copp.stat
4179 [port_idx][copp_idx]) > 0) {
4180 pr_err("%s: DSP returned error[%s]\n",
4181 __func__, adsp_err_get_err_str(
4182 atomic_read(&this_adm.copp.stat
4183 [port_idx][copp_idx])));
4184 rc = adsp_err_get_lnx_err_code(
4185 atomic_read(&this_adm.copp.stat
4186 [port_idx][copp_idx]));
4187 goto fail_cmd;
4188 }
4189 rc = 0;
4190fail_cmd:
4191 return rc;
4192
4193}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304194EXPORT_SYMBOL(adm_param_enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304195
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304196/**
4197 * adm_send_calibration -
4198 * send ADM calibration to DSP
4199 *
4200 * @port_id: Port ID number
4201 * @copp_idx: copp index assigned
4202 * @path: direction or ADM path type
4203 * @perf_mode: performance mode like LL/ULL/..
4204 * @cal_type: calibration type to use
4205 * @params: pointer with cal data
4206 * @size: cal size
4207 *
4208 * Returns 0 on success or error on failure
4209 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304210int adm_send_calibration(int port_id, int copp_idx, int path, int perf_mode,
4211 int cal_type, char *params, int size)
4212{
4213
4214 struct adm_cmd_set_pp_params_v5 *adm_params = NULL;
4215 int sz, rc = 0;
4216 int port_idx;
4217
4218 pr_debug("%s:port_id %d, path %d, perf_mode %d, cal_type %d, size %d\n",
4219 __func__, port_id, path, perf_mode, cal_type, size);
4220
4221 port_id = afe_convert_virtual_to_portid(port_id);
4222 port_idx = adm_validate_and_get_port_index(port_id);
4223 if (port_idx < 0) {
4224 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4225 rc = -EINVAL;
4226 goto end;
4227 }
4228
4229 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4230 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4231 return -EINVAL;
4232 }
4233
4234 /* Maps audio_dev_ctrl path definition to ACDB definition */
4235 if (get_cal_path(path) != RX_DEVICE) {
4236 pr_err("%s: acdb_path %d\n", __func__, path);
4237 rc = -EINVAL;
4238 goto end;
4239 }
4240
4241 sz = sizeof(struct adm_cmd_set_pp_params_v5) + size;
4242 adm_params = kzalloc(sz, GFP_KERNEL);
4243 if (!adm_params) {
4244 pr_err("%s, adm params memory alloc failed", __func__);
4245 rc = -ENOMEM;
4246 goto end;
4247 }
4248
4249 memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
4250 params, size);
4251
4252 adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4253 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4254 adm_params->hdr.pkt_size = sz;
4255 adm_params->hdr.src_svc = APR_SVC_ADM;
4256 adm_params->hdr.src_domain = APR_DOMAIN_APPS;
4257 adm_params->hdr.src_port = port_id;
4258 adm_params->hdr.dest_svc = APR_SVC_ADM;
4259 adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
4260 adm_params->hdr.dest_port =
4261 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
4262 adm_params->hdr.token = port_idx << 16 | copp_idx;
4263 adm_params->hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
4264 /* payload address and mmap handle initialized to zero by kzalloc */
4265 adm_params->payload_size = size;
4266
4267 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
4268 rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
4269 if (rc < 0) {
4270 pr_err("%s: Set params failed port = %#x\n",
4271 __func__, port_id);
4272 rc = -EINVAL;
4273 goto end;
4274 }
4275 /* Wait for the callback */
4276 rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
4277 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
4278 msecs_to_jiffies(TIMEOUT_MS));
4279 if (!rc) {
4280 pr_err("%s: Set params timed out port = %#x\n",
4281 __func__, port_id);
4282 rc = -EINVAL;
4283 goto end;
4284 } else if (atomic_read(&this_adm.copp.stat
4285 [port_idx][copp_idx]) > 0) {
4286 pr_err("%s: DSP returned error[%s]\n",
4287 __func__, adsp_err_get_err_str(
4288 atomic_read(&this_adm.copp.stat
4289 [port_idx][copp_idx])));
4290 rc = adsp_err_get_lnx_err_code(
4291 atomic_read(&this_adm.copp.stat
4292 [port_idx][copp_idx]));
4293 goto end;
4294 }
4295 rc = 0;
4296
4297end:
4298 kfree(adm_params);
4299 return rc;
4300}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304301EXPORT_SYMBOL(adm_send_calibration);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304302
4303/*
4304 * adm_update_wait_parameters must be called with routing driver locks.
4305 * adm_reset_wait_parameters must be called with routing driver locks.
4306 * set and reset parmeters are separated to make sure it is always called
4307 * under routing driver lock.
4308 * adm_wait_timeout is to block until timeout or interrupted. Timeout is
4309 * not a an error.
4310 */
4311int adm_set_wait_parameters(int port_id, int copp_idx)
4312{
4313
4314 int ret = 0, port_idx;
4315
4316 pr_debug("%s: port_id 0x%x, copp_idx %d\n", __func__, port_id,
4317 copp_idx);
4318 port_id = afe_convert_virtual_to_portid(port_id);
4319 port_idx = adm_validate_and_get_port_index(port_id);
4320 if (port_idx < 0) {
4321 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4322 ret = -EINVAL;
4323 goto end;
4324 }
4325
4326 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4327 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4328 return -EINVAL;
4329 }
4330
4331 this_adm.copp.adm_delay[port_idx][copp_idx] = 1;
4332 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 0);
4333
4334end:
4335 return ret;
4336
4337}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304338EXPORT_SYMBOL(adm_set_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304339
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304340/**
4341 * adm_reset_wait_parameters -
4342 * reset wait parameters or ADM delay value
4343 *
4344 * @port_id: Port ID number
4345 * @copp_idx: copp index assigned
4346 *
4347 * Returns 0 on success or error on failure
4348 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304349int adm_reset_wait_parameters(int port_id, int copp_idx)
4350{
4351 int ret = 0, port_idx;
4352
4353 pr_debug("%s: port_id 0x%x copp_idx %d\n", __func__, port_id,
4354 copp_idx);
4355 port_id = afe_convert_virtual_to_portid(port_id);
4356 port_idx = adm_validate_and_get_port_index(port_id);
4357 if (port_idx < 0) {
4358 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4359 ret = -EINVAL;
4360 goto end;
4361 }
4362
4363 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4364 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4365 return -EINVAL;
4366 }
4367
4368 atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx], 1);
4369 this_adm.copp.adm_delay[port_idx][copp_idx] = 0;
4370
4371end:
4372 return ret;
4373}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304374EXPORT_SYMBOL(adm_reset_wait_parameters);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304375
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304376/**
4377 * adm_wait_timeout -
4378 * ADM wait command after command send to DSP
4379 *
4380 * @port_id: Port ID number
4381 * @copp_idx: copp index assigned
4382 * @wait_time: value in ms for command timeout
4383 *
4384 * Returns 0 on success or error on failure
4385 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304386int adm_wait_timeout(int port_id, int copp_idx, int wait_time)
4387{
4388 int ret = 0, port_idx;
4389
4390 pr_debug("%s: port_id 0x%x, copp_idx %d, wait_time %d\n", __func__,
4391 port_id, copp_idx, wait_time);
4392 port_id = afe_convert_virtual_to_portid(port_id);
4393 port_idx = adm_validate_and_get_port_index(port_id);
4394 if (port_idx < 0) {
4395 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4396 ret = -EINVAL;
4397 goto end;
4398 }
4399
4400 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4401 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4402 return -EINVAL;
4403 }
4404
4405 ret = wait_event_timeout(
4406 this_adm.copp.adm_delay_wait[port_idx][copp_idx],
4407 atomic_read(&this_adm.copp.adm_delay_stat[port_idx][copp_idx]),
4408 msecs_to_jiffies(wait_time));
4409 pr_debug("%s: return %d\n", __func__, ret);
4410 if (ret != 0)
4411 ret = -EINTR;
4412end:
4413 pr_debug("%s: return %d--\n", __func__, ret);
4414 return ret;
4415}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304416EXPORT_SYMBOL(adm_wait_timeout);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304417
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304418/**
4419 * adm_store_cal_data -
4420 * Retrieve calibration data for ADM copp device
4421 *
4422 * @port_id: Port ID number
4423 * @copp_idx: copp index assigned
4424 * @path: direction or copp type
4425 * @perf_mode: performance mode like LL/ULL/..
4426 * @cal_index: calibration index to use
4427 * @params: pointer to store cal data
4428 * @size: pointer to fill with cal size
4429 *
4430 * Returns 0 on success or error on failure
4431 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304432int adm_store_cal_data(int port_id, int copp_idx, int path, int perf_mode,
4433 int cal_index, char *params, int *size)
4434{
4435 int rc = 0;
4436 struct cal_block_data *cal_block = NULL;
4437 int app_type, acdb_id, port_idx, sample_rate;
4438
4439 if (this_adm.cal_data[cal_index] == NULL) {
4440 pr_debug("%s: cal_index %d not allocated!\n",
4441 __func__, cal_index);
4442 goto end;
4443 }
4444
4445 if (get_cal_path(path) != RX_DEVICE) {
4446 pr_debug("%s: Invalid path to store calibration %d\n",
4447 __func__, path);
4448 rc = -EINVAL;
4449 goto end;
4450 }
4451
4452 port_id = afe_convert_virtual_to_portid(port_id);
4453 port_idx = adm_validate_and_get_port_index(port_id);
4454 if (port_idx < 0) {
4455 pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
4456 rc = -EINVAL;
4457 goto end;
4458 }
4459
4460 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4461 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4462 return -EINVAL;
4463 }
4464
4465 acdb_id = atomic_read(&this_adm.copp.acdb_id[port_idx][copp_idx]);
4466 app_type = atomic_read(&this_adm.copp.app_type[port_idx][copp_idx]);
4467 sample_rate = atomic_read(&this_adm.copp.rate[port_idx][copp_idx]);
4468
4469 mutex_lock(&this_adm.cal_data[cal_index]->lock);
4470 cal_block = adm_find_cal(cal_index, get_cal_path(path), app_type,
4471 acdb_id, sample_rate);
4472 if (cal_block == NULL)
4473 goto unlock;
4474
4475 if (cal_block->cal_data.size <= 0) {
4476 pr_debug("%s: No ADM cal send for port_id = 0x%x!\n",
4477 __func__, port_id);
4478 rc = -EINVAL;
4479 goto unlock;
4480 }
4481
Aditya Bavanari2a627ae2017-11-21 20:24:53 +05304482 if (cal_index == ADM_AUDPROC_CAL || cal_index == ADM_LSM_AUDPROC_CAL) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304483 if (cal_block->cal_data.size > AUD_PROC_BLOCK_SIZE) {
4484 pr_err("%s:audproc:invalid size exp/actual[%zd, %d]\n",
4485 __func__, cal_block->cal_data.size, *size);
4486 rc = -ENOMEM;
4487 goto unlock;
4488 }
4489 } else if (cal_index == ADM_AUDVOL_CAL) {
4490 if (cal_block->cal_data.size > AUD_VOL_BLOCK_SIZE) {
4491 pr_err("%s:aud_vol:invalid size exp/actual[%zd, %d]\n",
4492 __func__, cal_block->cal_data.size, *size);
4493 rc = -ENOMEM;
4494 goto unlock;
4495 }
4496 } else {
4497 pr_debug("%s: Not valid calibration for dolby topolgy\n",
4498 __func__);
4499 rc = -EINVAL;
4500 goto unlock;
4501 }
4502 memcpy(params, cal_block->cal_data.kvaddr, cal_block->cal_data.size);
4503 *size = cal_block->cal_data.size;
4504
4505 pr_debug("%s:port_id %d, copp_idx %d, path %d",
4506 __func__, port_id, copp_idx, path);
4507 pr_debug("perf_mode %d, cal_type %d, size %d\n",
4508 perf_mode, cal_index, *size);
4509
4510unlock:
4511 mutex_unlock(&this_adm.cal_data[cal_index]->lock);
4512end:
4513 return rc;
4514}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304515EXPORT_SYMBOL(adm_store_cal_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304516
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304517/**
4518 * adm_send_compressed_device_mute -
4519 * command to send mute for compressed device
4520 *
4521 * @port_id: Port ID number
4522 * @copp_idx: copp index assigned
4523 * @mute_on: flag to indicate mute or unmute
4524 *
4525 * Returns 0 on success or error on failure
4526 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304527int adm_send_compressed_device_mute(int port_id, int copp_idx, bool mute_on)
4528{
4529 struct adm_set_compressed_device_mute mute_params;
4530 int ret = 0;
4531 int port_idx;
4532
4533 pr_debug("%s port_id: 0x%x, copp_idx %d, mute_on: %d\n",
4534 __func__, port_id, copp_idx, mute_on);
4535 port_id = afe_convert_virtual_to_portid(port_id);
4536 port_idx = adm_validate_and_get_port_index(port_id);
4537 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
4538 pr_err("%s: Invalid port_id %#x copp_idx %d\n",
4539 __func__, port_id, copp_idx);
4540 ret = -EINVAL;
4541 goto end;
4542 }
4543
4544 mute_params.command.hdr.hdr_field =
4545 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4546 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4547 mute_params.command.hdr.pkt_size =
4548 sizeof(struct adm_set_compressed_device_mute);
4549 mute_params.command.hdr.src_svc = APR_SVC_ADM;
4550 mute_params.command.hdr.src_domain = APR_DOMAIN_APPS;
4551 mute_params.command.hdr.src_port = port_id;
4552 mute_params.command.hdr.dest_svc = APR_SVC_ADM;
4553 mute_params.command.hdr.dest_domain = APR_DOMAIN_ADSP;
4554 mute_params.command.hdr.dest_port =
4555 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
4556 mute_params.command.hdr.token = port_idx << 16 | copp_idx;
4557 mute_params.command.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
4558 mute_params.command.payload_addr_lsw = 0;
4559 mute_params.command.payload_addr_msw = 0;
4560 mute_params.command.mem_map_handle = 0;
4561 mute_params.command.payload_size = sizeof(mute_params) -
4562 sizeof(mute_params.command);
4563 mute_params.params.module_id = AUDPROC_MODULE_ID_COMPRESSED_MUTE;
4564 mute_params.params.param_id = AUDPROC_PARAM_ID_COMPRESSED_MUTE;
4565 mute_params.params.param_size = mute_params.command.payload_size -
4566 sizeof(mute_params.params);
4567 mute_params.params.reserved = 0;
4568 mute_params.mute_on = mute_on;
4569
4570 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
4571 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&mute_params);
4572 if (ret < 0) {
4573 pr_err("%s: device mute for port %d copp %d failed, ret %d\n",
4574 __func__, port_id, copp_idx, ret);
4575 ret = -EINVAL;
4576 goto end;
4577 }
4578
4579 /* Wait for the callback */
4580 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
4581 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
4582 msecs_to_jiffies(TIMEOUT_MS));
4583 if (!ret) {
4584 pr_err("%s: send device mute for port %d copp %d failed\n",
4585 __func__, port_id, copp_idx);
4586 ret = -EINVAL;
4587 goto end;
4588 } else if (atomic_read(&this_adm.copp.stat
4589 [port_idx][copp_idx]) > 0) {
4590 pr_err("%s: DSP returned error[%s]\n",
4591 __func__, adsp_err_get_err_str(
4592 atomic_read(&this_adm.copp.stat
4593 [port_idx][copp_idx])));
4594 ret = adsp_err_get_lnx_err_code(
4595 atomic_read(&this_adm.copp.stat
4596 [port_idx][copp_idx]));
4597 goto end;
4598 }
4599 ret = 0;
4600end:
4601 return ret;
4602}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304603EXPORT_SYMBOL(adm_send_compressed_device_mute);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304604
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304605/**
4606 * adm_send_compressed_device_latency -
4607 * command to send latency for compressed device
4608 *
4609 * @port_id: Port ID number
4610 * @copp_idx: copp index assigned
4611 * @latency: latency value to pass
4612 *
4613 * Returns 0 on success or error on failure
4614 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304615int adm_send_compressed_device_latency(int port_id, int copp_idx, int latency)
4616{
4617 struct adm_set_compressed_device_latency latency_params;
4618 int port_idx;
4619 int ret = 0;
4620
4621 pr_debug("%s port_id: 0x%x, copp_idx %d latency: %d\n", __func__,
4622 port_id, copp_idx, latency);
4623 port_id = afe_convert_virtual_to_portid(port_id);
4624 port_idx = adm_validate_and_get_port_index(port_id);
4625 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
4626 pr_err("%s: Invalid port_id %#x copp_idx %d\n",
4627 __func__, port_id, copp_idx);
4628 ret = -EINVAL;
4629 goto end;
4630 }
4631
4632 latency_params.command.hdr.hdr_field =
4633 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4634 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4635 latency_params.command.hdr.pkt_size =
4636 sizeof(struct adm_set_compressed_device_latency);
4637 latency_params.command.hdr.src_svc = APR_SVC_ADM;
4638 latency_params.command.hdr.src_domain = APR_DOMAIN_APPS;
4639 latency_params.command.hdr.src_port = port_id;
4640 latency_params.command.hdr.dest_svc = APR_SVC_ADM;
4641 latency_params.command.hdr.dest_domain = APR_DOMAIN_ADSP;
4642 latency_params.command.hdr.dest_port =
4643 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
4644 latency_params.command.hdr.token = port_idx << 16 | copp_idx;
4645 latency_params.command.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
4646 latency_params.command.payload_addr_lsw = 0;
4647 latency_params.command.payload_addr_msw = 0;
4648 latency_params.command.mem_map_handle = 0;
4649 latency_params.command.payload_size = sizeof(latency_params) -
4650 sizeof(latency_params.command);
4651 latency_params.params.module_id = AUDPROC_MODULE_ID_COMPRESSED_LATENCY;
4652 latency_params.params.param_id = AUDPROC_PARAM_ID_COMPRESSED_LATENCY;
4653 latency_params.params.param_size = latency_params.command.payload_size -
4654 sizeof(latency_params.params);
4655 latency_params.params.reserved = 0;
4656 latency_params.latency = latency;
4657
4658 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
4659 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&latency_params);
4660 if (ret < 0) {
4661 pr_err("%s: send device latency err %d for port %d copp %d\n",
4662 __func__, port_id, copp_idx, ret);
4663 ret = -EINVAL;
4664 goto end;
4665 }
4666
4667 /* Wait for the callback */
4668 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
4669 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
4670 msecs_to_jiffies(TIMEOUT_MS));
4671 if (!ret) {
4672 pr_err("%s: send device latency for port %d failed\n", __func__,
4673 port_id);
4674 ret = -EINVAL;
4675 goto end;
4676 } else if (atomic_read(&this_adm.copp.stat
4677 [port_idx][copp_idx]) > 0) {
4678 pr_err("%s: DSP returned error[%s]\n",
4679 __func__, adsp_err_get_err_str(
4680 atomic_read(&this_adm.copp.stat
4681 [port_idx][copp_idx])));
4682 ret = adsp_err_get_lnx_err_code(
4683 atomic_read(&this_adm.copp.stat
4684 [port_idx][copp_idx]));
4685 goto end;
4686 }
4687 ret = 0;
4688end:
4689 return ret;
4690}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304691EXPORT_SYMBOL(adm_send_compressed_device_latency);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304692
4693/**
4694 * adm_swap_speaker_channels
4695 *
4696 * Receives port_id, copp_idx, sample rate, spk_swap and
4697 * send MFC command to swap speaker channel.
4698 * Return zero on success. On failure returns nonzero.
4699 *
4700 * port_id - Passed value, port_id for which channels swap is wanted
4701 * copp_idx - Passed value, copp_idx for which channels swap is wanted
4702 * sample_rate - Passed value, sample rate used by app type config
4703 * spk_swap - Passed value, spk_swap for check if swap flag is set
4704 */
4705int adm_swap_speaker_channels(int port_id, int copp_idx,
4706 int sample_rate, bool spk_swap)
4707{
4708 struct audproc_mfc_output_media_fmt mfc_cfg;
4709 uint16_t num_channels;
4710 int port_idx;
4711 int ret = 0;
4712
4713 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
4714 __func__, port_id, copp_idx);
4715 port_id = q6audio_convert_virtual_to_portid(port_id);
4716 port_idx = adm_validate_and_get_port_index(port_id);
4717 if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
4718 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4719 ret = -EINVAL;
4720 goto done;
4721 }
4722
4723 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4724 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4725 ret = -EINVAL;
4726 goto done;
4727 }
4728
4729 num_channels = atomic_read(
4730 &this_adm.copp.channels[port_idx][copp_idx]);
4731 if (num_channels != 2) {
4732 pr_debug("%s: Invalid number of channels: %d\n",
4733 __func__, num_channels);
4734 ret = -EINVAL;
4735 goto done;
4736 }
4737
4738 memset(&mfc_cfg, 0, sizeof(mfc_cfg));
4739 mfc_cfg.params.hdr.hdr_field =
4740 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4741 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
4742 mfc_cfg.params.hdr.pkt_size =
4743 sizeof(mfc_cfg);
4744 mfc_cfg.params.hdr.src_svc = APR_SVC_ADM;
4745 mfc_cfg.params.hdr.src_domain = APR_DOMAIN_APPS;
4746 mfc_cfg.params.hdr.src_port = port_id;
4747 mfc_cfg.params.hdr.dest_svc = APR_SVC_ADM;
4748 mfc_cfg.params.hdr.dest_domain = APR_DOMAIN_ADSP;
4749 mfc_cfg.params.hdr.dest_port =
4750 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
4751 mfc_cfg.params.hdr.token = port_idx << 16 | copp_idx;
4752 mfc_cfg.params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
4753 mfc_cfg.params.payload_addr_lsw = 0;
4754 mfc_cfg.params.payload_addr_msw = 0;
4755 mfc_cfg.params.mem_map_handle = 0;
4756 mfc_cfg.params.payload_size = sizeof(mfc_cfg) -
4757 sizeof(mfc_cfg.params);
4758 mfc_cfg.data.module_id = AUDPROC_MODULE_ID_MFC;
4759 mfc_cfg.data.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
4760 mfc_cfg.data.param_size = mfc_cfg.params.payload_size -
4761 sizeof(mfc_cfg.data);
4762 mfc_cfg.data.reserved = 0;
4763 mfc_cfg.sampling_rate = sample_rate;
4764 mfc_cfg.bits_per_sample =
4765 atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
4766 mfc_cfg.num_channels = num_channels;
4767
4768 /* Currently applying speaker swap for only 2 channel use case */
4769 if (spk_swap) {
4770 mfc_cfg.channel_type[0] =
4771 (uint16_t) PCM_CHANNEL_FR;
4772 mfc_cfg.channel_type[1] =
4773 (uint16_t) PCM_CHANNEL_FL;
4774 } else {
4775 mfc_cfg.channel_type[0] =
4776 (uint16_t) PCM_CHANNEL_FL;
4777 mfc_cfg.channel_type[1] =
4778 (uint16_t) PCM_CHANNEL_FR;
4779 }
4780
4781 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
4782 pr_debug("%s: mfc config: port_idx %d copp_idx %d copp SR %d copp BW %d copp chan %d\n",
4783 __func__, port_idx, copp_idx, mfc_cfg.sampling_rate,
4784 mfc_cfg.bits_per_sample, mfc_cfg.num_channels);
4785
4786 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&mfc_cfg);
4787 if (ret < 0) {
4788 pr_err("%s: port_id: for[0x%x] failed %d\n",
4789 __func__, port_id, ret);
4790 goto done;
4791 }
4792 /* Wait for the callback with copp id */
4793 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
4794 atomic_read(&this_adm.copp.stat
4795 [port_idx][copp_idx]) >= 0,
4796 msecs_to_jiffies(TIMEOUT_MS));
4797 if (!ret) {
4798 pr_err("%s: mfc_cfg Set params timed out for port_id: for [0x%x]\n",
4799 __func__, port_id);
4800 ret = -ETIMEDOUT;
4801 goto done;
4802 }
4803
4804 if (atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) > 0) {
4805 pr_err("%s: DSP returned error[%s]\n",
4806 __func__, adsp_err_get_err_str(
4807 atomic_read(&this_adm.copp.stat
4808 [port_idx][copp_idx])));
4809 ret = adsp_err_get_lnx_err_code(
4810 atomic_read(&this_adm.copp.stat
4811 [port_idx][copp_idx]));
4812 goto done;
4813 }
4814
4815 pr_debug("%s: mfc_cfg Set params returned success", __func__);
4816 ret = 0;
4817
4818done:
4819 return ret;
4820}
4821EXPORT_SYMBOL(adm_swap_speaker_channels);
4822
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304823/**
4824 * adm_set_sound_focus -
4825 * Update sound focus info
4826 *
4827 * @port_id: Port ID number
4828 * @copp_idx: copp index assigned
4829 * @soundFocusData: sound focus data to pass
4830 *
4831 * Returns 0 on success or error on failure
4832 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304833int adm_set_sound_focus(int port_id, int copp_idx,
4834 struct sound_focus_param soundFocusData)
4835{
4836 struct adm_set_fluence_soundfocus_param soundfocus_params;
4837 int sz = 0;
4838 int ret = 0;
4839 int port_idx;
4840 int i;
4841
4842 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
4843 __func__, port_id, copp_idx);
4844
4845 port_id = afe_convert_virtual_to_portid(port_id);
4846 port_idx = adm_validate_and_get_port_index(port_id);
4847 if (port_idx < 0) {
4848 pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
4849
4850 ret = -EINVAL;
4851 goto done;
4852 }
4853
4854 if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
4855 pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
4856
4857 ret = -EINVAL;
4858 goto done;
4859 }
4860
4861 sz = sizeof(struct adm_set_fluence_soundfocus_param);
4862 soundfocus_params.params.hdr.hdr_field =
4863 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
4864 APR_PKT_VER);
4865 soundfocus_params.params.hdr.pkt_size = sz;
4866 soundfocus_params.params.hdr.src_svc = APR_SVC_ADM;
4867 soundfocus_params.params.hdr.src_domain = APR_DOMAIN_APPS;
4868 soundfocus_params.params.hdr.src_port = port_id;
4869 soundfocus_params.params.hdr.dest_svc = APR_SVC_ADM;
4870 soundfocus_params.params.hdr.dest_domain = APR_DOMAIN_ADSP;
4871 soundfocus_params.params.hdr.dest_port =
4872 atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
4873 soundfocus_params.params.hdr.token = port_idx << 16 |
4874 ADM_CLIENT_ID_SOURCE_TRACKING << 8 | copp_idx;
4875 soundfocus_params.params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
4876 soundfocus_params.params.payload_addr_lsw = 0;
4877 soundfocus_params.params.payload_addr_msw = 0;
4878 soundfocus_params.params.mem_map_handle = 0;
4879 soundfocus_params.params.payload_size = sizeof(soundfocus_params) -
4880 sizeof(soundfocus_params.params);
4881 soundfocus_params.data.module_id = VOICEPROC_MODULE_ID_GENERIC_TX;
4882 soundfocus_params.data.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS;
4883 soundfocus_params.data.param_size =
4884 soundfocus_params.params.payload_size -
4885 sizeof(soundfocus_params.data);
4886 soundfocus_params.data.reserved = 0;
4887
4888 memset(&(soundfocus_params.soundfocus_data), 0xFF,
4889 sizeof(struct adm_param_fluence_soundfocus_t));
4890 for (i = 0; i < MAX_SECTORS; i++) {
4891 soundfocus_params.soundfocus_data.start_angles[i] =
4892 soundFocusData.start_angle[i];
4893 soundfocus_params.soundfocus_data.enables[i] =
4894 soundFocusData.enable[i];
4895 pr_debug("%s: start_angle[%d] = %d\n",
4896 __func__, i, soundFocusData.start_angle[i]);
4897 pr_debug("%s: enable[%d] = %d\n",
4898 __func__, i, soundFocusData.enable[i]);
4899 }
4900 soundfocus_params.soundfocus_data.gain_step =
4901 soundFocusData.gain_step;
4902 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData.gain_step);
4903
4904 soundfocus_params.soundfocus_data.reserved = 0;
4905
4906 atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
4907 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&soundfocus_params);
4908 if (ret < 0) {
4909 pr_err("%s: Set params failed\n", __func__);
4910
4911 ret = -EINVAL;
4912 goto done;
4913 }
4914 /* Wait for the callback */
4915 ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
4916 atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
4917 msecs_to_jiffies(TIMEOUT_MS));
4918 if (!ret) {
4919 pr_err("%s: Set params timed out\n", __func__);
4920
4921 ret = -EINVAL;
4922 goto done;
4923 }
4924
4925 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
4926 pr_err("%s - set params returned error [%s]\n",
4927 __func__, adsp_err_get_err_str(
4928 this_adm.sourceTrackingData.apr_cmd_status));
4929
4930 ret = adsp_err_get_lnx_err_code(
4931 this_adm.sourceTrackingData.apr_cmd_status);
4932 goto done;
4933 }
4934
4935 ret = 0;
4936
4937done:
4938 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
4939
4940 return ret;
4941}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304942EXPORT_SYMBOL(adm_set_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304943
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05304944/**
4945 * adm_get_sound_focus -
4946 * Retrieve sound focus info
4947 *
4948 * @port_id: Port ID number
4949 * @copp_idx: copp index assigned
4950 * @soundFocusData: pointer for sound focus data to be updated with
4951 *
4952 * Returns 0 on success or error on failure
4953 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304954int adm_get_sound_focus(int port_id, int copp_idx,
4955 struct sound_focus_param *soundFocusData)
4956{
4957 int ret = 0, i;
4958 char *params_value;
4959 uint32_t param_payload_len = sizeof(struct adm_param_data_v5) +
4960 sizeof(struct adm_param_fluence_soundfocus_t);
4961 struct adm_param_fluence_soundfocus_t *soundfocus_params;
4962
4963 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
4964 __func__, port_id, copp_idx);
4965
4966 params_value = kzalloc(param_payload_len, GFP_KERNEL);
4967 if (!params_value) {
4968 ret = -ENOMEM;
4969 goto done;
4970 }
4971 ret = adm_get_params_v2(port_id, copp_idx,
4972 VOICEPROC_MODULE_ID_GENERIC_TX,
4973 VOICEPROC_PARAM_ID_FLUENCE_SOUNDFOCUS,
4974 param_payload_len,
4975 params_value,
4976 ADM_CLIENT_ID_SOURCE_TRACKING);
4977 if (ret) {
4978 pr_err("%s: get parameters failed ret:%d\n", __func__, ret);
4979
4980 kfree(params_value);
4981 ret = -EINVAL;
4982 goto done;
4983 }
4984
4985 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
4986 pr_err("%s - get params returned error [%s]\n",
4987 __func__, adsp_err_get_err_str(
4988 this_adm.sourceTrackingData.apr_cmd_status));
4989
4990 kfree(params_value);
4991 ret = adsp_err_get_lnx_err_code(
4992 this_adm.sourceTrackingData.apr_cmd_status);
4993 goto done;
4994 }
4995
4996 soundfocus_params = (struct adm_param_fluence_soundfocus_t *)
4997 params_value;
4998 for (i = 0; i < MAX_SECTORS; i++) {
4999 soundFocusData->start_angle[i] =
5000 soundfocus_params->start_angles[i];
5001 soundFocusData->enable[i] = soundfocus_params->enables[i];
5002 pr_debug("%s: start_angle[%d] = %d\n",
5003 __func__, i, soundFocusData->start_angle[i]);
5004 pr_debug("%s: enable[%d] = %d\n",
5005 __func__, i, soundFocusData->enable[i]);
5006 }
5007 soundFocusData->gain_step = soundfocus_params->gain_step;
5008 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData->gain_step);
5009
5010 kfree(params_value);
5011
5012done:
5013 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5014
5015 return ret;
5016}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305017EXPORT_SYMBOL(adm_get_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305018
5019static int adm_source_tracking_alloc_map_memory(void)
5020{
5021 int ret;
5022
5023 pr_debug("%s: Enter\n", __func__);
5024
Banajit Goswami08bb7362017-11-03 22:48:23 -07005025 ret = msm_audio_ion_alloc(&this_adm.sourceTrackingData.dma_buf,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305026 AUD_PROC_BLOCK_SIZE,
5027 &this_adm.sourceTrackingData.memmap.paddr,
5028 &this_adm.sourceTrackingData.memmap.size,
5029 &this_adm.sourceTrackingData.memmap.kvaddr);
5030 if (ret) {
5031 pr_err("%s: failed to allocate memory\n", __func__);
5032
5033 ret = -EINVAL;
5034 goto done;
5035 }
5036
5037 atomic_set(&this_adm.mem_map_index, ADM_MEM_MAP_INDEX_SOURCE_TRACKING);
5038 ret = adm_memory_map_regions(&this_adm.sourceTrackingData.memmap.paddr,
5039 0,
5040 (uint32_t *)&this_adm.sourceTrackingData.memmap.size,
5041 1);
5042 if (ret < 0) {
5043 pr_err("%s: failed to map memory, paddr = 0x%pK, size = %d\n",
5044 __func__,
5045 (void *)this_adm.sourceTrackingData.memmap.paddr,
5046 (uint32_t)this_adm.sourceTrackingData.memmap.size);
5047
Banajit Goswami08bb7362017-11-03 22:48:23 -07005048 msm_audio_ion_free(this_adm.sourceTrackingData.dma_buf);
5049 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305050 this_adm.sourceTrackingData.memmap.size = 0;
5051 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5052 this_adm.sourceTrackingData.memmap.paddr = 0;
5053 this_adm.sourceTrackingData.apr_cmd_status = -1;
5054 atomic_set(&this_adm.mem_map_handles
5055 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
5056
5057 ret = -EINVAL;
5058 goto done;
5059 }
5060 ret = 0;
5061 pr_debug("%s: paddr = 0x%pK, size = %d, mem_map_handle = 0x%x\n",
5062 __func__, (void *)this_adm.sourceTrackingData.memmap.paddr,
5063 (uint32_t)this_adm.sourceTrackingData.memmap.size,
5064 atomic_read(&this_adm.mem_map_handles
5065 [ADM_MEM_MAP_INDEX_SOURCE_TRACKING]));
5066
5067done:
5068 pr_debug("%s: Exit, ret = %d\n", __func__, ret);
5069
5070 return ret;
5071}
5072
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305073/**
5074 * adm_get_source_tracking -
5075 * Retrieve source tracking info
5076 *
5077 * @port_id: Port ID number
5078 * @copp_idx: copp index assigned
5079 * @sourceTrackingData: pointer for source track data to be updated with
5080 *
5081 * Returns 0 on success or error on failure
5082 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305083int adm_get_source_tracking(int port_id, int copp_idx,
5084 struct source_tracking_param *sourceTrackingData)
5085{
5086 struct adm_cmd_get_pp_params_v5 admp;
5087 int p_idx, ret = 0, i;
5088 struct adm_param_fluence_sourcetracking_t *source_tracking_params;
5089
5090 pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
5091 __func__, port_id, copp_idx);
5092
5093 if (!this_adm.sourceTrackingData.memmap.paddr) {
5094 /* Allocate and map shared memory for out of band usage */
5095 ret = adm_source_tracking_alloc_map_memory();
5096 if (ret != 0) {
5097 ret = -EINVAL;
5098 goto done;
5099 }
5100 }
5101
5102 port_id = afe_convert_virtual_to_portid(port_id);
5103 p_idx = adm_validate_and_get_port_index(port_id);
5104 if (p_idx < 0) {
5105 pr_err("%s - invalid port index %i, port id %i, copp idx %i\n",
5106 __func__, p_idx, port_id, copp_idx);
5107
5108 ret = -EINVAL;
5109 goto done;
5110 }
5111
5112 admp.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5113 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5114 admp.hdr.pkt_size = sizeof(admp);
5115 admp.hdr.src_svc = APR_SVC_ADM;
5116 admp.hdr.src_domain = APR_DOMAIN_APPS;
5117 admp.hdr.src_port = port_id;
5118 admp.hdr.dest_svc = APR_SVC_ADM;
5119 admp.hdr.dest_domain = APR_DOMAIN_ADSP;
5120 admp.hdr.dest_port = atomic_read(&this_adm.copp.id[p_idx][copp_idx]);
5121 admp.hdr.token = p_idx << 16 | ADM_CLIENT_ID_SOURCE_TRACKING << 8 |
5122 copp_idx;
5123 admp.hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
5124 admp.data_payload_addr_lsw =
5125 lower_32_bits(this_adm.sourceTrackingData.memmap.paddr);
5126 admp.data_payload_addr_msw =
5127 msm_audio_populate_upper_32_bits(
5128 this_adm.sourceTrackingData.memmap.paddr);
5129 admp.mem_map_handle = atomic_read(&this_adm.mem_map_handles[
5130 ADM_MEM_MAP_INDEX_SOURCE_TRACKING]);
5131 admp.module_id = VOICEPROC_MODULE_ID_GENERIC_TX;
5132 admp.param_id = VOICEPROC_PARAM_ID_FLUENCE_SOURCETRACKING;
5133 admp.param_max_size = sizeof(struct adm_param_fluence_sourcetracking_t)
5134 + sizeof(struct adm_param_data_v5);
5135 admp.reserved = 0;
5136
5137 atomic_set(&this_adm.copp.stat[p_idx][copp_idx], -1);
5138
5139 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&admp);
5140 if (ret < 0) {
5141 pr_err("%s - failed to get Source Tracking Params\n",
5142 __func__);
5143
5144 ret = -EINVAL;
5145 goto done;
5146 }
5147 ret = wait_event_timeout(this_adm.copp.wait[p_idx][copp_idx],
5148 atomic_read(&this_adm.copp.stat[p_idx][copp_idx]) >= 0,
5149 msecs_to_jiffies(TIMEOUT_MS));
5150 if (!ret) {
5151 pr_err("%s - get params timed out\n", __func__);
5152
5153 ret = -EINVAL;
5154 goto done;
5155 } else if (atomic_read(&this_adm.copp.stat
5156 [p_idx][copp_idx]) > 0) {
5157 pr_err("%s: DSP returned error[%s]\n",
5158 __func__, adsp_err_get_err_str(
5159 atomic_read(&this_adm.copp.stat
5160 [p_idx][copp_idx])));
5161 ret = adsp_err_get_lnx_err_code(
5162 atomic_read(&this_adm.copp.stat
5163 [p_idx][copp_idx]));
5164 goto done;
5165 }
5166
5167 if (this_adm.sourceTrackingData.apr_cmd_status != 0) {
5168 pr_err("%s - get params returned error [%s]\n",
5169 __func__, adsp_err_get_err_str(
5170 this_adm.sourceTrackingData.apr_cmd_status));
5171
5172 ret = adsp_err_get_lnx_err_code(
5173 this_adm.sourceTrackingData.apr_cmd_status);
5174 goto done;
5175 }
5176
5177 source_tracking_params = (struct adm_param_fluence_sourcetracking_t *)
5178 (this_adm.sourceTrackingData.memmap.kvaddr +
5179 sizeof(struct adm_param_data_v5));
5180 for (i = 0; i < MAX_SECTORS; i++) {
5181 sourceTrackingData->vad[i] = source_tracking_params->vad[i];
5182 pr_debug("%s: vad[%d] = %d\n",
5183 __func__, i, sourceTrackingData->vad[i]);
5184 }
5185 sourceTrackingData->doa_speech = source_tracking_params->doa_speech;
5186 pr_debug("%s: doa_speech = %d\n",
5187 __func__, sourceTrackingData->doa_speech);
5188
5189 for (i = 0; i < MAX_NOISE_SOURCE_INDICATORS; i++) {
5190 sourceTrackingData->doa_noise[i] =
5191 source_tracking_params->doa_noise[i];
5192 pr_debug("%s: doa_noise[%d] = %d\n",
5193 __func__, i, sourceTrackingData->doa_noise[i]);
5194 }
5195 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
5196 sourceTrackingData->polar_activity[i] =
5197 source_tracking_params->polar_activity[i];
5198 pr_debug("%s: polar_activity[%d] = %d\n",
5199 __func__, i, sourceTrackingData->polar_activity[i]);
5200 }
5201
5202 ret = 0;
5203
5204done:
5205 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
5206
5207 return ret;
5208}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305209EXPORT_SYMBOL(adm_get_source_tracking);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305210
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305211int __init adm_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305212{
5213 int i = 0, j;
5214
5215 this_adm.apr = NULL;
5216 this_adm.ec_ref_rx = -1;
5217 this_adm.num_ec_ref_rx_chans = 0;
5218 this_adm.ec_ref_rx_bit_width = 0;
5219 this_adm.ec_ref_rx_sampling_rate = 0;
5220 atomic_set(&this_adm.matrix_map_stat, 0);
5221 init_waitqueue_head(&this_adm.matrix_map_wait);
5222 atomic_set(&this_adm.adm_stat, 0);
5223 init_waitqueue_head(&this_adm.adm_wait);
5224
5225 for (i = 0; i < AFE_MAX_PORTS; i++) {
5226 for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
5227 atomic_set(&this_adm.copp.id[i][j], RESET_COPP_ID);
5228 atomic_set(&this_adm.copp.cnt[i][j], 0);
5229 atomic_set(&this_adm.copp.topology[i][j], 0);
5230 atomic_set(&this_adm.copp.mode[i][j], 0);
5231 atomic_set(&this_adm.copp.stat[i][j], 0);
5232 atomic_set(&this_adm.copp.rate[i][j], 0);
5233 atomic_set(&this_adm.copp.channels[i][j], 0);
5234 atomic_set(&this_adm.copp.bit_width[i][j], 0);
5235 atomic_set(&this_adm.copp.app_type[i][j], 0);
5236 atomic_set(&this_adm.copp.acdb_id[i][j], 0);
5237 init_waitqueue_head(&this_adm.copp.wait[i][j]);
5238 atomic_set(&this_adm.copp.adm_delay_stat[i][j], 0);
5239 init_waitqueue_head(
5240 &this_adm.copp.adm_delay_wait[i][j]);
5241 atomic_set(&this_adm.copp.topology[i][j], 0);
5242 this_adm.copp.adm_delay[i][j] = 0;
5243 this_adm.copp.adm_status[i][j] =
5244 ADM_STATUS_CALIBRATION_REQUIRED;
5245 }
5246 }
5247
5248 if (adm_init_cal_data())
5249 pr_err("%s: could not init cal data!\n", __func__);
5250
Banajit Goswami08bb7362017-11-03 22:48:23 -07005251 this_adm.sourceTrackingData.dma_buf = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305252 this_adm.sourceTrackingData.memmap.size = 0;
5253 this_adm.sourceTrackingData.memmap.kvaddr = NULL;
5254 this_adm.sourceTrackingData.memmap.paddr = 0;
5255 this_adm.sourceTrackingData.apr_cmd_status = -1;
5256 atomic_set(&this_adm.mem_map_handles[ADM_MEM_MAP_INDEX_SOURCE_TRACKING],
5257 0);
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305258 mutex_init(&dts_srs_lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305259
5260 return 0;
5261}
5262
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05305263void adm_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305264{
Laxminath Kasam30ad7512017-11-28 12:40:22 +05305265 if (this_adm.apr)
5266 adm_reset_data();
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305267 mutex_destroy(&dts_srs_lock);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305268 adm_delete_cal_data();
5269}