audio_cal_utils.c 25 KB

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