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