audio_cal_utils.c 25 KB

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