q6adm.c 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  1. /* Copyright (c) 2010-2013, 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. #include <linux/slab.h>
  13. #include <linux/wait.h>
  14. #include <linux/sched.h>
  15. #include <linux/jiffies.h>
  16. #include <linux/uaccess.h>
  17. #include <linux/atomic.h>
  18. #include <linux/err.h>
  19. #include <mach/qdsp6v2/audio_dev_ctl.h>
  20. #include <mach/qdsp6v2/audio_acdb.h>
  21. #include <mach/qdsp6v2/rtac.h>
  22. #include <sound/apr_audio.h>
  23. #include <sound/q6afe.h>
  24. #define TIMEOUT_MS 1000
  25. #define AUDIO_RX 0x0
  26. #define AUDIO_TX 0x1
  27. #define ASM_MAX_SESSION 0x8 /* To do: define in a header */
  28. #define RESET_COPP_ID 99
  29. #define INVALID_COPP_ID 0xFF
  30. struct adm_ctl {
  31. void *apr;
  32. atomic_t copp_id[AFE_MAX_PORTS];
  33. atomic_t copp_cnt[AFE_MAX_PORTS];
  34. atomic_t copp_stat[AFE_MAX_PORTS];
  35. wait_queue_head_t wait;
  36. int ec_ref_rx;
  37. };
  38. static struct acdb_cal_block mem_addr_audproc[MAX_AUDPROC_TYPES];
  39. static struct acdb_cal_block mem_addr_audvol[MAX_AUDPROC_TYPES];
  40. static struct adm_ctl this_adm;
  41. static int pseudo_copp[2];
  42. int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
  43. {
  44. struct asm_pp_params_command *open = NULL;
  45. int ret = 0, sz = 0;
  46. int index;
  47. pr_debug("SRS - %s", __func__);
  48. index = afe_get_port_index(port_id);
  49. if (IS_ERR_VALUE(index)) {
  50. pr_err("%s: invald port id\n", __func__);
  51. return index;
  52. }
  53. switch (srs_tech_id) {
  54. case SRS_ID_GLOBAL: {
  55. struct srs_trumedia_params_GLOBAL *glb_params = NULL;
  56. sz = sizeof(struct asm_pp_params_command) +
  57. sizeof(struct srs_trumedia_params_GLOBAL);
  58. open = kzalloc(sz, GFP_KERNEL);
  59. open->payload_size = sizeof(struct srs_trumedia_params_GLOBAL) +
  60. sizeof(struct asm_pp_param_data_hdr);
  61. open->params.param_id = SRS_TRUMEDIA_PARAMS;
  62. open->params.param_size =
  63. sizeof(struct srs_trumedia_params_GLOBAL);
  64. glb_params = (struct srs_trumedia_params_GLOBAL *)((u8 *)open +
  65. sizeof(struct asm_pp_params_command));
  66. memcpy(glb_params, srs_params,
  67. sizeof(struct srs_trumedia_params_GLOBAL));
  68. pr_debug("SRS - %s: Global params - 1 = %x, 2 = %x, 3 = %x,"
  69. " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x\n",
  70. __func__, (int)glb_params->v1,
  71. (int)glb_params->v2, (int)glb_params->v3,
  72. (int)glb_params->v4, (int)glb_params->v5,
  73. (int)glb_params->v6, (int)glb_params->v7,
  74. (int)glb_params->v8);
  75. break;
  76. }
  77. case SRS_ID_WOWHD: {
  78. struct srs_trumedia_params_WOWHD *whd_params = NULL;
  79. sz = sizeof(struct asm_pp_params_command) +
  80. sizeof(struct srs_trumedia_params_WOWHD);
  81. open = kzalloc(sz, GFP_KERNEL);
  82. open->payload_size = sizeof(struct srs_trumedia_params_WOWHD) +
  83. sizeof(struct asm_pp_param_data_hdr);
  84. open->params.param_id = SRS_TRUMEDIA_PARAMS_WOWHD;
  85. open->params.param_size =
  86. sizeof(struct srs_trumedia_params_WOWHD);
  87. whd_params = (struct srs_trumedia_params_WOWHD *)((u8 *)open +
  88. sizeof(struct asm_pp_params_command));
  89. memcpy(whd_params, srs_params,
  90. sizeof(struct srs_trumedia_params_WOWHD));
  91. pr_debug("SRS - %s: WOWHD params - 1 = %x, 2 = %x, 3 = %x,"
  92. " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x, 9 = %x,"
  93. " 10 = %x, 11 = %x\n", __func__, (int)whd_params->v1,
  94. (int)whd_params->v2, (int)whd_params->v3,
  95. (int)whd_params->v4, (int)whd_params->v5,
  96. (int)whd_params->v6, (int)whd_params->v7,
  97. (int)whd_params->v8, (int)whd_params->v9,
  98. (int)whd_params->v10, (int)whd_params->v11);
  99. break;
  100. }
  101. case SRS_ID_CSHP: {
  102. struct srs_trumedia_params_CSHP *chp_params = NULL;
  103. sz = sizeof(struct asm_pp_params_command) +
  104. sizeof(struct srs_trumedia_params_CSHP);
  105. open = kzalloc(sz, GFP_KERNEL);
  106. open->payload_size = sizeof(struct srs_trumedia_params_CSHP) +
  107. sizeof(struct asm_pp_param_data_hdr);
  108. open->params.param_id = SRS_TRUMEDIA_PARAMS_CSHP;
  109. open->params.param_size =
  110. sizeof(struct srs_trumedia_params_CSHP);
  111. chp_params = (struct srs_trumedia_params_CSHP *)((u8 *)open +
  112. sizeof(struct asm_pp_params_command));
  113. memcpy(chp_params, srs_params,
  114. sizeof(struct srs_trumedia_params_CSHP));
  115. pr_debug("SRS - %s: CSHP params - 1 = %x, 2 = %x, 3 = %x,"
  116. " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x,"
  117. " 9 = %x\n", __func__, (int)chp_params->v1,
  118. (int)chp_params->v2, (int)chp_params->v3,
  119. (int)chp_params->v4, (int)chp_params->v5,
  120. (int)chp_params->v6, (int)chp_params->v7,
  121. (int)chp_params->v8, (int)chp_params->v9);
  122. break;
  123. }
  124. case SRS_ID_HPF: {
  125. struct srs_trumedia_params_HPF *hpf_params = NULL;
  126. sz = sizeof(struct asm_pp_params_command) +
  127. sizeof(struct srs_trumedia_params_HPF);
  128. open = kzalloc(sz, GFP_KERNEL);
  129. open->payload_size = sizeof(struct srs_trumedia_params_HPF) +
  130. sizeof(struct asm_pp_param_data_hdr);
  131. open->params.param_id = SRS_TRUMEDIA_PARAMS_HPF;
  132. open->params.param_size =
  133. sizeof(struct srs_trumedia_params_HPF);
  134. hpf_params = (struct srs_trumedia_params_HPF *)((u8 *)open +
  135. sizeof(struct asm_pp_params_command));
  136. memcpy(hpf_params, srs_params,
  137. sizeof(struct srs_trumedia_params_HPF));
  138. pr_debug("SRS - %s: HPF params - 1 = %x\n", __func__,
  139. (int)hpf_params->v1);
  140. break;
  141. }
  142. case SRS_ID_PEQ: {
  143. struct srs_trumedia_params_PEQ *peq_params = NULL;
  144. sz = sizeof(struct asm_pp_params_command) +
  145. sizeof(struct srs_trumedia_params_PEQ);
  146. open = kzalloc(sz, GFP_KERNEL);
  147. open->payload_size = sizeof(struct srs_trumedia_params_PEQ) +
  148. sizeof(struct asm_pp_param_data_hdr);
  149. open->params.param_id = SRS_TRUMEDIA_PARAMS_PEQ;
  150. open->params.param_size =
  151. sizeof(struct srs_trumedia_params_PEQ);
  152. peq_params = (struct srs_trumedia_params_PEQ *)((u8 *)open +
  153. sizeof(struct asm_pp_params_command));
  154. memcpy(peq_params, srs_params,
  155. sizeof(struct srs_trumedia_params_PEQ));
  156. pr_debug("SRS - %s: PEQ params - 1 = %x 2 = %x, 3 = %x,"
  157. " 4 = %x\n", __func__, (int)peq_params->v1,
  158. (int)peq_params->v2, (int)peq_params->v3,
  159. (int)peq_params->v4);
  160. break;
  161. }
  162. case SRS_ID_HL: {
  163. struct srs_trumedia_params_HL *hl_params = NULL;
  164. sz = sizeof(struct asm_pp_params_command) +
  165. sizeof(struct srs_trumedia_params_HL);
  166. open = kzalloc(sz, GFP_KERNEL);
  167. open->payload_size = sizeof(struct srs_trumedia_params_HL) +
  168. sizeof(struct asm_pp_param_data_hdr);
  169. open->params.param_id = SRS_TRUMEDIA_PARAMS_HL;
  170. open->params.param_size = sizeof(struct srs_trumedia_params_HL);
  171. hl_params = (struct srs_trumedia_params_HL *)((u8 *)open +
  172. sizeof(struct asm_pp_params_command));
  173. memcpy(hl_params, srs_params,
  174. sizeof(struct srs_trumedia_params_HL));
  175. pr_debug("SRS - %s: HL params - 1 = %x, 2 = %x, 3 = %x, 4 = %x,"
  176. " 5 = %x, 6 = %x, 7 = %x\n", __func__,
  177. (int)hl_params->v1, (int)hl_params->v2,
  178. (int)hl_params->v3, (int)hl_params->v4,
  179. (int)hl_params->v5, (int)hl_params->v6,
  180. (int)hl_params->v7);
  181. break;
  182. }
  183. default:
  184. goto fail_cmd;
  185. }
  186. open->payload = NULL;
  187. open->params.module_id = SRS_TRUMEDIA_MODULE_ID;
  188. open->params.reserved = 0;
  189. open->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  190. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  191. open->hdr.pkt_size = sz;
  192. open->hdr.src_svc = APR_SVC_ADM;
  193. open->hdr.src_domain = APR_DOMAIN_APPS;
  194. open->hdr.src_port = port_id;
  195. open->hdr.dest_svc = APR_SVC_ADM;
  196. open->hdr.dest_domain = APR_DOMAIN_ADSP;
  197. open->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
  198. open->hdr.token = port_id;
  199. open->hdr.opcode = ADM_CMD_SET_PARAMS;
  200. pr_debug("SRS - %s: Command was sent now check Q6 - port id = %d,"
  201. " size %d, module id %x, param id %x.\n", __func__,
  202. open->hdr.dest_port, open->payload_size,
  203. open->params.module_id, open->params.param_id);
  204. ret = apr_send_pkt(this_adm.apr, (uint32_t *)open);
  205. if (ret < 0) {
  206. pr_err("SRS - %s: ADM enable for port %d failed\n", __func__,
  207. port_id);
  208. ret = -EINVAL;
  209. goto fail_cmd;
  210. }
  211. /* Wait for the callback with copp id */
  212. ret = wait_event_timeout(this_adm.wait, 1,
  213. msecs_to_jiffies(TIMEOUT_MS));
  214. if (!ret) {
  215. pr_err("SRS - %s: ADM open failed for port %d\n", __func__,
  216. port_id);
  217. ret = -EINVAL;
  218. goto fail_cmd;
  219. }
  220. fail_cmd:
  221. kfree(open);
  222. return ret;
  223. }
  224. struct SS3D {
  225. int _1; int _2; short _3; short _4;
  226. short _5; short _6; int _7; int _X[32];
  227. short _8; short _9; short _10; short _11;
  228. short _12; short _13; short _14; short _15;
  229. short _16; short _17; short _18; short _19;
  230. short _20; short _21; short _22; short _23;
  231. short _24; short _25; short _26[5];
  232. short _27; short _28; short _29; short _30;
  233. short _31; short _32; short _33; int _34; int _35;
  234. int _36; int _37; int _38; int _39; int _40;
  235. };
  236. struct SS3D_F {
  237. int _1; int _2; int _3; int _4; int _5; int _6; int _7; int _X[];
  238. };
  239. int srs_ss3d_open(int port_id, int srs_tech_id, void *srs_params)
  240. {
  241. struct asm_pp_params_command *open = NULL;
  242. int ret = 0, sz = 0;
  243. int index;
  244. pr_debug("SRS - %s: called.", __func__);
  245. switch (srs_tech_id) {
  246. case SRS_ID_SS3D_GLOBAL: {
  247. struct srs_SS3D_params_GLOBAL *glb_params = NULL;
  248. sz = sizeof(struct asm_pp_params_command) +
  249. sizeof(struct srs_SS3D_params_GLOBAL);
  250. open = kzalloc(sz, GFP_KERNEL);
  251. open->payload_size = sizeof(struct srs_SS3D_params_GLOBAL) +
  252. sizeof(struct asm_pp_param_data_hdr);
  253. open->params.param_id = SRS_SS3D_PARAMS;
  254. open->params.param_size =
  255. sizeof(struct srs_SS3D_params_GLOBAL);
  256. glb_params = (struct srs_SS3D_params_GLOBAL *)((u8 *)open +
  257. sizeof(struct asm_pp_params_command));
  258. memcpy(glb_params, srs_params,
  259. sizeof(struct srs_SS3D_params_GLOBAL));
  260. pr_debug("SRS - ss3d global params - 1 = %x, 2 = %x, 3 = %x\n"
  261. " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x\n",
  262. (int)glb_params->v1, (int)glb_params->v2,
  263. (int)glb_params->v3, (int)glb_params->v4,
  264. (int)glb_params->v5, (int)glb_params->v6,
  265. (int)glb_params->v7, (int)glb_params->v8);
  266. break;
  267. }
  268. case SRS_ID_SS3D_CTRL: {
  269. struct srs_SS3D_ctrl_params *whd_params = NULL;
  270. sz = sizeof(struct asm_pp_params_command) +
  271. sizeof(struct srs_SS3D_ctrl_params);
  272. open = kzalloc(sz, GFP_KERNEL);
  273. open->payload_size = sizeof(struct srs_SS3D_ctrl_params) +
  274. sizeof(struct asm_pp_param_data_hdr);
  275. open->params.param_id = SRS_SS3D_PARAMS_CTRL;
  276. open->params.param_size = sizeof(struct srs_SS3D_ctrl_params);
  277. whd_params = (struct srs_SS3D_ctrl_params *)((u8 *)open +
  278. sizeof(struct asm_pp_params_command));
  279. memcpy(whd_params, srs_params,
  280. sizeof(struct srs_SS3D_ctrl_params));
  281. {
  282. struct SS3D *D = (struct SS3D *)whd_params->v;
  283. pr_debug("SRS - ss3d ctrl params\n"
  284. "1 = 0x%08X, 2 = 0x%08X, 3 = 0x%04X,\n"
  285. "4 = 0x%04X, 5 = 0x%04X, 6 = 0x%04X,\n"
  286. "7 = 0x%08X, 8 = 0x%04X, 9 = 0x%04X,\n"
  287. "10 = 0x%04X, 11 = 0x%04X, 12 = 0x%04X,\n"
  288. "13 = 0x%04X, 14 = 0x%04X, 15 = 0x%04X,\n"
  289. "16 = 0x%04X, 17 = 0x%04X, 18 = 0x%04X,\n"
  290. "19 = 0x%04X, 20 = 0x%04X, 21 = 0x%04X,\n"
  291. "22 = 0x%04X, 23 = 0x%04X, 24 = 0x%04X,\n"
  292. "25 = 0x%04X, 26.0 = 0x%04X, 26.1 = 0x%04X,\n"
  293. "26.2 = 0x%04X, 26.3 = 0x%04X,\n"
  294. "26.4 = 0x%04X, 27 = 0x%04X, 28 = 0x%04X,\n"
  295. "29 = 0x%04X, 30 = 0x%04X, 31 = 0x%04X,\n"
  296. "32 = 0x%04X, 33 = 0x%04X, 34 = 0x%08X,\n"
  297. "35 = 0x%08X, 36 = 0x%08X, 37 = 0x%08X,\n"
  298. "38 = 0x%08X, 39 = 0x%08X, 40 = 0x%08X",
  299. D->_1, D->_2, D->_3, D->_4, D->_5, D->_6, D->_7,
  300. D->_8, D->_9, D->_10, D->_11, D->_12, D->_13,
  301. D->_14, D->_15, D->_16, D->_17, D->_18, D->_19,
  302. D->_20, D->_21, D->_22, D->_23, D->_24, D->_25,
  303. D->_26[0], D->_26[1], D->_26[2], D->_26[3],
  304. D->_26[4], D->_27, D->_28, D->_29, D->_30,
  305. D->_31, D->_32, D->_33, D->_34, D->_35, D->_36,
  306. D->_37, D->_38, D->_39, D->_40);
  307. }
  308. break;
  309. }
  310. case SRS_ID_SS3D_FILTER: {
  311. struct srs_SS3D_filter_params *chp_params = NULL;
  312. sz = sizeof(struct asm_pp_params_command) +
  313. sizeof(struct srs_SS3D_filter_params);
  314. open = kzalloc(sz, GFP_KERNEL);
  315. open->payload_size = sizeof(struct srs_SS3D_filter_params) +
  316. sizeof(struct asm_pp_param_data_hdr);
  317. open->params.param_id = SRS_SS3D_PARAMS_FILTER;
  318. open->params.param_size =
  319. sizeof(struct srs_SS3D_filter_params);
  320. chp_params = (struct srs_SS3D_filter_params *)((u8 *)open +
  321. sizeof(struct asm_pp_params_command));
  322. memcpy(chp_params, srs_params,
  323. sizeof(struct srs_SS3D_filter_params));
  324. {
  325. struct SS3D_F *D = (struct SS3D_F *)chp_params->v;
  326. pr_debug("SRS - ss3d filter params\n"
  327. "1 = 0x%08X, 2 = 0x%08X, 3 = 0x%08X\n"
  328. "4 = 0x%08X, 5 = 0x%08X, 6 = 0x%08X\n"
  329. "7 = 0x%08X", D->_1, D->_2, D->_3, D->_4, D->_5,
  330. D->_6, D->_7);
  331. }
  332. break;
  333. }
  334. default:
  335. pr_debug("SRS - bad param!\n");
  336. goto fail_cmd;
  337. }
  338. open->payload = NULL;
  339. open->params.module_id = SRS_SS3D_MODULE_ID;
  340. open->params.reserved = 0;
  341. open->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  342. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  343. open->hdr.pkt_size = sz;
  344. open->hdr.src_svc = APR_SVC_ADM;
  345. open->hdr.src_domain = APR_DOMAIN_APPS;
  346. open->hdr.src_port = port_id;
  347. open->hdr.dest_svc = APR_SVC_ADM;
  348. open->hdr.dest_domain = APR_DOMAIN_ADSP;
  349. index = afe_get_port_index(port_id);
  350. open->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
  351. /* port_id;//atomic_read(&this_adm.copp_id[port_id]); */
  352. open->hdr.token = port_id;
  353. open->hdr.opcode = ADM_CMD_SET_PARAMS;
  354. pr_debug("SRS - %s: Command was sent now check Q6 - port id = %d,\n"
  355. "size %d, module id %x, param id %x.\n",
  356. __func__, open->hdr.dest_port, open->payload_size,
  357. open->params.module_id, open->params.param_id);
  358. ret = apr_send_pkt(this_adm.apr, (uint32_t *)open);
  359. if (ret < 0) {
  360. pr_err("SRS - %s: ADM enable for port %d failed\n",
  361. __func__, port_id);
  362. ret = -EINVAL;
  363. goto fail_cmd;
  364. }
  365. /* Wait for the callback with copp id */
  366. ret = wait_event_timeout(this_adm.wait, 1,
  367. msecs_to_jiffies(TIMEOUT_MS));
  368. if (!ret) {
  369. pr_err("SRS - %s: ADM open failed for port %d\n",
  370. __func__, port_id);
  371. ret = -EINVAL;
  372. goto fail_cmd;
  373. }
  374. fail_cmd:
  375. kfree(open);
  376. return ret;
  377. }
  378. static int32_t adm_callback(struct apr_client_data *data, void *priv)
  379. {
  380. uint32_t *payload;
  381. int i, index;
  382. payload = data->payload;
  383. if (data->opcode == RESET_EVENTS) {
  384. pr_debug("adm_callback: Reset event is received: %d %d apr[%p]\n",
  385. data->reset_event, data->reset_proc,
  386. this_adm.apr);
  387. if (this_adm.apr) {
  388. apr_reset(this_adm.apr);
  389. for (i = 0; i < AFE_MAX_PORTS; i++) {
  390. atomic_set(&this_adm.copp_id[i],
  391. RESET_COPP_ID);
  392. atomic_set(&this_adm.copp_cnt[i], 0);
  393. atomic_set(&this_adm.copp_stat[i], 0);
  394. }
  395. this_adm.apr = NULL;
  396. }
  397. pr_debug("Resetting calibration blocks");
  398. for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
  399. /* Device calibration */
  400. mem_addr_audproc[i].cal_size = 0;
  401. mem_addr_audproc[i].cal_kvaddr = 0;
  402. mem_addr_audproc[i].cal_paddr = 0;
  403. /* Volume calibration */
  404. mem_addr_audvol[i].cal_size = 0;
  405. mem_addr_audvol[i].cal_kvaddr = 0;
  406. mem_addr_audvol[i].cal_paddr = 0;
  407. }
  408. return 0;
  409. }
  410. pr_debug("%s: code = 0x%x %x %x size = %d\n", __func__,
  411. data->opcode, payload[0], payload[1],
  412. data->payload_size);
  413. if (data->payload_size) {
  414. index = afe_get_port_index(data->token);
  415. pr_debug("%s: Port ID %d, index %d\n", __func__,
  416. data->token, index);
  417. if (index < 0 || index >= AFE_MAX_PORTS) {
  418. pr_err("%s: invalid port idx %d token %d\n",
  419. __func__, index, data->token);
  420. return 0;
  421. }
  422. if (data->opcode == APR_BASIC_RSP_RESULT) {
  423. pr_debug("APR_BASIC_RSP_RESULT id %x\n", payload[0]);
  424. switch (payload[0]) {
  425. case ADM_CMD_SET_PARAMS:
  426. if (rtac_make_adm_callback(payload,
  427. data->payload_size))
  428. break;
  429. case ADM_CMD_COPP_CLOSE:
  430. case ADM_CMD_MEMORY_MAP:
  431. case ADM_CMD_MEMORY_UNMAP:
  432. case ADM_CMD_MEMORY_MAP_REGIONS:
  433. case ADM_CMD_MEMORY_UNMAP_REGIONS:
  434. case ADM_CMD_MATRIX_MAP_ROUTINGS:
  435. case ADM_CMD_CONNECT_AFE_PORT:
  436. case ADM_CMD_DISCONNECT_AFE_PORT:
  437. case ADM_CMD_CONNECT_AFE_PORT_V2:
  438. case ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3:
  439. atomic_set(&this_adm.copp_stat[index], 1);
  440. wake_up(&this_adm.wait);
  441. break;
  442. default:
  443. pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
  444. payload[0]);
  445. break;
  446. }
  447. return 0;
  448. }
  449. switch (data->opcode) {
  450. case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN_V3:
  451. case ADM_CMDRSP_COPP_OPEN:
  452. case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN: {
  453. struct adm_copp_open_respond *open = data->payload;
  454. if (open->copp_id == INVALID_COPP_ID) {
  455. pr_err("%s: invalid coppid rxed %d\n",
  456. __func__, open->copp_id);
  457. atomic_set(&this_adm.copp_stat[index], 1);
  458. wake_up(&this_adm.wait);
  459. break;
  460. }
  461. if (index == IDX_PSEUDOPORT_01)
  462. pseudo_copp[
  463. atomic_read(&this_adm.copp_cnt[index])] =
  464. open->copp_id;
  465. atomic_set(&this_adm.copp_id[index], open->copp_id);
  466. atomic_set(&this_adm.copp_stat[index], 1);
  467. pr_debug("%s: coppid rxed=%d\n", __func__,
  468. open->copp_id);
  469. wake_up(&this_adm.wait);
  470. }
  471. break;
  472. case ADM_CMDRSP_GET_PARAMS:
  473. pr_debug("%s: ADM_CMDRSP_GET_PARAMS\n", __func__);
  474. rtac_make_adm_callback(payload,
  475. data->payload_size);
  476. break;
  477. default:
  478. pr_err("%s: Unknown cmd:0x%x\n", __func__,
  479. data->opcode);
  480. break;
  481. }
  482. }
  483. return 0;
  484. }
  485. int adm_connect_afe_port_v2(int mode, int session_id, int port_id,
  486. int sample_rate, int channels)
  487. {
  488. struct adm_cmd_connect_afe_port_v2 cmd;
  489. int ret = 0;
  490. int index;
  491. pr_debug("%s: port %d session id:%d\n", __func__,
  492. port_id, session_id);
  493. port_id = afe_convert_virtual_to_portid(port_id);
  494. if (afe_validate_port(port_id) < 0) {
  495. pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
  496. return -ENODEV;
  497. }
  498. if (this_adm.apr == NULL) {
  499. this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
  500. 0xFFFFFFFF, &this_adm);
  501. if (this_adm.apr == NULL) {
  502. pr_err("%s: Unable to register ADM\n", __func__);
  503. ret = -ENODEV;
  504. return ret;
  505. }
  506. rtac_set_adm_handle(this_adm.apr);
  507. }
  508. index = afe_get_port_index(port_id);
  509. pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
  510. cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  511. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  512. cmd.hdr.pkt_size = sizeof(cmd);
  513. cmd.hdr.src_svc = APR_SVC_ADM;
  514. cmd.hdr.src_domain = APR_DOMAIN_APPS;
  515. cmd.hdr.src_port = port_id;
  516. cmd.hdr.dest_svc = APR_SVC_ADM;
  517. cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
  518. cmd.hdr.dest_port = port_id;
  519. cmd.hdr.token = port_id;
  520. cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V2;
  521. cmd.mode = mode;
  522. cmd.session_id = session_id;
  523. cmd.afe_port_id = port_id;
  524. cmd.num_channels = channels;
  525. cmd.sampling_rate = sample_rate;
  526. atomic_set(&this_adm.copp_stat[index], 0);
  527. ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
  528. if (ret < 0) {
  529. pr_err("%s:ADM enable for port %d failed\n",
  530. __func__, port_id);
  531. ret = -EINVAL;
  532. goto fail_cmd;
  533. }
  534. ret = wait_event_timeout(this_adm.wait,
  535. atomic_read(&this_adm.copp_stat[index]),
  536. msecs_to_jiffies(TIMEOUT_MS));
  537. if (!ret) {
  538. pr_err("%s ADM connect AFE failed for port %d\n", __func__,
  539. port_id);
  540. ret = -EINVAL;
  541. goto fail_cmd;
  542. }
  543. atomic_inc(&this_adm.copp_cnt[index]);
  544. return 0;
  545. fail_cmd:
  546. return ret;
  547. }
  548. static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
  549. {
  550. s32 result = 0;
  551. struct adm_set_params_command adm_params;
  552. int index = afe_get_port_index(port_id);
  553. if (index < 0 || index >= AFE_MAX_PORTS) {
  554. pr_err("%s: invalid port idx %d portid %d\n",
  555. __func__, index, port_id);
  556. return 0;
  557. }
  558. pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
  559. if (!aud_cal || aud_cal->cal_size == 0) {
  560. pr_debug("%s: No ADM cal to send for port_id = %d!\n",
  561. __func__, port_id);
  562. result = -EINVAL;
  563. goto done;
  564. }
  565. adm_params.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  566. APR_HDR_LEN(20), APR_PKT_VER);
  567. adm_params.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
  568. sizeof(adm_params));
  569. adm_params.hdr.src_svc = APR_SVC_ADM;
  570. adm_params.hdr.src_domain = APR_DOMAIN_APPS;
  571. adm_params.hdr.src_port = port_id;
  572. adm_params.hdr.dest_svc = APR_SVC_ADM;
  573. adm_params.hdr.dest_domain = APR_DOMAIN_ADSP;
  574. adm_params.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
  575. adm_params.hdr.token = port_id;
  576. adm_params.hdr.opcode = ADM_CMD_SET_PARAMS;
  577. adm_params.payload = aud_cal->cal_paddr;
  578. adm_params.payload_size = aud_cal->cal_size;
  579. atomic_set(&this_adm.copp_stat[index], 0);
  580. pr_debug("%s: Sending SET_PARAMS payload = 0x%x, size = %d\n",
  581. __func__, adm_params.payload, adm_params.payload_size);
  582. result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_params);
  583. if (result < 0) {
  584. pr_err("%s: Set params failed port = %d payload = 0x%x\n",
  585. __func__, port_id, aud_cal->cal_paddr);
  586. result = -EINVAL;
  587. goto done;
  588. }
  589. /* Wait for the callback */
  590. result = wait_event_timeout(this_adm.wait,
  591. atomic_read(&this_adm.copp_stat[index]),
  592. msecs_to_jiffies(TIMEOUT_MS));
  593. if (!result) {
  594. pr_err("%s: Set params timed out port = %d, payload = 0x%x\n",
  595. __func__, port_id, aud_cal->cal_paddr);
  596. result = -EINVAL;
  597. goto done;
  598. }
  599. result = 0;
  600. done:
  601. return result;
  602. }
  603. static void send_adm_cal(int port_id, int path)
  604. {
  605. int result = 0;
  606. s32 acdb_path;
  607. struct acdb_cal_block aud_cal;
  608. pr_debug("%s\n", __func__);
  609. /* Maps audio_dev_ctrl path definition to ACDB definition */
  610. acdb_path = path - 1;
  611. pr_debug("%s: Sending audproc cal\n", __func__);
  612. get_audproc_cal(acdb_path, &aud_cal);
  613. /* map & cache buffers used */
  614. if (((mem_addr_audproc[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
  615. (aud_cal.cal_size > 0)) ||
  616. (aud_cal.cal_size > mem_addr_audproc[acdb_path].cal_size)) {
  617. if (mem_addr_audproc[acdb_path].cal_paddr != 0)
  618. adm_memory_unmap_regions(
  619. &mem_addr_audproc[acdb_path].cal_paddr,
  620. &mem_addr_audproc[acdb_path].cal_size, 1);
  621. result = adm_memory_map_regions(&aud_cal.cal_paddr, 0,
  622. &aud_cal.cal_size, 1);
  623. if (result < 0)
  624. pr_err("ADM audproc mmap did not work! path = %d, "
  625. "addr = 0x%x, size = %d\n", acdb_path,
  626. aud_cal.cal_paddr, aud_cal.cal_size);
  627. else
  628. mem_addr_audproc[acdb_path] = aud_cal;
  629. }
  630. if (!send_adm_cal_block(port_id, &aud_cal))
  631. pr_debug("%s: Audproc cal sent for port id: %d, path %d\n",
  632. __func__, port_id, acdb_path);
  633. else
  634. pr_debug("%s: Audproc cal not sent for port id: %d, path %d\n",
  635. __func__, port_id, acdb_path);
  636. pr_debug("%s: Sending audvol cal\n", __func__);
  637. get_audvol_cal(acdb_path, &aud_cal);
  638. /* map & cache buffers used */
  639. if (((mem_addr_audvol[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
  640. (aud_cal.cal_size > 0)) ||
  641. (aud_cal.cal_size > mem_addr_audvol[acdb_path].cal_size)) {
  642. if (mem_addr_audvol[acdb_path].cal_paddr != 0)
  643. adm_memory_unmap_regions(
  644. &mem_addr_audvol[acdb_path].cal_paddr,
  645. &mem_addr_audvol[acdb_path].cal_size, 1);
  646. result = adm_memory_map_regions(&aud_cal.cal_paddr, 0,
  647. &aud_cal.cal_size, 1);
  648. if (result < 0)
  649. pr_err("ADM audvol mmap did not work! path = %d, "
  650. "addr = 0x%x, size = %d\n", acdb_path,
  651. aud_cal.cal_paddr, aud_cal.cal_size);
  652. else
  653. mem_addr_audvol[acdb_path] = aud_cal;
  654. }
  655. if (!send_adm_cal_block(port_id, &aud_cal))
  656. pr_debug("%s: Audvol cal sent for port id: %d, path %d\n",
  657. __func__, port_id, acdb_path);
  658. else
  659. pr_debug("%s: Audvol cal not sent for port id: %d, path %d\n",
  660. __func__, port_id, acdb_path);
  661. }
  662. int adm_connect_afe_port(int mode, int session_id, int port_id)
  663. {
  664. struct adm_cmd_connect_afe_port cmd;
  665. int ret = 0;
  666. int index;
  667. pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
  668. port_id, session_id, mode);
  669. port_id = afe_convert_virtual_to_portid(port_id);
  670. if (afe_validate_port(port_id) < 0) {
  671. pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
  672. return -ENODEV;
  673. }
  674. if (this_adm.apr == NULL) {
  675. this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
  676. 0xFFFFFFFF, &this_adm);
  677. if (this_adm.apr == NULL) {
  678. pr_err("%s: Unable to register ADM\n", __func__);
  679. ret = -ENODEV;
  680. return ret;
  681. }
  682. rtac_set_adm_handle(this_adm.apr);
  683. }
  684. index = afe_get_port_index(port_id);
  685. pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
  686. cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  687. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  688. cmd.hdr.pkt_size = sizeof(cmd);
  689. cmd.hdr.src_svc = APR_SVC_ADM;
  690. cmd.hdr.src_domain = APR_DOMAIN_APPS;
  691. cmd.hdr.src_port = port_id;
  692. cmd.hdr.dest_svc = APR_SVC_ADM;
  693. cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
  694. cmd.hdr.dest_port = port_id;
  695. cmd.hdr.token = port_id;
  696. cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT;
  697. cmd.mode = mode;
  698. cmd.session_id = session_id;
  699. cmd.afe_port_id = port_id;
  700. atomic_set(&this_adm.copp_stat[index], 0);
  701. ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
  702. if (ret < 0) {
  703. pr_err("%s:ADM enable for port %d failed\n",
  704. __func__, port_id);
  705. ret = -EINVAL;
  706. goto fail_cmd;
  707. }
  708. /* Wait for the callback with copp id */
  709. ret = wait_event_timeout(this_adm.wait,
  710. atomic_read(&this_adm.copp_stat[index]),
  711. msecs_to_jiffies(TIMEOUT_MS));
  712. if (!ret) {
  713. pr_err("%s ADM connect AFE failed for port %d\n", __func__,
  714. port_id);
  715. ret = -EINVAL;
  716. goto fail_cmd;
  717. }
  718. atomic_inc(&this_adm.copp_cnt[index]);
  719. return 0;
  720. fail_cmd:
  721. return ret;
  722. }
  723. int adm_disconnect_afe_port(int mode, int session_id, int port_id)
  724. {
  725. struct adm_cmd_connect_afe_port cmd;
  726. int ret = 0;
  727. int index;
  728. pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
  729. port_id, session_id, mode);
  730. port_id = afe_convert_virtual_to_portid(port_id);
  731. if (afe_validate_port(port_id) < 0) {
  732. pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
  733. return -ENODEV;
  734. }
  735. if (this_adm.apr == NULL) {
  736. this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
  737. 0xFFFFFFFF, &this_adm);
  738. if (this_adm.apr == NULL) {
  739. pr_err("%s: Unable to register ADM\n", __func__);
  740. ret = -ENODEV;
  741. return ret;
  742. }
  743. rtac_set_adm_handle(this_adm.apr);
  744. }
  745. index = afe_get_port_index(port_id);
  746. pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
  747. cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  748. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  749. cmd.hdr.pkt_size = sizeof(cmd);
  750. cmd.hdr.src_svc = APR_SVC_ADM;
  751. cmd.hdr.src_domain = APR_DOMAIN_APPS;
  752. cmd.hdr.src_port = port_id;
  753. cmd.hdr.dest_svc = APR_SVC_ADM;
  754. cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
  755. cmd.hdr.dest_port = port_id;
  756. cmd.hdr.token = port_id;
  757. cmd.hdr.opcode = ADM_CMD_DISCONNECT_AFE_PORT;
  758. cmd.mode = mode;
  759. cmd.session_id = session_id;
  760. cmd.afe_port_id = port_id;
  761. atomic_set(&this_adm.copp_stat[index], 0);
  762. ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
  763. if (ret < 0) {
  764. pr_err("%s:ADM enable for port %d failed\n",
  765. __func__, port_id);
  766. ret = -EINVAL;
  767. goto fail_cmd;
  768. }
  769. /* Wait for the callback with copp id */
  770. ret = wait_event_timeout(this_adm.wait,
  771. atomic_read(&this_adm.copp_stat[index]),
  772. msecs_to_jiffies(TIMEOUT_MS));
  773. if (!ret) {
  774. pr_err("%s ADM connect AFE failed for port %d\n", __func__,
  775. port_id);
  776. ret = -EINVAL;
  777. goto fail_cmd;
  778. }
  779. atomic_dec(&this_adm.copp_cnt[index]);
  780. return 0;
  781. fail_cmd:
  782. return ret;
  783. }
  784. int adm_open(int port_id, int path, int rate, int channel_mode, int topology)
  785. {
  786. struct adm_copp_open_command open;
  787. int ret = 0;
  788. int index;
  789. pr_debug("%s: port %d path:%d rate:%d mode:%d\n", __func__,
  790. port_id, path, rate, channel_mode);
  791. port_id = afe_convert_virtual_to_portid(port_id);
  792. if (afe_validate_port(port_id) < 0) {
  793. pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
  794. return -ENODEV;
  795. }
  796. index = afe_get_port_index(port_id);
  797. pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
  798. if (this_adm.apr == NULL) {
  799. this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
  800. 0xFFFFFFFF, &this_adm);
  801. if (this_adm.apr == NULL) {
  802. pr_err("%s: Unable to register ADM\n", __func__);
  803. ret = -ENODEV;
  804. return ret;
  805. }
  806. rtac_set_adm_handle(this_adm.apr);
  807. }
  808. /* Create a COPP if port id are not enabled */
  809. if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
  810. open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  811. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  812. open.hdr.pkt_size = sizeof(open);
  813. open.hdr.src_svc = APR_SVC_ADM;
  814. open.hdr.src_domain = APR_DOMAIN_APPS;
  815. open.hdr.src_port = port_id;
  816. open.hdr.dest_svc = APR_SVC_ADM;
  817. open.hdr.dest_domain = APR_DOMAIN_ADSP;
  818. open.hdr.dest_port = port_id;
  819. open.hdr.token = port_id;
  820. open.hdr.opcode = ADM_CMD_COPP_OPEN;
  821. open.mode = path;
  822. open.endpoint_id1 = port_id;
  823. if (this_adm.ec_ref_rx == 0) {
  824. open.endpoint_id2 = 0xFFFF;
  825. } else if (this_adm.ec_ref_rx && (path != 1)) {
  826. open.endpoint_id2 = this_adm.ec_ref_rx;
  827. this_adm.ec_ref_rx = 0;
  828. }
  829. pr_debug("%s open.endpoint_id1:%d open.endpoint_id2:%d",
  830. __func__, open.endpoint_id1, open.endpoint_id2);
  831. /* convert path to acdb path */
  832. if (path == ADM_PATH_PLAYBACK)
  833. open.topology_id = get_adm_rx_topology();
  834. else {
  835. open.topology_id = get_adm_tx_topology();
  836. if ((open.topology_id ==
  837. VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
  838. (open.topology_id ==
  839. VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
  840. rate = 16000;
  841. }
  842. if (open.topology_id == 0)
  843. open.topology_id = topology;
  844. open.channel_config = channel_mode & 0x00FF;
  845. open.rate = rate;
  846. pr_debug("%s: channel_config=%d port_id=%d rate=%d"
  847. "topology_id=0x%X\n", __func__, open.channel_config,\
  848. open.endpoint_id1, open.rate,\
  849. open.topology_id);
  850. atomic_set(&this_adm.copp_stat[index], 0);
  851. ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
  852. if (ret < 0) {
  853. pr_err("%s:ADM enable for port %d failed\n",
  854. __func__, port_id);
  855. ret = -EINVAL;
  856. goto fail_cmd;
  857. }
  858. /* Wait for the callback with copp id */
  859. ret = wait_event_timeout(this_adm.wait,
  860. atomic_read(&this_adm.copp_stat[index]),
  861. msecs_to_jiffies(TIMEOUT_MS));
  862. if (!ret) {
  863. pr_err("%s ADM open failed for port %d\n", __func__,
  864. port_id);
  865. ret = -EINVAL;
  866. goto fail_cmd;
  867. }
  868. }
  869. atomic_inc(&this_adm.copp_cnt[index]);
  870. return 0;
  871. fail_cmd:
  872. return ret;
  873. }
  874. int adm_multi_ch_copp_pseudo_open_v3(int port_id, int path,
  875. int rate, int channel_mode,
  876. int topology)
  877. {
  878. struct adm_multi_channel_copp_open_v3 open;
  879. int ret = 0;
  880. int index;
  881. pr_debug("%s: port %d path:%d rate:%d mode:%d\n", __func__,
  882. port_id, path, rate, channel_mode);
  883. port_id = afe_convert_virtual_to_portid(port_id);
  884. if (afe_validate_port(port_id) < 0) {
  885. pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
  886. return -ENODEV;
  887. }
  888. index = afe_get_port_index(port_id);
  889. pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
  890. if (this_adm.apr == NULL) {
  891. this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
  892. 0xFFFFFFFF, &this_adm);
  893. if (this_adm.apr == NULL) {
  894. pr_err("%s: Unable to register ADM\n", __func__);
  895. ret = -ENODEV;
  896. return ret;
  897. }
  898. rtac_set_adm_handle(this_adm.apr);
  899. }
  900. {
  901. open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  902. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  903. open.hdr.pkt_size = sizeof(open);
  904. open.hdr.src_svc = APR_SVC_ADM;
  905. open.hdr.src_domain = APR_DOMAIN_APPS;
  906. open.hdr.src_port = port_id;
  907. open.hdr.dest_svc = APR_SVC_ADM;
  908. open.hdr.dest_domain = APR_DOMAIN_ADSP;
  909. open.hdr.dest_port = port_id;
  910. open.hdr.token = port_id;
  911. open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3;
  912. memset(open.dev_channel_mapping, 0, 8);
  913. if (channel_mode == 1) {
  914. open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
  915. } else if (channel_mode == 2) {
  916. open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
  917. open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
  918. } else if (channel_mode == 4) {
  919. open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
  920. open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
  921. open.dev_channel_mapping[2] = PCM_CHANNEL_LS;
  922. open.dev_channel_mapping[3] = PCM_CHANNEL_RS;
  923. } else if (channel_mode == 6) {
  924. open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
  925. open.dev_channel_mapping[1] = PCM_CHANNEL_FL;
  926. open.dev_channel_mapping[2] = PCM_CHANNEL_FR;
  927. open.dev_channel_mapping[3] = PCM_CHANNEL_LS;
  928. open.dev_channel_mapping[4] = PCM_CHANNEL_RS;
  929. open.dev_channel_mapping[5] = PCM_CHANNEL_LFE;
  930. } else {
  931. pr_err("%s invalid num_chan %d\n", __func__,
  932. channel_mode);
  933. return -EINVAL;
  934. }
  935. open.mode = path;
  936. open.endpoint_id1 = port_id;
  937. open.endpoint_id2 = 0xFFFF;
  938. open.bit_width = 16;
  939. if (path == ADM_PATH_PLAYBACK)
  940. open.topology_id = get_adm_rx_topology();
  941. else {
  942. open.topology_id = get_adm_tx_topology();
  943. if ((open.topology_id ==
  944. VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
  945. (open.topology_id ==
  946. VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
  947. rate = 16000;
  948. }
  949. if (open.topology_id == 0)
  950. open.topology_id = topology;
  951. open.channel_config = channel_mode & 0x00FF;
  952. open.rate = rate;
  953. open.flags = 0;
  954. pr_debug("%s: channel_config=%d port_id=%d rate=%d" \
  955. "topology_id=0x%X\n", __func__, open.channel_config,\
  956. open.endpoint_id1, open.rate,\
  957. open.topology_id);
  958. atomic_set(&this_adm.copp_stat[index], 0);
  959. ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
  960. if (ret < 0) {
  961. pr_err("%s:ADM enable for port %d failed\n",
  962. __func__, port_id);
  963. ret = -EINVAL;
  964. goto fail_cmd;
  965. }
  966. ret = wait_event_timeout(this_adm.wait,
  967. atomic_read(&this_adm.copp_stat[index]),
  968. msecs_to_jiffies(TIMEOUT_MS));
  969. if (!ret) {
  970. pr_err("%s ADM open failed for port %d\n", __func__,
  971. port_id);
  972. ret = -EINVAL;
  973. goto fail_cmd;
  974. }
  975. }
  976. atomic_inc(&this_adm.copp_cnt[index]);
  977. return 0;
  978. fail_cmd:
  979. return ret;
  980. }
  981. int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
  982. int topology, int perfmode)
  983. {
  984. struct adm_multi_ch_copp_open_command open;
  985. int ret = 0;
  986. int index;
  987. pr_debug("%s: port %d path:%d rate:%d channel :%d\n", __func__,
  988. port_id, path, rate, channel_mode);
  989. port_id = afe_convert_virtual_to_portid(port_id);
  990. if (afe_validate_port(port_id) < 0) {
  991. pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
  992. return -ENODEV;
  993. }
  994. index = afe_get_port_index(port_id);
  995. pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
  996. if (this_adm.apr == NULL) {
  997. this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
  998. 0xFFFFFFFF, &this_adm);
  999. if (this_adm.apr == NULL) {
  1000. pr_err("%s: Unable to register ADM\n", __func__);
  1001. ret = -ENODEV;
  1002. return ret;
  1003. }
  1004. rtac_set_adm_handle(this_adm.apr);
  1005. }
  1006. /* Create a COPP if port id are not enabled */
  1007. if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
  1008. open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  1009. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  1010. open.hdr.pkt_size =
  1011. sizeof(struct adm_multi_ch_copp_open_command);
  1012. if (perfmode) {
  1013. pr_debug("%s Performance mode", __func__);
  1014. open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3;
  1015. open.flags = ADM_MULTI_CH_COPP_OPEN_PERF_MODE_BIT;
  1016. open.reserved = PCM_BITS_PER_SAMPLE;
  1017. } else {
  1018. open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN;
  1019. open.reserved = 0;
  1020. }
  1021. memset(open.dev_channel_mapping, 0, 8);
  1022. if (channel_mode == 1) {
  1023. open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
  1024. } else if (channel_mode == 2) {
  1025. open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
  1026. open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
  1027. } else if (channel_mode == 4) {
  1028. open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
  1029. open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
  1030. open.dev_channel_mapping[2] = PCM_CHANNEL_RB;
  1031. open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
  1032. } else if (channel_mode == 6) {
  1033. open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
  1034. open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
  1035. open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
  1036. open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
  1037. open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
  1038. open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
  1039. } else if (channel_mode == 8) {
  1040. open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
  1041. open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
  1042. open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
  1043. open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
  1044. open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
  1045. open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
  1046. open.dev_channel_mapping[6] = PCM_CHANNEL_FLC;
  1047. open.dev_channel_mapping[7] = PCM_CHANNEL_FRC;
  1048. } else {
  1049. pr_err("%s invalid num_chan %d\n", __func__,
  1050. channel_mode);
  1051. return -EINVAL;
  1052. }
  1053. open.hdr.src_svc = APR_SVC_ADM;
  1054. open.hdr.src_domain = APR_DOMAIN_APPS;
  1055. open.hdr.src_port = port_id;
  1056. open.hdr.dest_svc = APR_SVC_ADM;
  1057. open.hdr.dest_domain = APR_DOMAIN_ADSP;
  1058. open.hdr.dest_port = port_id;
  1059. open.hdr.token = port_id;
  1060. open.mode = path;
  1061. open.endpoint_id1 = port_id;
  1062. if (this_adm.ec_ref_rx == 0) {
  1063. open.endpoint_id2 = 0xFFFF;
  1064. } else if (this_adm.ec_ref_rx && (path != 1)) {
  1065. open.endpoint_id2 = this_adm.ec_ref_rx;
  1066. this_adm.ec_ref_rx = 0;
  1067. }
  1068. pr_debug("%s open.endpoint_id1:%d open.endpoint_id2:%d",
  1069. __func__, open.endpoint_id1, open.endpoint_id2);
  1070. /* convert path to acdb path */
  1071. if (path == ADM_PATH_PLAYBACK)
  1072. open.topology_id = get_adm_rx_topology();
  1073. else {
  1074. open.topology_id = get_adm_tx_topology();
  1075. if ((open.topology_id ==
  1076. VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
  1077. (open.topology_id ==
  1078. VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
  1079. rate = 16000;
  1080. }
  1081. if (open.topology_id == 0)
  1082. open.topology_id = topology;
  1083. open.channel_config = channel_mode & 0x00FF;
  1084. open.rate = rate;
  1085. pr_debug("%s: channel_config=%d port_id=%d rate=%d"
  1086. " topology_id=0x%X\n", __func__, open.channel_config,
  1087. open.endpoint_id1, open.rate,
  1088. open.topology_id);
  1089. atomic_set(&this_adm.copp_stat[index], 0);
  1090. ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
  1091. if (ret < 0) {
  1092. pr_err("%s:ADM enable for port %d failed\n",
  1093. __func__, port_id);
  1094. ret = -EINVAL;
  1095. goto fail_cmd;
  1096. }
  1097. /* Wait for the callback with copp id */
  1098. ret = wait_event_timeout(this_adm.wait,
  1099. atomic_read(&this_adm.copp_stat[index]),
  1100. msecs_to_jiffies(TIMEOUT_MS));
  1101. if (!ret) {
  1102. pr_err("%s ADM open failed for port %d\n", __func__,
  1103. port_id);
  1104. ret = -EINVAL;
  1105. goto fail_cmd;
  1106. }
  1107. }
  1108. atomic_inc(&this_adm.copp_cnt[index]);
  1109. return 0;
  1110. fail_cmd:
  1111. return ret;
  1112. }
  1113. int adm_matrix_map(int session_id, int path, int num_copps,
  1114. unsigned int *port_id, int copp_id)
  1115. {
  1116. struct adm_routings_command route;
  1117. int ret = 0, i = 0;
  1118. /* Assumes port_ids have already been validated during adm_open */
  1119. int index = afe_get_port_index(copp_id);
  1120. int copp_cnt;
  1121. if (index < 0 || index >= AFE_MAX_PORTS) {
  1122. pr_err("%s: invalid port idx %d token %d\n",
  1123. __func__, index, copp_id);
  1124. return 0;
  1125. }
  1126. pr_debug("%s: session 0x%x path:%d num_copps:%d port_id[0]:%d\n",
  1127. __func__, session_id, path, num_copps, port_id[0]);
  1128. route.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  1129. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  1130. route.hdr.pkt_size = sizeof(route);
  1131. route.hdr.src_svc = 0;
  1132. route.hdr.src_domain = APR_DOMAIN_APPS;
  1133. route.hdr.src_port = copp_id;
  1134. route.hdr.dest_svc = APR_SVC_ADM;
  1135. route.hdr.dest_domain = APR_DOMAIN_ADSP;
  1136. route.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
  1137. route.hdr.token = copp_id;
  1138. route.hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS;
  1139. route.num_sessions = 1;
  1140. route.session[0].id = session_id;
  1141. if (num_copps < ADM_MAX_COPPS) {
  1142. copp_cnt = num_copps;
  1143. } else {
  1144. copp_cnt = ADM_MAX_COPPS;
  1145. /* print out warning for now as playback/capture to/from
  1146. * COPPs more than maximum allowed is extremely unlikely
  1147. */
  1148. pr_warn("%s: max out routable COPPs\n", __func__);
  1149. }
  1150. route.session[0].num_copps = copp_cnt;
  1151. for (i = 0; i < copp_cnt; i++) {
  1152. int tmp;
  1153. port_id[i] = afe_convert_virtual_to_portid(port_id[i]);
  1154. tmp = afe_get_port_index(port_id[i]);
  1155. pr_debug("%s: port_id[%d]: %d, index: %d\n", __func__, i,
  1156. port_id[i], tmp);
  1157. if (tmp >= 0 && tmp < AFE_MAX_PORTS)
  1158. route.session[0].copp_id[i] =
  1159. atomic_read(&this_adm.copp_id[tmp]);
  1160. }
  1161. if (copp_cnt % 2)
  1162. route.session[0].copp_id[i] = 0;
  1163. switch (path) {
  1164. case 0x1:
  1165. route.path = AUDIO_RX;
  1166. break;
  1167. case 0x2:
  1168. case 0x3:
  1169. route.path = AUDIO_TX;
  1170. break;
  1171. default:
  1172. pr_err("%s: Wrong path set[%d]\n", __func__, path);
  1173. break;
  1174. }
  1175. atomic_set(&this_adm.copp_stat[index], 0);
  1176. ret = apr_send_pkt(this_adm.apr, (uint32_t *)&route);
  1177. if (ret < 0) {
  1178. pr_err("%s: ADM routing for port %d failed\n",
  1179. __func__, port_id[0]);
  1180. ret = -EINVAL;
  1181. goto fail_cmd;
  1182. }
  1183. ret = wait_event_timeout(this_adm.wait,
  1184. atomic_read(&this_adm.copp_stat[index]),
  1185. msecs_to_jiffies(TIMEOUT_MS));
  1186. if (!ret) {
  1187. pr_err("%s: ADM cmd Route failed for port %d\n",
  1188. __func__, port_id[0]);
  1189. ret = -EINVAL;
  1190. goto fail_cmd;
  1191. }
  1192. for (i = 0; i < num_copps; i++)
  1193. send_adm_cal(port_id[i], path);
  1194. for (i = 0; i < num_copps; i++) {
  1195. int tmp;
  1196. tmp = afe_get_port_index(port_id[i]);
  1197. if (tmp >= 0 && tmp < AFE_MAX_PORTS)
  1198. rtac_add_adm_device(port_id[i],
  1199. atomic_read(&this_adm.copp_id[tmp]),
  1200. path, session_id);
  1201. else
  1202. pr_debug("%s: Invalid port index %d",
  1203. __func__, tmp);
  1204. }
  1205. return 0;
  1206. fail_cmd:
  1207. return ret;
  1208. }
  1209. int adm_memory_map_regions(uint32_t *buf_add, uint32_t mempool_id,
  1210. uint32_t *bufsz, uint32_t bufcnt)
  1211. {
  1212. struct adm_cmd_memory_map_regions *mmap_regions = NULL;
  1213. struct adm_memory_map_regions *mregions = NULL;
  1214. void *mmap_region_cmd = NULL;
  1215. void *payload = NULL;
  1216. int ret = 0;
  1217. int i = 0;
  1218. int cmd_size = 0;
  1219. pr_debug("%s\n", __func__);
  1220. if (this_adm.apr == NULL) {
  1221. this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
  1222. 0xFFFFFFFF, &this_adm);
  1223. if (this_adm.apr == NULL) {
  1224. pr_err("%s: Unable to register ADM\n", __func__);
  1225. ret = -ENODEV;
  1226. return ret;
  1227. }
  1228. rtac_set_adm_handle(this_adm.apr);
  1229. }
  1230. cmd_size = sizeof(struct adm_cmd_memory_map_regions)
  1231. + sizeof(struct adm_memory_map_regions) * bufcnt;
  1232. mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
  1233. if (!mmap_region_cmd) {
  1234. pr_err("%s: allocate mmap_region_cmd failed\n", __func__);
  1235. return -ENOMEM;
  1236. }
  1237. mmap_regions = (struct adm_cmd_memory_map_regions *)mmap_region_cmd;
  1238. mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  1239. APR_HDR_LEN(APR_HDR_SIZE),
  1240. APR_PKT_VER);
  1241. mmap_regions->hdr.pkt_size = cmd_size;
  1242. mmap_regions->hdr.src_port = 0;
  1243. mmap_regions->hdr.dest_port = 0;
  1244. mmap_regions->hdr.token = 0;
  1245. mmap_regions->hdr.opcode = ADM_CMD_MEMORY_MAP_REGIONS;
  1246. mmap_regions->mempool_id = mempool_id & 0x00ff;
  1247. mmap_regions->nregions = bufcnt & 0x00ff;
  1248. pr_debug("%s: map_regions->nregions = %d\n", __func__,
  1249. mmap_regions->nregions);
  1250. payload = ((u8 *) mmap_region_cmd +
  1251. sizeof(struct adm_cmd_memory_map_regions));
  1252. mregions = (struct adm_memory_map_regions *)payload;
  1253. for (i = 0; i < bufcnt; i++) {
  1254. mregions->phys = buf_add[i];
  1255. mregions->buf_size = bufsz[i];
  1256. ++mregions;
  1257. }
  1258. atomic_set(&this_adm.copp_stat[0], 0);
  1259. ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
  1260. if (ret < 0) {
  1261. pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
  1262. mmap_regions->hdr.opcode, ret);
  1263. ret = -EINVAL;
  1264. goto fail_cmd;
  1265. }
  1266. ret = wait_event_timeout(this_adm.wait,
  1267. atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
  1268. if (!ret) {
  1269. pr_err("%s: timeout. waited for memory_map\n", __func__);
  1270. ret = -EINVAL;
  1271. goto fail_cmd;
  1272. }
  1273. fail_cmd:
  1274. kfree(mmap_region_cmd);
  1275. return ret;
  1276. }
  1277. int adm_memory_unmap_regions(uint32_t *buf_add, uint32_t *bufsz,
  1278. uint32_t bufcnt)
  1279. {
  1280. struct adm_cmd_memory_unmap_regions *unmap_regions = NULL;
  1281. struct adm_memory_unmap_regions *mregions = NULL;
  1282. void *unmap_region_cmd = NULL;
  1283. void *payload = NULL;
  1284. int ret = 0;
  1285. int i = 0;
  1286. int cmd_size = 0;
  1287. pr_debug("%s\n", __func__);
  1288. if (this_adm.apr == NULL) {
  1289. pr_err("%s APR handle NULL\n", __func__);
  1290. return -EINVAL;
  1291. }
  1292. cmd_size = sizeof(struct adm_cmd_memory_unmap_regions)
  1293. + sizeof(struct adm_memory_unmap_regions) * bufcnt;
  1294. unmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
  1295. if (!unmap_region_cmd) {
  1296. pr_err("%s: allocate unmap_region_cmd failed\n", __func__);
  1297. return -ENOMEM;
  1298. }
  1299. unmap_regions = (struct adm_cmd_memory_unmap_regions *)
  1300. unmap_region_cmd;
  1301. unmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  1302. APR_HDR_LEN(APR_HDR_SIZE),
  1303. APR_PKT_VER);
  1304. unmap_regions->hdr.pkt_size = cmd_size;
  1305. unmap_regions->hdr.src_port = 0;
  1306. unmap_regions->hdr.dest_port = 0;
  1307. unmap_regions->hdr.token = 0;
  1308. unmap_regions->hdr.opcode = ADM_CMD_MEMORY_UNMAP_REGIONS;
  1309. unmap_regions->nregions = bufcnt & 0x00ff;
  1310. unmap_regions->reserved = 0;
  1311. pr_debug("%s: unmap_regions->nregions = %d\n", __func__,
  1312. unmap_regions->nregions);
  1313. payload = ((u8 *) unmap_region_cmd +
  1314. sizeof(struct adm_cmd_memory_unmap_regions));
  1315. mregions = (struct adm_memory_unmap_regions *)payload;
  1316. for (i = 0; i < bufcnt; i++) {
  1317. mregions->phys = buf_add[i];
  1318. ++mregions;
  1319. }
  1320. atomic_set(&this_adm.copp_stat[0], 0);
  1321. ret = apr_send_pkt(this_adm.apr, (uint32_t *) unmap_region_cmd);
  1322. if (ret < 0) {
  1323. pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
  1324. unmap_regions->hdr.opcode, ret);
  1325. ret = -EINVAL;
  1326. goto fail_cmd;
  1327. }
  1328. ret = wait_event_timeout(this_adm.wait,
  1329. atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
  1330. if (!ret) {
  1331. pr_err("%s: timeout. waited for memory_unmap\n", __func__);
  1332. ret = -EINVAL;
  1333. goto fail_cmd;
  1334. }
  1335. fail_cmd:
  1336. kfree(unmap_region_cmd);
  1337. return ret;
  1338. }
  1339. int adm_get_copp_id(int port_index)
  1340. {
  1341. pr_debug("%s\n", __func__);
  1342. if (port_index < 0) {
  1343. pr_err("%s: invalid port_id = %d\n", __func__, port_index);
  1344. return -EINVAL;
  1345. }
  1346. return atomic_read(&this_adm.copp_id[port_index]);
  1347. }
  1348. void adm_ec_ref_rx_id(int port_id)
  1349. {
  1350. this_adm.ec_ref_rx = port_id;
  1351. pr_debug("%s ec_ref_rx:%d", __func__, this_adm.ec_ref_rx);
  1352. }
  1353. int adm_pseudo_close(int port_id)
  1354. {
  1355. struct apr_hdr close;
  1356. int ret = 0, i = 0;
  1357. int index = 0;
  1358. int pseudo_copp_cnt;
  1359. index = afe_get_port_index(port_id);
  1360. if (afe_validate_port(port_id) < 0)
  1361. return -EINVAL;
  1362. pseudo_copp_cnt = atomic_read(&this_adm.copp_cnt[index]);
  1363. pr_debug("%s port_id=%d index %d copp_cnt %d\n", __func__, port_id,
  1364. index, pseudo_copp_cnt);
  1365. for (i = 0; i < pseudo_copp_cnt; i++) {
  1366. close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  1367. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  1368. close.pkt_size = sizeof(close);
  1369. close.src_svc = APR_SVC_ADM;
  1370. close.src_domain = APR_DOMAIN_APPS;
  1371. close.src_port = port_id;
  1372. close.dest_svc = APR_SVC_ADM;
  1373. close.dest_domain = APR_DOMAIN_ADSP;
  1374. close.dest_port = pseudo_copp[i];
  1375. close.token = port_id;
  1376. close.opcode = ADM_CMD_COPP_CLOSE;
  1377. atomic_set(&this_adm.copp_id[index], RESET_COPP_ID);
  1378. atomic_set(&this_adm.copp_stat[index], 0);
  1379. pr_debug("%s:coppid %d portid=%d index=%d coppcnt=%d\n",
  1380. __func__,
  1381. atomic_read(&this_adm.copp_id[index]),
  1382. port_id, index,
  1383. atomic_read(&this_adm.copp_cnt[index]));
  1384. ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
  1385. ret = wait_event_timeout(this_adm.wait,
  1386. atomic_read(&this_adm.copp_stat[index]),
  1387. msecs_to_jiffies(TIMEOUT_MS));
  1388. }
  1389. atomic_set(&this_adm.copp_cnt[index], 0);
  1390. return ret;
  1391. }
  1392. int adm_close(int port_id)
  1393. {
  1394. struct apr_hdr close;
  1395. int ret = 0;
  1396. int index = 0;
  1397. port_id = afe_convert_virtual_to_portid(port_id);
  1398. index = afe_get_port_index(port_id);
  1399. if (afe_validate_port(port_id) < 0)
  1400. return -EINVAL;
  1401. pr_debug("%s port_id=%d index %d\n", __func__, port_id, index);
  1402. if (!(atomic_read(&this_adm.copp_cnt[index]))) {
  1403. pr_err("%s: copp count for port[%d]is 0\n", __func__, port_id);
  1404. goto fail_cmd;
  1405. }
  1406. atomic_dec(&this_adm.copp_cnt[index]);
  1407. if (!(atomic_read(&this_adm.copp_cnt[index]))) {
  1408. close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
  1409. APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
  1410. close.pkt_size = sizeof(close);
  1411. close.src_svc = APR_SVC_ADM;
  1412. close.src_domain = APR_DOMAIN_APPS;
  1413. close.src_port = port_id;
  1414. close.dest_svc = APR_SVC_ADM;
  1415. close.dest_domain = APR_DOMAIN_ADSP;
  1416. close.dest_port = atomic_read(&this_adm.copp_id[index]);
  1417. close.token = port_id;
  1418. close.opcode = ADM_CMD_COPP_CLOSE;
  1419. atomic_set(&this_adm.copp_id[index], RESET_COPP_ID);
  1420. atomic_set(&this_adm.copp_stat[index], 0);
  1421. pr_debug("%s:coppid %d portid=%d index=%d coppcnt=%d\n",
  1422. __func__,
  1423. atomic_read(&this_adm.copp_id[index]),
  1424. port_id, index,
  1425. atomic_read(&this_adm.copp_cnt[index]));
  1426. ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
  1427. if (ret < 0) {
  1428. pr_err("%s ADM close failed\n", __func__);
  1429. ret = -EINVAL;
  1430. goto fail_cmd;
  1431. }
  1432. ret = wait_event_timeout(this_adm.wait,
  1433. atomic_read(&this_adm.copp_stat[index]),
  1434. msecs_to_jiffies(TIMEOUT_MS));
  1435. if (!ret) {
  1436. pr_err("%s: ADM cmd Route failed for port %d\n",
  1437. __func__, port_id);
  1438. ret = -EINVAL;
  1439. goto fail_cmd;
  1440. }
  1441. rtac_remove_adm_device(port_id);
  1442. }
  1443. fail_cmd:
  1444. return ret;
  1445. }
  1446. static int __init adm_init(void)
  1447. {
  1448. int i = 0;
  1449. init_waitqueue_head(&this_adm.wait);
  1450. this_adm.apr = NULL;
  1451. for (i = 0; i < AFE_MAX_PORTS; i++) {
  1452. atomic_set(&this_adm.copp_id[i], RESET_COPP_ID);
  1453. atomic_set(&this_adm.copp_cnt[i], 0);
  1454. atomic_set(&this_adm.copp_stat[i], 0);
  1455. }
  1456. return 0;
  1457. }
  1458. device_initcall(adm_init);