audio_cal_utils.c 25 KB

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