audio_cal_utils.c 25 KB

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