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