blob: f989a97e265386f570a769345faff6991ea31393 [file] [log] [blame]
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07001/* Copyright (c) 2014-2019, 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 */
13#include <linux/slab.h>
14#include <linux/fs.h>
15#include <linux/module.h>
16#include <linux/miscdevice.h>
17#include <linux/uaccess.h>
18#include <linux/mutex.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053019#include <dsp/audio_cal_utils.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053020
21static int unmap_memory(struct cal_type_data *cal_type,
22 struct cal_block_data *cal_block);
23
24size_t get_cal_info_size(int32_t cal_type)
25{
26 size_t size = 0;
27
28 switch (cal_type) {
29 case CVP_VOC_RX_TOPOLOGY_CAL_TYPE:
30 size = sizeof(struct audio_cal_info_voc_top);
31 break;
32 case CVP_VOC_TX_TOPOLOGY_CAL_TYPE:
33 size = sizeof(struct audio_cal_info_voc_top);
34 break;
35 case CVP_VOCPROC_STATIC_CAL_TYPE:
36 size = sizeof(struct audio_cal_info_vocproc);
37 break;
38 case CVP_VOCPROC_DYNAMIC_CAL_TYPE:
39 size = sizeof(struct audio_cal_info_vocvol);
40 break;
41 case CVS_VOCSTRM_STATIC_CAL_TYPE:
42 size = 0;
43 break;
44 case CVP_VOCDEV_CFG_CAL_TYPE:
45 size = sizeof(struct audio_cal_info_vocdev_cfg);
46 break;
47 case CVP_VOCPROC_STATIC_COL_CAL_TYPE:
48 size = sizeof(struct audio_cal_info_voc_col);
49 break;
50 case CVP_VOCPROC_DYNAMIC_COL_CAL_TYPE:
51 size = sizeof(struct audio_cal_info_voc_col);
52 break;
53 case CVS_VOCSTRM_STATIC_COL_CAL_TYPE:
54 size = sizeof(struct audio_cal_info_voc_col);
55 break;
56 case ADM_TOPOLOGY_CAL_TYPE:
Aditya Bavanari2a627ae2017-11-21 20:24:53 +053057 case ADM_LSM_TOPOLOGY_CAL_TYPE:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053058 size = sizeof(struct audio_cal_info_adm_top);
59 break;
60 case ADM_CUST_TOPOLOGY_CAL_TYPE:
61 case CORE_CUSTOM_TOPOLOGIES_CAL_TYPE:
62 size = 0;
63 break;
64 case ADM_AUDPROC_CAL_TYPE:
Aditya Bavanari2a627ae2017-11-21 20:24:53 +053065 case ADM_LSM_AUDPROC_CAL_TYPE:
Bhalchandra Gajareface2762018-05-10 14:16:49 -070066 case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053067 size = sizeof(struct audio_cal_info_audproc);
68 break;
69 case ADM_AUDVOL_CAL_TYPE:
70 case ADM_RTAC_AUDVOL_CAL_TYPE:
71 size = sizeof(struct audio_cal_info_audvol);
72 break;
73 case ASM_TOPOLOGY_CAL_TYPE:
74 size = sizeof(struct audio_cal_info_asm_top);
75 break;
76 case ASM_CUST_TOPOLOGY_CAL_TYPE:
77 size = 0;
78 break;
79 case ASM_AUDSTRM_CAL_TYPE:
80 size = sizeof(struct audio_cal_info_audstrm);
81 break;
82 case AFE_TOPOLOGY_CAL_TYPE:
Aditya Bavanari3889b4a2017-11-21 19:52:26 +053083 case AFE_LSM_TOPOLOGY_CAL_TYPE:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053084 size = sizeof(struct audio_cal_info_afe_top);
85 break;
86 case AFE_CUST_TOPOLOGY_CAL_TYPE:
87 size = 0;
88 break;
89 case AFE_COMMON_RX_CAL_TYPE:
90 size = sizeof(struct audio_cal_info_afe);
91 break;
92 case AFE_COMMON_TX_CAL_TYPE:
Aditya Bavanari3889b4a2017-11-21 19:52:26 +053093 case AFE_LSM_TX_CAL_TYPE:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053094 size = sizeof(struct audio_cal_info_afe);
95 break;
96 case AFE_FB_SPKR_PROT_CAL_TYPE:
97 size = sizeof(struct audio_cal_info_spk_prot_cfg);
98 break;
99 case AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE:
100 /*
101 * Since get and set parameter structures are different in size
102 * use the maximum size of get and set parameter structure
103 */
104 size = max(sizeof(struct audio_cal_info_sp_th_vi_ftm_cfg),
105 sizeof(struct audio_cal_info_sp_th_vi_param));
106 break;
107 case AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE:
108 /*
109 * Since get and set parameter structures are different in size
110 * use the maximum size of get and set parameter structure
111 */
112 size = max(sizeof(struct audio_cal_info_sp_ex_vi_ftm_cfg),
113 sizeof(struct audio_cal_info_sp_ex_vi_param));
114 break;
115 case AFE_ANC_CAL_TYPE:
116 size = 0;
117 break;
118 case AFE_AANC_CAL_TYPE:
119 size = sizeof(struct audio_cal_info_aanc);
120 break;
121 case AFE_HW_DELAY_CAL_TYPE:
122 size = sizeof(struct audio_cal_info_hw_delay);
123 break;
124 case AFE_SIDETONE_CAL_TYPE:
125 size = sizeof(struct audio_cal_info_sidetone);
126 break;
127 case AFE_SIDETONE_IIR_CAL_TYPE:
128 size = sizeof(struct audio_cal_info_sidetone_iir);
129 break;
130 case LSM_CUST_TOPOLOGY_CAL_TYPE:
131 size = 0;
132 break;
133 case LSM_TOPOLOGY_CAL_TYPE:
134 size = sizeof(struct audio_cal_info_lsm_top);
135 break;
136 case ULP_LSM_TOPOLOGY_ID_CAL_TYPE:
137 size = sizeof(struct audio_cal_info_lsm_top);
138 break;
139 case LSM_CAL_TYPE:
140 size = sizeof(struct audio_cal_info_lsm);
141 break;
142 case ADM_RTAC_INFO_CAL_TYPE:
143 size = 0;
144 break;
145 case VOICE_RTAC_INFO_CAL_TYPE:
146 size = 0;
147 break;
148 case ADM_RTAC_APR_CAL_TYPE:
149 size = 0;
150 break;
151 case ASM_RTAC_APR_CAL_TYPE:
152 size = 0;
153 break;
154 case VOICE_RTAC_APR_CAL_TYPE:
155 size = 0;
156 break;
157 case MAD_CAL_TYPE:
158 size = 0;
159 break;
160 case ULP_AFE_CAL_TYPE:
161 size = sizeof(struct audio_cal_info_afe);
162 break;
163 case ULP_LSM_CAL_TYPE:
164 size = sizeof(struct audio_cal_info_lsm);
165 break;
166 case AUDIO_CORE_METAINFO_CAL_TYPE:
167 size = sizeof(struct audio_cal_info_metainfo);
168 break;
169 case SRS_TRUMEDIA_CAL_TYPE:
170 size = 0;
171 break;
172 default:
173 pr_err("%s:Invalid cal type %d!",
174 __func__, cal_type);
175 }
176 return size;
177}
178
179size_t get_user_cal_type_size(int32_t cal_type)
180{
181 size_t size = 0;
182
183 switch (cal_type) {
184 case CVP_VOC_RX_TOPOLOGY_CAL_TYPE:
185 size = sizeof(struct audio_cal_type_voc_top);
186 break;
187 case CVP_VOC_TX_TOPOLOGY_CAL_TYPE:
188 size = sizeof(struct audio_cal_type_voc_top);
189 break;
190 case CVP_VOCPROC_STATIC_CAL_TYPE:
191 size = sizeof(struct audio_cal_type_vocproc);
192 break;
193 case CVP_VOCPROC_DYNAMIC_CAL_TYPE:
194 size = sizeof(struct audio_cal_type_vocvol);
195 break;
196 case CVS_VOCSTRM_STATIC_CAL_TYPE:
197 size = sizeof(struct audio_cal_type_basic);
198 break;
199 case CVP_VOCDEV_CFG_CAL_TYPE:
200 size = sizeof(struct audio_cal_type_vocdev_cfg);
201 break;
202 case CVP_VOCPROC_STATIC_COL_CAL_TYPE:
203 case CVP_VOCPROC_DYNAMIC_COL_CAL_TYPE:
204 case CVS_VOCSTRM_STATIC_COL_CAL_TYPE:
205 size = sizeof(struct audio_cal_type_voc_col);
206 break;
207 case ADM_TOPOLOGY_CAL_TYPE:
Aditya Bavanari2a627ae2017-11-21 20:24:53 +0530208 case ADM_LSM_TOPOLOGY_CAL_TYPE:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530209 size = sizeof(struct audio_cal_type_adm_top);
210 break;
211 case ADM_CUST_TOPOLOGY_CAL_TYPE:
212 case CORE_CUSTOM_TOPOLOGIES_CAL_TYPE:
213 size = sizeof(struct audio_cal_type_basic);
214 break;
215 case ADM_AUDPROC_CAL_TYPE:
Aditya Bavanari2a627ae2017-11-21 20:24:53 +0530216 case ADM_LSM_AUDPROC_CAL_TYPE:
Bhalchandra Gajareface2762018-05-10 14:16:49 -0700217 case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530218 size = sizeof(struct audio_cal_type_audproc);
219 break;
220 case ADM_AUDVOL_CAL_TYPE:
221 case ADM_RTAC_AUDVOL_CAL_TYPE:
222 size = sizeof(struct audio_cal_type_audvol);
223 break;
224 case ASM_TOPOLOGY_CAL_TYPE:
225 size = sizeof(struct audio_cal_type_asm_top);
226 break;
227 case ASM_CUST_TOPOLOGY_CAL_TYPE:
228 size = sizeof(struct audio_cal_type_basic);
229 break;
230 case ASM_AUDSTRM_CAL_TYPE:
231 size = sizeof(struct audio_cal_type_audstrm);
232 break;
233 case AFE_TOPOLOGY_CAL_TYPE:
Aditya Bavanari3889b4a2017-11-21 19:52:26 +0530234 case AFE_LSM_TOPOLOGY_CAL_TYPE:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530235 size = sizeof(struct audio_cal_type_afe_top);
236 break;
237 case AFE_CUST_TOPOLOGY_CAL_TYPE:
238 size = sizeof(struct audio_cal_type_basic);
239 break;
240 case AFE_COMMON_RX_CAL_TYPE:
241 size = sizeof(struct audio_cal_type_afe);
242 break;
243 case AFE_COMMON_TX_CAL_TYPE:
Aditya Bavanari3889b4a2017-11-21 19:52:26 +0530244 case AFE_LSM_TX_CAL_TYPE:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530245 size = sizeof(struct audio_cal_type_afe);
246 break;
247 case AFE_FB_SPKR_PROT_CAL_TYPE:
248 size = sizeof(struct audio_cal_type_fb_spk_prot_cfg);
249 break;
250 case AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE:
251 /*
252 * Since get and set parameter structures are different in size
253 * use the maximum size of get and set parameter structure
254 */
255 size = max(sizeof(struct audio_cal_type_sp_th_vi_ftm_cfg),
256 sizeof(struct audio_cal_type_sp_th_vi_param));
257 break;
258 case AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE:
259 /*
260 * Since get and set parameter structures are different in size
261 * use the maximum size of get and set parameter structure
262 */
263 size = max(sizeof(struct audio_cal_type_sp_ex_vi_ftm_cfg),
264 sizeof(struct audio_cal_type_sp_ex_vi_param));
265 break;
266 case AFE_ANC_CAL_TYPE:
267 size = 0;
268 break;
269 case AFE_AANC_CAL_TYPE:
270 size = sizeof(struct audio_cal_type_aanc);
271 break;
272 case AFE_HW_DELAY_CAL_TYPE:
273 size = sizeof(struct audio_cal_type_hw_delay);
274 break;
275 case AFE_SIDETONE_CAL_TYPE:
276 size = sizeof(struct audio_cal_type_sidetone);
277 break;
278 case AFE_SIDETONE_IIR_CAL_TYPE:
279 size = sizeof(struct audio_cal_type_sidetone_iir);
280 break;
281 case LSM_CUST_TOPOLOGY_CAL_TYPE:
282 size = sizeof(struct audio_cal_type_basic);
283 break;
284 case LSM_TOPOLOGY_CAL_TYPE:
285 size = sizeof(struct audio_cal_type_lsm_top);
286 break;
287 case ULP_LSM_TOPOLOGY_ID_CAL_TYPE:
288 size = sizeof(struct audio_cal_type_lsm_top);
289 break;
290 case LSM_CAL_TYPE:
291 size = sizeof(struct audio_cal_type_lsm);
292 break;
293 case ADM_RTAC_INFO_CAL_TYPE:
294 size = 0;
295 break;
296 case VOICE_RTAC_INFO_CAL_TYPE:
297 size = 0;
298 break;
299 case ADM_RTAC_APR_CAL_TYPE:
300 size = 0;
301 break;
302 case ASM_RTAC_APR_CAL_TYPE:
303 size = 0;
304 break;
305 case VOICE_RTAC_APR_CAL_TYPE:
306 size = 0;
307 break;
308 case MAD_CAL_TYPE:
309 size = 0;
310 break;
311 case ULP_AFE_CAL_TYPE:
312 size = sizeof(struct audio_cal_type_afe);
313 break;
314 case ULP_LSM_CAL_TYPE:
315 size = sizeof(struct audio_cal_type_lsm);
316 break;
317 case AUDIO_CORE_METAINFO_CAL_TYPE:
318 size = sizeof(struct audio_cal_type_metainfo);
319 break;
320 case SRS_TRUMEDIA_CAL_TYPE:
321 size = 0;
322 break;
323 default:
324 pr_err("%s:Invalid cal type %d!",
325 __func__, cal_type);
326 }
327 return size;
328}
329
330int32_t cal_utils_get_cal_type_version(void *cal_type_data)
331{
332 struct audio_cal_type_basic *data = NULL;
333
334 data = (struct audio_cal_type_basic *)cal_type_data;
335
336 return data->cal_hdr.version;
337}
338
339static struct cal_type_data *create_cal_type_data(
340 struct cal_type_info *info)
341{
342 struct cal_type_data *cal_type = NULL;
343
344 if ((info->reg.cal_type < 0) ||
345 (info->reg.cal_type >= MAX_CAL_TYPES)) {
346 pr_err("%s: cal type %d is Invalid!\n",
347 __func__, info->reg.cal_type);
348 goto done;
349 }
350
351 if (info->cal_util_callbacks.match_block == NULL) {
352 pr_err("%s: cal type %d no method to match blocks!\n",
353 __func__, info->reg.cal_type);
354 goto done;
355 }
356
357 cal_type = kmalloc(sizeof(*cal_type), GFP_KERNEL);
358 if (cal_type == NULL)
359 goto done;
360
361 INIT_LIST_HEAD(&cal_type->cal_blocks);
362 mutex_init(&cal_type->lock);
363 memcpy(&cal_type->info, info,
364 sizeof(cal_type->info));
365done:
366 return cal_type;
367}
368
369/**
370 * cal_utils_create_cal_types
371 *
372 * @num_cal_types: number of types
373 * @cal_type: pointer to the cal types pointer
374 * @info: pointer to info
375 *
376 * Returns 0 on success, EINVAL otherwise
377 */
378int cal_utils_create_cal_types(int num_cal_types,
379 struct cal_type_data **cal_type,
380 struct cal_type_info *info)
381{
382 int ret = 0;
383 int i;
384
385 pr_debug("%s\n", __func__);
386
387 if (cal_type == NULL) {
388 pr_err("%s: cal_type is NULL!\n", __func__);
389 ret = -EINVAL;
390 goto done;
391 } else if (info == NULL) {
392 pr_err("%s: info is NULL!\n", __func__);
393 ret = -EINVAL;
394 goto done;
395 } else if ((num_cal_types <= 0) ||
396 (num_cal_types > MAX_CAL_TYPES)) {
397 pr_err("%s: num_cal_types of %d is Invalid!\n",
398 __func__, num_cal_types);
399 ret = -EINVAL;
400 goto done;
401 }
402
403 for (i = 0; i < num_cal_types; i++) {
404 if ((info[i].reg.cal_type < 0) ||
405 (info[i].reg.cal_type >= MAX_CAL_TYPES)) {
406 pr_err("%s: cal type %d at index %d is Invalid!\n",
407 __func__, info[i].reg.cal_type, i);
408 ret = -EINVAL;
409 goto done;
410 }
411
412 cal_type[i] = create_cal_type_data(&info[i]);
413 if (cal_type[i] == NULL) {
414 pr_err("%s: Could not allocate cal_type of index %d!\n",
415 __func__, i);
416 ret = -EINVAL;
417 goto done;
418 }
419
420 ret = audio_cal_register(1, &info[i].reg);
421 if (ret < 0) {
422 pr_err("%s: audio_cal_register failed, ret = %d!\n",
423 __func__, ret);
424 ret = -EINVAL;
425 goto done;
426 }
427 pr_debug("%s: cal type %d at index %d!\n",
428 __func__, info[i].reg.cal_type, i);
429 }
430done:
431 return ret;
432}
433EXPORT_SYMBOL(cal_utils_create_cal_types);
434
435static void delete_cal_block(struct cal_block_data *cal_block)
436{
437 pr_debug("%s\n", __func__);
438
439 if (cal_block == NULL)
440 goto done;
441
442 list_del(&cal_block->list);
443 kfree(cal_block->client_info);
444 cal_block->client_info = NULL;
445 kfree(cal_block->cal_info);
446 cal_block->cal_info = NULL;
447 if (cal_block->map_data.ion_client != NULL) {
448 msm_audio_ion_free(cal_block->map_data.ion_client,
449 cal_block->map_data.ion_handle);
450 cal_block->map_data.ion_client = NULL;
451 cal_block->map_data.ion_handle = NULL;
452 }
453 kfree(cal_block);
454done:
455 return;
456}
457
458static void destroy_all_cal_blocks(struct cal_type_data *cal_type)
459{
460 int ret = 0;
461 struct list_head *ptr, *next;
462 struct cal_block_data *cal_block;
463
464 list_for_each_safe(ptr, next,
465 &cal_type->cal_blocks) {
466
467 cal_block = list_entry(ptr,
468 struct cal_block_data, list);
469
470 ret = unmap_memory(cal_type, cal_block);
471 if (ret < 0) {
472 pr_err("%s: unmap_memory failed, cal type %d, ret = %d!\n",
473 __func__,
474 cal_type->info.reg.cal_type,
475 ret);
476 }
477 delete_cal_block(cal_block);
478 cal_block = NULL;
479 }
480}
481
482static void destroy_cal_type_data(struct cal_type_data *cal_type)
483{
484 if (cal_type == NULL)
485 goto done;
486
487 destroy_all_cal_blocks(cal_type);
488 list_del(&cal_type->cal_blocks);
489 kfree(cal_type);
490done:
491 return;
492}
493
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530494/**
495 * cal_utils_destroy_cal_types -
496 * Destroys cal types and deregister from cal info
497 *
498 * @num_cal_types: number of cal types
499 * @cal_type: cal type pointer with cal info
500 *
501 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530502void cal_utils_destroy_cal_types(int num_cal_types,
503 struct cal_type_data **cal_type)
504{
505 int i;
506
507 pr_debug("%s\n", __func__);
508
509 if (cal_type == NULL) {
510 pr_err("%s: cal_type is NULL!\n", __func__);
511 goto done;
512 } else if ((num_cal_types <= 0) ||
513 (num_cal_types > MAX_CAL_TYPES)) {
514 pr_err("%s: num_cal_types of %d is Invalid!\n",
515 __func__, num_cal_types);
516 goto done;
517 }
518
519 for (i = 0; i < num_cal_types; i++) {
520 audio_cal_deregister(1, &cal_type[i]->info.reg);
521 destroy_cal_type_data(cal_type[i]);
522 cal_type[i] = NULL;
523 }
524done:
525 return;
526}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530527EXPORT_SYMBOL(cal_utils_destroy_cal_types);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530528
529/**
530 * cal_utils_get_only_cal_block
531 *
532 * @cal_type: pointer to the cal type
533 *
534 * Returns cal_block structure
535 */
536struct cal_block_data *cal_utils_get_only_cal_block(
537 struct cal_type_data *cal_type)
538{
539 struct list_head *ptr, *next;
540 struct cal_block_data *cal_block = NULL;
541
542 if (cal_type == NULL)
543 goto done;
544
545 list_for_each_safe(ptr, next,
546 &cal_type->cal_blocks) {
547
548 cal_block = list_entry(ptr,
549 struct cal_block_data, list);
550 break;
551 }
552done:
553 return cal_block;
554}
555EXPORT_SYMBOL(cal_utils_get_only_cal_block);
556
557/**
558 * cal_utils_get_only_cal_block
559 *
560 * @cal_block: pointer to cal block struct
561 * @user_data: pointer to user data
562 *
563 * Returns true on match
564 */
565bool cal_utils_match_buf_num(struct cal_block_data *cal_block,
566 void *user_data)
567{
568 bool ret = false;
569 struct audio_cal_type_basic *data = user_data;
570
571 if (cal_block->buffer_number == data->cal_hdr.buffer_number)
572 ret = true;
573
574 return ret;
575}
576EXPORT_SYMBOL(cal_utils_match_buf_num);
577
578static struct cal_block_data *get_matching_cal_block(
579 struct cal_type_data *cal_type,
580 void *data)
581{
582 struct list_head *ptr, *next;
583 struct cal_block_data *cal_block = NULL;
584
585 list_for_each_safe(ptr, next,
586 &cal_type->cal_blocks) {
587
588 cal_block = list_entry(ptr,
589 struct cal_block_data, list);
590
591 if (cal_type->info.cal_util_callbacks.
592 match_block(cal_block, data))
593 return cal_block;
594 }
595
596 return NULL;
597}
598
599static int cal_block_ion_alloc(struct cal_block_data *cal_block)
600{
601 int ret = 0;
602
603 if (cal_block == NULL) {
604 pr_err("%s: cal_block is NULL!\n", __func__);
605 ret = -EINVAL;
606 goto done;
607 }
608
609 ret = msm_audio_ion_import("audio_cal_client",
610 &cal_block->map_data.ion_client,
611 &cal_block->map_data.ion_handle,
612 cal_block->map_data.ion_map_handle,
613 NULL, 0,
614 &cal_block->cal_data.paddr,
615 &cal_block->map_data.map_size,
616 &cal_block->cal_data.kvaddr);
617 if (ret) {
618 pr_err("%s: audio ION import failed, rc = %d\n",
619 __func__, ret);
620 ret = -ENOMEM;
621 goto done;
622 }
623done:
624 return ret;
625}
626
627static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type,
628 struct audio_cal_type_basic *basic_cal,
629 size_t client_info_size, void *client_info)
630{
631 struct cal_block_data *cal_block = NULL;
632
633 if (cal_type == NULL) {
634 pr_err("%s: cal_type is NULL!\n", __func__);
635 goto done;
636 } else if (basic_cal == NULL) {
637 pr_err("%s: basic_cal is NULL!\n", __func__);
638 goto done;
639 }
640
641 cal_block = kzalloc(sizeof(*cal_block),
642 GFP_KERNEL);
643 if (cal_block == NULL)
644 goto done;
645
646 INIT_LIST_HEAD(&cal_block->list);
647
648 cal_block->map_data.ion_map_handle = basic_cal->cal_data.mem_handle;
649 if (basic_cal->cal_data.mem_handle > 0) {
650 if (cal_block_ion_alloc(cal_block)) {
651 pr_err("%s: cal_block_ion_alloc failed!\n",
652 __func__);
653 goto err;
654 }
655 }
656 if (client_info_size > 0) {
657 cal_block->client_info_size = client_info_size;
658 cal_block->client_info = kmalloc(client_info_size, GFP_KERNEL);
659 if (cal_block->client_info == NULL) {
660 pr_err("%s: could not allocats client_info!\n",
661 __func__);
662 goto err;
663 }
664 if (client_info != NULL)
665 memcpy(cal_block->client_info, client_info,
666 client_info_size);
667 }
668
669 cal_block->cal_info = kzalloc(
670 get_cal_info_size(cal_type->info.reg.cal_type),
671 GFP_KERNEL);
672 if (cal_block->cal_info == NULL) {
673 pr_err("%s: could not allocats cal_info!\n",
674 __func__);
675 goto err;
676 }
677 cal_block->buffer_number = basic_cal->cal_hdr.buffer_number;
678 list_add_tail(&cal_block->list, &cal_type->cal_blocks);
679 pr_debug("%s: created block for cal type %d, buf num %d, map handle %d, map size %zd paddr 0x%pK!\n",
680 __func__, cal_type->info.reg.cal_type,
681 cal_block->buffer_number,
682 cal_block->map_data.ion_map_handle,
683 cal_block->map_data.map_size,
684 &cal_block->cal_data.paddr);
685done:
686 return cal_block;
687err:
688 kfree(cal_block->cal_info);
689 cal_block->cal_info = NULL;
690 kfree(cal_block->client_info);
691 cal_block->client_info = NULL;
692 kfree(cal_block);
693 cal_block = NULL;
694 return cal_block;
695}
696
697void cal_utils_clear_cal_block_q6maps(int num_cal_types,
698 struct cal_type_data **cal_type)
699{
700 int i = 0;
701 struct list_head *ptr, *next;
702 struct cal_block_data *cal_block;
703
704 pr_debug("%s\n", __func__);
705
706 if (cal_type == NULL) {
707 pr_err("%s: cal_type is NULL!\n", __func__);
708 goto done;
709 } else if ((num_cal_types <= 0) ||
710 (num_cal_types > MAX_CAL_TYPES)) {
711 pr_err("%s: num_cal_types of %d is Invalid!\n",
712 __func__, num_cal_types);
713 goto done;
714 }
715
716 for (; i < num_cal_types; i++) {
717 if (cal_type[i] == NULL)
718 continue;
719
720 mutex_lock(&cal_type[i]->lock);
721 list_for_each_safe(ptr, next,
722 &cal_type[i]->cal_blocks) {
723
724 cal_block = list_entry(ptr,
725 struct cal_block_data, list);
726
727 cal_block->map_data.q6map_handle = 0;
728 }
729 mutex_unlock(&cal_type[i]->lock);
730 }
731done:
732 return;
733}
734
735
736
737static int realloc_memory(struct cal_block_data *cal_block)
738{
739 int ret = 0;
740
741 msm_audio_ion_free(cal_block->map_data.ion_client,
742 cal_block->map_data.ion_handle);
743 cal_block->map_data.ion_client = NULL;
744 cal_block->map_data.ion_handle = NULL;
745 cal_block->cal_data.size = 0;
746
747 ret = cal_block_ion_alloc(cal_block);
748 if (ret < 0)
749 pr_err("%s: realloc_memory failed!\n",
750 __func__);
751 return ret;
752}
753
754static int map_memory(struct cal_type_data *cal_type,
755 struct cal_block_data *cal_block)
756{
757 int ret = 0;
758
759
760 if (cal_type->info.cal_util_callbacks.map_cal != NULL) {
761 if ((cal_block->map_data.ion_map_handle < 0) ||
762 (cal_block->map_data.map_size <= 0) ||
763 (cal_block->map_data.q6map_handle != 0)) {
764 goto done;
765 }
766
767 pr_debug("%s: cal type %d call map\n",
768 __func__, cal_type->info.reg.cal_type);
769 ret = cal_type->info.cal_util_callbacks.
770 map_cal(cal_type->info.reg.cal_type, cal_block);
771 if (ret < 0) {
772 pr_err("%s: map_cal failed, cal type %d, ret = %d!\n",
773 __func__, cal_type->info.reg.cal_type,
774 ret);
775 goto done;
776 }
777 }
778done:
779 return ret;
780}
781
782static int unmap_memory(struct cal_type_data *cal_type,
783 struct cal_block_data *cal_block)
784{
785 int ret = 0;
786
787 if (cal_type->info.cal_util_callbacks.unmap_cal != NULL) {
788 if ((cal_block->map_data.ion_map_handle < 0) ||
789 (cal_block->map_data.map_size <= 0) ||
790 (cal_block->map_data.q6map_handle == 0)) {
791 goto done;
792 }
793 pr_debug("%s: cal type %d call unmap\n",
794 __func__, cal_type->info.reg.cal_type);
795 ret = cal_type->info.cal_util_callbacks.
796 unmap_cal(cal_type->info.reg.cal_type, cal_block);
797 if (ret < 0) {
798 pr_err("%s: unmap_cal failed, cal type %d, ret = %d!\n",
799 __func__, cal_type->info.reg.cal_type,
800 ret);
801 goto done;
802 }
803 }
804done:
805 return ret;
806}
807
808/**
809 * cal_utils_alloc_cal
810 *
811 * @data_size: size of data to allocate
812 * @data: data pointer
813 * @cal_type: pointer to the cal type
814 * @client_info_size: client info size
815 * @client_info: pointer to client info
816 *
817 * Returns 0 on success, appropriate error code otherwise
818 */
819int cal_utils_alloc_cal(size_t data_size, void *data,
820 struct cal_type_data *cal_type,
821 size_t client_info_size, void *client_info)
822{
823 int ret = 0;
824 struct cal_block_data *cal_block;
825 struct audio_cal_type_alloc *alloc_data = data;
826
827 pr_debug("%s\n", __func__);
828
829 if (cal_type == NULL) {
830 pr_err("%s: cal_type is NULL!\n",
831 __func__);
832 ret = -EINVAL;
833 goto done;
834 }
835 if (data_size < sizeof(struct audio_cal_type_alloc)) {
836 pr_err("%s: data_size of %zd does not equal alloc struct size of %zd!\n",
837 __func__, data_size,
838 sizeof(struct audio_cal_type_alloc));
839 ret = -EINVAL;
840 goto done;
841 }
842 if ((client_info_size > 0) && (client_info == NULL)) {
843 pr_err("%s: User info pointer is NULL but size is %zd!\n",
844 __func__, client_info_size);
845 ret = -EINVAL;
846 goto done;
847 }
848
849 if (alloc_data->cal_data.mem_handle < 0) {
850 pr_err("%s: mem_handle %d invalid!\n",
851 __func__, alloc_data->cal_data.mem_handle);
852 ret = -EINVAL;
853 goto done;
854 }
855
856 mutex_lock(&cal_type->lock);
857
858 cal_block = get_matching_cal_block(cal_type,
859 data);
860 if (cal_block != NULL) {
861 ret = unmap_memory(cal_type, cal_block);
862 if (ret < 0)
863 goto err;
864 ret = realloc_memory(cal_block);
865 if (ret < 0)
866 goto err;
867 } else {
868 cal_block = create_cal_block(cal_type,
869 (struct audio_cal_type_basic *)alloc_data,
870 client_info_size, client_info);
871 if (cal_block == NULL) {
872 pr_err("%s: create_cal_block failed for %d!\n",
873 __func__, alloc_data->cal_data.mem_handle);
874 ret = -EINVAL;
875 goto err;
876 }
877 }
878
879 ret = map_memory(cal_type, cal_block);
880 if (ret < 0)
881 goto err;
882err:
883 mutex_unlock(&cal_type->lock);
884done:
885 return ret;
886}
887EXPORT_SYMBOL(cal_utils_alloc_cal);
888
889/**
890 * cal_utils_dealloc_cal
891 *
892 * @data_size: size of data to allocate
893 * @data: data pointer
894 * @cal_type: pointer to the cal type
895 *
896 * Returns 0 on success, appropriate error code otherwise
897 */
898int cal_utils_dealloc_cal(size_t data_size, void *data,
899 struct cal_type_data *cal_type)
900{
901 int ret = 0;
902 struct cal_block_data *cal_block;
903 struct audio_cal_type_dealloc *dealloc_data = data;
904
905 pr_debug("%s\n", __func__);
906
907
908 if (cal_type == NULL) {
909 pr_err("%s: cal_type is NULL!\n",
910 __func__);
911 ret = -EINVAL;
912 goto done;
913 }
914
915 if (data_size < sizeof(struct audio_cal_type_dealloc)) {
916 pr_err("%s: data_size of %zd does not equal struct size of %zd!\n",
917 __func__, data_size,
918 sizeof(struct audio_cal_type_dealloc));
919 ret = -EINVAL;
920 goto done;
921 }
922
923 if ((dealloc_data->cal_data.mem_handle == -1) &&
924 (dealloc_data->cal_hdr.buffer_number == ALL_CAL_BLOCKS)) {
925 destroy_all_cal_blocks(cal_type);
926 goto done;
927 }
928
929 if (dealloc_data->cal_data.mem_handle < 0) {
930 pr_err("%s: mem_handle %d invalid!\n",
931 __func__, dealloc_data->cal_data.mem_handle);
932 ret = -EINVAL;
933 goto done;
934 }
935
936 mutex_lock(&cal_type->lock);
937 cal_block = get_matching_cal_block(
938 cal_type,
939 data);
940 if (cal_block == NULL) {
941 pr_err("%s: allocation does not exist for %d!\n",
942 __func__, dealloc_data->cal_data.mem_handle);
943 ret = -EINVAL;
944 goto err;
945 }
946
947 ret = unmap_memory(cal_type, cal_block);
948 if (ret < 0)
949 goto err;
950
951 delete_cal_block(cal_block);
952err:
953 mutex_unlock(&cal_type->lock);
954done:
955 return ret;
956}
957EXPORT_SYMBOL(cal_utils_dealloc_cal);
958
959/**
960 * cal_utils_set_cal
961 *
962 * @data_size: size of data to allocate
963 * @data: data pointer
964 * @cal_type: pointer to the cal type
965 * @client_info_size: client info size
966 * @client_info: pointer to client info
967 *
968 * Returns 0 on success, appropriate error code otherwise
969 */
970int cal_utils_set_cal(size_t data_size, void *data,
971 struct cal_type_data *cal_type,
972 size_t client_info_size, void *client_info)
973{
974 int ret = 0;
975 struct cal_block_data *cal_block;
976 struct audio_cal_type_basic *basic_data = data;
977
978 pr_debug("%s\n", __func__);
979
980 if (cal_type == NULL) {
981 pr_err("%s: cal_type is NULL!\n",
982 __func__);
983 ret = -EINVAL;
984 goto done;
985 }
986
987 if ((client_info_size > 0) && (client_info == NULL)) {
988 pr_err("%s: User info pointer is NULL but size is %zd!\n",
989 __func__, client_info_size);
990 ret = -EINVAL;
991 goto done;
992 }
993
994 if ((data_size > get_user_cal_type_size(
995 cal_type->info.reg.cal_type)) || (data_size < 0)) {
996 pr_err("%s: cal_type %d, data_size of %zd is invalid, expecting %zd!\n",
997 __func__, cal_type->info.reg.cal_type, data_size,
998 get_user_cal_type_size(cal_type->info.reg.cal_type));
999 ret = -EINVAL;
1000 goto done;
1001 }
1002
1003 mutex_lock(&cal_type->lock);
1004 cal_block = get_matching_cal_block(
1005 cal_type,
1006 data);
1007 if (cal_block == NULL) {
1008 if (basic_data->cal_data.mem_handle > 0) {
1009 pr_err("%s: allocation does not exist for %d!\n",
1010 __func__, basic_data->cal_data.mem_handle);
1011 ret = -EINVAL;
1012 goto err;
1013 } else {
1014 cal_block = create_cal_block(
1015 cal_type,
1016 basic_data,
1017 client_info_size, client_info);
1018 if (cal_block == NULL) {
1019 pr_err("%s: create_cal_block failed for cal type %d!\n",
1020 __func__,
1021 cal_type->info.reg.cal_type);
1022 ret = -EINVAL;
1023 goto err;
1024 }
1025 }
1026 }
1027
1028 ret = map_memory(cal_type, cal_block);
1029 if (ret < 0)
1030 goto err;
1031
1032 cal_block->cal_data.size = basic_data->cal_data.cal_size;
1033
1034 if (client_info_size > 0) {
1035 memcpy(cal_block->client_info,
1036 client_info,
1037 client_info_size);
1038 }
1039
1040 memcpy(cal_block->cal_info,
1041 ((uint8_t *)data + sizeof(struct audio_cal_type_basic)),
1042 data_size - sizeof(struct audio_cal_type_basic));
1043
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07001044 /* reset buffer stale flag */
1045 cal_block->cal_stale = false;
1046
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301047err:
1048 mutex_unlock(&cal_type->lock);
1049done:
1050 return ret;
1051}
1052EXPORT_SYMBOL(cal_utils_set_cal);
Vikram Pandurangad3b58cc2017-09-27 12:17:36 -07001053
1054/**
1055 * cal_utils_mark_cal_used
1056 *
1057 * @cal_block: pointer to cal block
1058 */
1059void cal_utils_mark_cal_used(struct cal_block_data *cal_block)
1060{
1061 if (cal_block)
1062 cal_block->cal_stale = true;
1063}
1064EXPORT_SYMBOL(cal_utils_mark_cal_used);
1065
1066/**
1067 * cal_utils_is_cal_stale
1068 *
1069 * @cal_block: pointer to cal block
1070 *
1071 * Returns true if cal block is stale, false otherwise
1072 */
1073bool cal_utils_is_cal_stale(struct cal_block_data *cal_block)
1074{
1075 if ((cal_block) && (cal_block->cal_stale))
1076 return true;
1077
1078 return false;
1079}
1080EXPORT_SYMBOL(cal_utils_is_cal_stale);