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