msm-transcode-loopback-q6-v2.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552
  1. /* Copyright (c) 2017-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. #include <linux/init.h>
  13. #include <linux/err.h>
  14. #include <linux/module.h>
  15. #include <linux/moduleparam.h>
  16. #include <linux/time.h>
  17. #include <linux/math64.h>
  18. #include <linux/wait.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/slab.h>
  21. #include <sound/core.h>
  22. #include <sound/soc.h>
  23. #include <sound/soc-dapm.h>
  24. #include <sound/pcm.h>
  25. #include <sound/initval.h>
  26. #include <sound/control.h>
  27. #include <sound/audio_effects.h>
  28. #include <sound/pcm_params.h>
  29. #include <sound/timer.h>
  30. #include <sound/tlv.h>
  31. #include <sound/compress_params.h>
  32. #include <sound/compress_offload.h>
  33. #include <sound/compress_driver.h>
  34. #include <dsp/msm_audio_ion.h>
  35. #include <dsp/apr_audio-v2.h>
  36. #include <dsp/q6asm-v2.h>
  37. #include <dsp/q6audio-v2.h>
  38. #include <dsp/msm-audio-effects-q6-v2.h>
  39. #include "msm-pcm-routing-v2.h"
  40. #include "msm-qti-pp-config.h"
  41. #define LOOPBACK_SESSION_MAX_NUM_STREAMS 2
  42. /* Max volume corresponding to 24dB */
  43. #define TRANSCODE_LR_VOL_MAX_DB 0xFFFF
  44. #define APP_TYPE_CONFIG_IDX_APP_TYPE 0
  45. #define APP_TYPE_CONFIG_IDX_ACDB_ID 1
  46. #define APP_TYPE_CONFIG_IDX_SAMPLE_RATE 2
  47. #define APP_TYPE_CONFIG_IDX_BE_ID 3
  48. static DEFINE_MUTEX(transcode_loopback_session_lock);
  49. struct msm_transcode_audio_effects {
  50. struct bass_boost_params bass_boost;
  51. struct pbe_params pbe;
  52. struct virtualizer_params virtualizer;
  53. struct reverb_params reverb;
  54. struct eq_params equalizer;
  55. struct soft_volume_params volume;
  56. };
  57. struct trans_loopback_pdata {
  58. struct snd_compr_stream *cstream[MSM_FRONTEND_DAI_MAX];
  59. uint32_t master_gain;
  60. int perf_mode;
  61. struct msm_transcode_audio_effects *audio_effects[MSM_FRONTEND_DAI_MAX];
  62. };
  63. struct loopback_stream {
  64. struct snd_compr_stream *cstream;
  65. uint32_t codec_format;
  66. bool start;
  67. };
  68. enum loopback_session_state {
  69. /* One or both streams not opened */
  70. LOOPBACK_SESSION_CLOSE = 0,
  71. /* Loopback streams opened */
  72. LOOPBACK_SESSION_READY,
  73. /* Loopback streams opened and formats configured */
  74. LOOPBACK_SESSION_START,
  75. /* Trigger issued on either of streams when in START state */
  76. LOOPBACK_SESSION_RUN
  77. };
  78. struct msm_transcode_loopback {
  79. struct loopback_stream source;
  80. struct loopback_stream sink;
  81. struct snd_compr_caps source_compr_cap;
  82. struct snd_compr_caps sink_compr_cap;
  83. uint32_t instance;
  84. uint32_t num_streams;
  85. int session_state;
  86. struct mutex lock;
  87. int session_id;
  88. struct audio_client *audio_client;
  89. };
  90. /* Transcode loopback global info struct */
  91. static struct msm_transcode_loopback transcode_info;
  92. static void loopback_event_handler(uint32_t opcode,
  93. uint32_t token, uint32_t *payload, void *priv)
  94. {
  95. struct msm_transcode_loopback *trans =
  96. (struct msm_transcode_loopback *)priv;
  97. struct snd_soc_pcm_runtime *rtd;
  98. struct snd_compr_stream *cstream;
  99. struct audio_client *ac;
  100. int stream_id;
  101. int ret;
  102. if (!trans || !payload) {
  103. pr_err("%s: rtd or payload is NULL\n", __func__);
  104. return;
  105. }
  106. cstream = trans->sink.cstream;
  107. ac = trans->audio_client;
  108. /*
  109. * Token for rest of the compressed commands use to set
  110. * session id, stream id, dir etc.
  111. */
  112. stream_id = q6asm_get_stream_id_from_token(token);
  113. switch (opcode) {
  114. case ASM_STREAM_CMD_ENCDEC_EVENTS:
  115. case ASM_IEC_61937_MEDIA_FMT_EVENT:
  116. pr_debug("%s: Handling stream event : 0X%x\n",
  117. __func__, opcode);
  118. rtd = cstream->private_data;
  119. if (!rtd) {
  120. pr_err("%s: rtd is NULL\n", __func__);
  121. return;
  122. }
  123. ret = msm_adsp_inform_mixer_ctl(rtd, payload);
  124. if (ret) {
  125. pr_err("%s: failed to inform mixer ctrl. err = %d\n",
  126. __func__, ret);
  127. return;
  128. }
  129. break;
  130. case APR_BASIC_RSP_RESULT: {
  131. switch (payload[0]) {
  132. case ASM_SESSION_CMD_RUN_V2:
  133. pr_debug("%s: ASM_SESSION_CMD_RUN_V2:", __func__);
  134. pr_debug("token 0x%x, stream id %d\n", token,
  135. stream_id);
  136. break;
  137. case ASM_STREAM_CMD_CLOSE:
  138. pr_debug("%s: ASM_DATA_CMD_CLOSE:", __func__);
  139. pr_debug("token 0x%x, stream id %d\n", token,
  140. stream_id);
  141. break;
  142. default:
  143. break;
  144. }
  145. break;
  146. }
  147. default:
  148. pr_debug("%s: Not Supported Event opcode[0x%x]\n",
  149. __func__, opcode);
  150. break;
  151. }
  152. }
  153. static void populate_codec_list(struct msm_transcode_loopback *trans,
  154. struct snd_compr_stream *cstream)
  155. {
  156. struct snd_compr_caps compr_cap;
  157. pr_debug("%s\n", __func__);
  158. memset(&compr_cap, 0, sizeof(struct snd_compr_caps));
  159. if (cstream->direction == SND_COMPRESS_CAPTURE) {
  160. compr_cap.direction = SND_COMPRESS_CAPTURE;
  161. compr_cap.num_codecs = 3;
  162. compr_cap.codecs[0] = SND_AUDIOCODEC_PCM;
  163. compr_cap.codecs[1] = SND_AUDIOCODEC_AC3;
  164. compr_cap.codecs[2] = SND_AUDIOCODEC_EAC3;
  165. memcpy(&trans->source_compr_cap, &compr_cap,
  166. sizeof(struct snd_compr_caps));
  167. }
  168. if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  169. compr_cap.direction = SND_COMPRESS_PLAYBACK;
  170. compr_cap.num_codecs = 1;
  171. compr_cap.codecs[0] = SND_AUDIOCODEC_PCM;
  172. memcpy(&trans->sink_compr_cap, &compr_cap,
  173. sizeof(struct snd_compr_caps));
  174. }
  175. }
  176. static int msm_transcode_loopback_open(struct snd_compr_stream *cstream)
  177. {
  178. int ret = 0;
  179. struct snd_compr_runtime *runtime;
  180. struct snd_soc_pcm_runtime *rtd;
  181. struct msm_transcode_loopback *trans = &transcode_info;
  182. struct trans_loopback_pdata *pdata;
  183. if (cstream == NULL) {
  184. pr_err("%s: Invalid substream\n", __func__);
  185. return -EINVAL;
  186. }
  187. runtime = cstream->runtime;
  188. rtd = snd_pcm_substream_chip(cstream);
  189. pdata = snd_soc_platform_get_drvdata(rtd->platform);
  190. pdata->cstream[rtd->dai_link->id] = cstream;
  191. pdata->audio_effects[rtd->dai_link->id] =
  192. kzalloc(sizeof(struct msm_transcode_audio_effects), GFP_KERNEL);
  193. if (pdata->audio_effects[rtd->dai_link->id] == NULL) {
  194. ret = -ENOMEM;
  195. goto effect_error;
  196. }
  197. mutex_lock(&trans->lock);
  198. if (trans->num_streams > LOOPBACK_SESSION_MAX_NUM_STREAMS) {
  199. pr_err("msm_transcode_open failed..invalid stream\n");
  200. ret = -EINVAL;
  201. goto exit;
  202. }
  203. if (cstream->direction == SND_COMPRESS_CAPTURE) {
  204. if (trans->source.cstream == NULL) {
  205. trans->source.cstream = cstream;
  206. trans->num_streams++;
  207. } else {
  208. pr_err("%s: capture stream already opened\n",
  209. __func__);
  210. ret = -EINVAL;
  211. goto exit;
  212. }
  213. } else if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  214. if (trans->sink.cstream == NULL) {
  215. trans->sink.cstream = cstream;
  216. trans->num_streams++;
  217. } else {
  218. pr_debug("%s: playback stream already opened\n",
  219. __func__);
  220. ret = -EINVAL;
  221. goto exit;
  222. }
  223. msm_adsp_init_mixer_ctl_pp_event_queue(rtd);
  224. }
  225. pr_debug("%s: num stream%d, stream name %s\n", __func__,
  226. trans->num_streams, cstream->name);
  227. populate_codec_list(trans, cstream);
  228. if (trans->num_streams == LOOPBACK_SESSION_MAX_NUM_STREAMS) {
  229. pr_debug("%s: Moving loopback session to READY state %d\n",
  230. __func__, trans->session_state);
  231. trans->session_state = LOOPBACK_SESSION_READY;
  232. }
  233. runtime->private_data = trans;
  234. exit:
  235. mutex_unlock(&trans->lock);
  236. if ((pdata->audio_effects[rtd->dai_link->id] != NULL) && (ret < 0)) {
  237. kfree(pdata->audio_effects[rtd->dai_link->id]);
  238. pdata->audio_effects[rtd->dai_link->id] = NULL;
  239. }
  240. effect_error:
  241. return ret;
  242. }
  243. static void stop_transcoding(struct msm_transcode_loopback *trans)
  244. {
  245. struct snd_soc_pcm_runtime *soc_pcm_rx;
  246. struct snd_soc_pcm_runtime *soc_pcm_tx;
  247. if (trans->audio_client != NULL) {
  248. q6asm_cmd(trans->audio_client, CMD_CLOSE);
  249. if (trans->sink.cstream != NULL) {
  250. soc_pcm_rx = trans->sink.cstream->private_data;
  251. msm_pcm_routing_dereg_phy_stream(
  252. soc_pcm_rx->dai_link->id,
  253. SND_COMPRESS_PLAYBACK);
  254. }
  255. if (trans->source.cstream != NULL) {
  256. soc_pcm_tx = trans->source.cstream->private_data;
  257. msm_pcm_routing_dereg_phy_stream(
  258. soc_pcm_tx->dai_link->id,
  259. SND_COMPRESS_CAPTURE);
  260. }
  261. q6asm_audio_client_free(trans->audio_client);
  262. trans->audio_client = NULL;
  263. }
  264. }
  265. static int msm_transcode_loopback_free(struct snd_compr_stream *cstream)
  266. {
  267. struct snd_compr_runtime *runtime = cstream->runtime;
  268. struct msm_transcode_loopback *trans = runtime->private_data;
  269. struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(cstream);
  270. struct trans_loopback_pdata *pdata;
  271. int ret = 0;
  272. pdata = snd_soc_platform_get_drvdata(rtd->platform);
  273. mutex_lock(&trans->lock);
  274. if (pdata->audio_effects[rtd->dai_link->id] != NULL) {
  275. kfree(pdata->audio_effects[rtd->dai_link->id]);
  276. pdata->audio_effects[rtd->dai_link->id] = NULL;
  277. }
  278. pr_debug("%s: Transcode loopback end:%d, streams %d\n", __func__,
  279. cstream->direction, trans->num_streams);
  280. trans->num_streams--;
  281. stop_transcoding(trans);
  282. if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  283. memset(&trans->sink, 0, sizeof(struct loopback_stream));
  284. msm_adsp_clean_mixer_ctl_pp_event_queue(rtd);
  285. } else if (cstream->direction == SND_COMPRESS_CAPTURE) {
  286. memset(&trans->source, 0, sizeof(struct loopback_stream));
  287. }
  288. trans->session_state = LOOPBACK_SESSION_CLOSE;
  289. mutex_unlock(&trans->lock);
  290. return ret;
  291. }
  292. static int msm_transcode_loopback_trigger(struct snd_compr_stream *cstream,
  293. int cmd)
  294. {
  295. struct snd_compr_runtime *runtime = cstream->runtime;
  296. struct msm_transcode_loopback *trans = runtime->private_data;
  297. switch (cmd) {
  298. case SNDRV_PCM_TRIGGER_START:
  299. case SNDRV_PCM_TRIGGER_RESUME:
  300. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  301. if (trans->session_state == LOOPBACK_SESSION_START) {
  302. pr_debug("%s: Issue Loopback session %d RUN\n",
  303. __func__, trans->instance);
  304. q6asm_run_nowait(trans->audio_client, 0, 0, 0);
  305. trans->session_state = LOOPBACK_SESSION_RUN;
  306. }
  307. break;
  308. case SNDRV_PCM_TRIGGER_SUSPEND:
  309. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  310. case SNDRV_PCM_TRIGGER_STOP:
  311. pr_debug("%s: Issue Loopback session %d STOP\n", __func__,
  312. trans->instance);
  313. if (trans->session_state == LOOPBACK_SESSION_RUN)
  314. q6asm_cmd_nowait(trans->audio_client, CMD_PAUSE);
  315. trans->session_state = LOOPBACK_SESSION_START;
  316. break;
  317. default:
  318. break;
  319. }
  320. return 0;
  321. }
  322. static int msm_transcode_set_render_window(struct audio_client *ac,
  323. uint32_t ws_lsw, uint32_t ws_msw,
  324. uint32_t we_lsw, uint32_t we_msw)
  325. {
  326. int ret = -EINVAL;
  327. struct asm_session_mtmx_strtr_param_window_v2_t asm_mtmx_strtr_window;
  328. uint32_t param_id;
  329. pr_debug("%s, ws_lsw 0x%x ws_msw 0x%x we_lsw 0x%x we_msw 0x%x\n",
  330. __func__, ws_lsw, ws_msw, we_lsw, we_msw);
  331. memset(&asm_mtmx_strtr_window, 0,
  332. sizeof(struct asm_session_mtmx_strtr_param_window_v2_t));
  333. asm_mtmx_strtr_window.window_lsw = ws_lsw;
  334. asm_mtmx_strtr_window.window_msw = ws_msw;
  335. param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_START_V2;
  336. ret = q6asm_send_mtmx_strtr_window(ac, &asm_mtmx_strtr_window, param_id);
  337. if (ret) {
  338. pr_err("%s, start window can't be set error %d\n", __func__, ret);
  339. goto exit;
  340. }
  341. asm_mtmx_strtr_window.window_lsw = we_lsw;
  342. asm_mtmx_strtr_window.window_msw = we_msw;
  343. param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_END_V2;
  344. ret = q6asm_send_mtmx_strtr_window(ac, &asm_mtmx_strtr_window, param_id);
  345. if (ret)
  346. pr_err("%s, end window can't be set error %d\n", __func__, ret);
  347. exit:
  348. return ret;
  349. }
  350. static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,
  351. struct snd_compr_params *codec_param)
  352. {
  353. struct snd_compr_runtime *runtime = cstream->runtime;
  354. struct msm_transcode_loopback *trans = runtime->private_data;
  355. struct snd_soc_pcm_runtime *soc_pcm_rx;
  356. struct snd_soc_pcm_runtime *soc_pcm_tx;
  357. struct snd_soc_pcm_runtime *rtd;
  358. struct trans_loopback_pdata *pdata;
  359. uint32_t bit_width = 16;
  360. int ret = 0;
  361. if (trans == NULL) {
  362. pr_err("%s: Invalid param\n", __func__);
  363. return -EINVAL;
  364. }
  365. mutex_lock(&trans->lock);
  366. rtd = snd_pcm_substream_chip(cstream);
  367. pdata = snd_soc_platform_get_drvdata(rtd->platform);
  368. if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  369. if (codec_param->codec.id == SND_AUDIOCODEC_PCM) {
  370. trans->sink.codec_format =
  371. FORMAT_LINEAR_PCM;
  372. switch (codec_param->codec.format) {
  373. case SNDRV_PCM_FORMAT_S32_LE:
  374. bit_width = 32;
  375. break;
  376. case SNDRV_PCM_FORMAT_S24_LE:
  377. bit_width = 24;
  378. break;
  379. case SNDRV_PCM_FORMAT_S24_3LE:
  380. bit_width = 24;
  381. break;
  382. case SNDRV_PCM_FORMAT_S16_LE:
  383. default:
  384. bit_width = 16;
  385. break;
  386. }
  387. } else {
  388. pr_debug("%s: unknown sink codec\n", __func__);
  389. ret = -EINVAL;
  390. goto exit;
  391. }
  392. trans->sink.start = true;
  393. }
  394. if (cstream->direction == SND_COMPRESS_CAPTURE) {
  395. switch (codec_param->codec.id) {
  396. case SND_AUDIOCODEC_PCM:
  397. pr_debug("Source SND_AUDIOCODEC_PCM\n");
  398. trans->source.codec_format =
  399. FORMAT_LINEAR_PCM;
  400. break;
  401. case SND_AUDIOCODEC_AC3:
  402. pr_debug("Source SND_AUDIOCODEC_AC3\n");
  403. trans->source.codec_format =
  404. FORMAT_AC3;
  405. break;
  406. case SND_AUDIOCODEC_EAC3:
  407. pr_debug("Source SND_AUDIOCODEC_EAC3\n");
  408. trans->source.codec_format =
  409. FORMAT_EAC3;
  410. break;
  411. default:
  412. pr_debug("%s: unknown source codec\n", __func__);
  413. ret = -EINVAL;
  414. goto exit;
  415. }
  416. trans->source.start = true;
  417. }
  418. pr_debug("%s: trans->source.start %d trans->sink.start %d trans->source.cstream %pK trans->sink.cstream %pK trans->session_state %d\n",
  419. __func__, trans->source.start, trans->sink.start,
  420. trans->source.cstream, trans->sink.cstream,
  421. trans->session_state);
  422. if ((trans->session_state == LOOPBACK_SESSION_READY) &&
  423. trans->source.start && trans->sink.start) {
  424. pr_debug("%s: Moving loopback session to start state\n",
  425. __func__);
  426. trans->session_state = LOOPBACK_SESSION_START;
  427. }
  428. if (trans->session_state == LOOPBACK_SESSION_START) {
  429. if (trans->audio_client != NULL) {
  430. pr_debug("%s: ASM client already opened, closing\n",
  431. __func__);
  432. stop_transcoding(trans);
  433. }
  434. trans->audio_client = q6asm_audio_client_alloc(
  435. (app_cb)loopback_event_handler, trans);
  436. if (!trans->audio_client) {
  437. pr_err("%s: Could not allocate memory\n", __func__);
  438. ret = -EINVAL;
  439. goto exit;
  440. }
  441. pr_debug("%s: ASM client allocated, callback %pK\n", __func__,
  442. loopback_event_handler);
  443. trans->session_id = trans->audio_client->session;
  444. trans->audio_client->perf_mode = pdata->perf_mode;
  445. ret = q6asm_open_transcode_loopback(trans->audio_client,
  446. bit_width,
  447. trans->source.codec_format,
  448. trans->sink.codec_format);
  449. if (ret < 0) {
  450. pr_err("%s: Session transcode loopback open failed\n",
  451. __func__);
  452. q6asm_audio_client_free(trans->audio_client);
  453. trans->audio_client = NULL;
  454. goto exit;
  455. }
  456. pr_debug("%s: Starting ADM open for loopback\n", __func__);
  457. soc_pcm_rx = trans->sink.cstream->private_data;
  458. soc_pcm_tx = trans->source.cstream->private_data;
  459. if (trans->source.codec_format != FORMAT_LINEAR_PCM)
  460. msm_pcm_routing_reg_phy_compr_stream(
  461. soc_pcm_tx->dai_link->id,
  462. LEGACY_PCM_MODE,
  463. trans->session_id,
  464. SNDRV_PCM_STREAM_CAPTURE,
  465. COMPRESSED_PASSTHROUGH_GEN);
  466. else
  467. msm_pcm_routing_reg_phy_stream(
  468. soc_pcm_tx->dai_link->id,
  469. trans->audio_client->perf_mode,
  470. trans->session_id,
  471. SNDRV_PCM_STREAM_CAPTURE);
  472. /* Opening Rx ADM in LOW_LATENCY mode by default */
  473. msm_pcm_routing_reg_phy_stream(
  474. soc_pcm_rx->dai_link->id,
  475. trans->audio_client->perf_mode,
  476. trans->session_id,
  477. SNDRV_PCM_STREAM_PLAYBACK);
  478. pr_debug("%s: Successfully opened ADM sessions\n", __func__);
  479. }
  480. exit:
  481. mutex_unlock(&trans->lock);
  482. return ret;
  483. }
  484. static int msm_transcode_loopback_get_caps(struct snd_compr_stream *cstream,
  485. struct snd_compr_caps *arg)
  486. {
  487. struct snd_compr_runtime *runtime;
  488. struct msm_transcode_loopback *trans;
  489. if (!arg || !cstream) {
  490. pr_err("%s: Invalid arguments\n", __func__);
  491. return -EINVAL;
  492. }
  493. runtime = cstream->runtime;
  494. trans = runtime->private_data;
  495. pr_debug("%s\n", __func__);
  496. if (cstream->direction == SND_COMPRESS_CAPTURE)
  497. memcpy(arg, &trans->source_compr_cap,
  498. sizeof(struct snd_compr_caps));
  499. else
  500. memcpy(arg, &trans->sink_compr_cap,
  501. sizeof(struct snd_compr_caps));
  502. return 0;
  503. }
  504. static int msm_transcode_loopback_set_metadata(struct snd_compr_stream *cstream,
  505. struct snd_compr_metadata *metadata)
  506. {
  507. struct snd_soc_pcm_runtime *rtd;
  508. struct trans_loopback_pdata *pdata;
  509. struct msm_transcode_loopback *prtd = NULL;
  510. struct audio_client *ac = NULL;
  511. if (!metadata || !cstream) {
  512. pr_err("%s: Invalid arguments\n", __func__);
  513. return -EINVAL;
  514. }
  515. rtd = snd_pcm_substream_chip(cstream);
  516. pdata = snd_soc_platform_get_drvdata(rtd->platform);
  517. prtd = cstream->runtime->private_data;
  518. if (!prtd || !prtd->audio_client) {
  519. pr_err("%s: prtd or audio client is NULL\n", __func__);
  520. return -EINVAL;
  521. }
  522. ac = prtd->audio_client;
  523. switch (metadata->key) {
  524. case SNDRV_COMPRESS_LATENCY_MODE:
  525. {
  526. switch (metadata->value[0]) {
  527. case SNDRV_COMPRESS_LEGACY_LATENCY_MODE:
  528. pdata->perf_mode = LEGACY_PCM_MODE;
  529. break;
  530. case SNDRV_COMPRESS_LOW_LATENCY_MODE:
  531. pdata->perf_mode = LOW_LATENCY_PCM_MODE;
  532. break;
  533. default:
  534. pr_debug("%s: Unsupported latency mode %d, default to Legacy\n",
  535. __func__, metadata->value[0]);
  536. pdata->perf_mode = LEGACY_PCM_MODE;
  537. break;
  538. }
  539. break;
  540. }
  541. case SNDRV_COMPRESS_RENDER_WINDOW:
  542. {
  543. return msm_transcode_set_render_window(
  544. ac,
  545. metadata->value[0],
  546. metadata->value[1],
  547. metadata->value[2],
  548. metadata->value[3]);
  549. }
  550. default:
  551. pr_debug("%s: Unsupported metadata %d\n",
  552. __func__, metadata->key);
  553. break;
  554. }
  555. return 0;
  556. }
  557. static int msm_transcode_stream_cmd_put(struct snd_kcontrol *kcontrol,
  558. struct snd_ctl_elem_value *ucontrol)
  559. {
  560. struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
  561. unsigned long fe_id = kcontrol->private_value;
  562. struct trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
  563. snd_soc_component_get_drvdata(comp);
  564. struct snd_compr_stream *cstream = NULL;
  565. struct msm_transcode_loopback *prtd;
  566. int ret = 0;
  567. struct msm_adsp_event_data *event_data = NULL;
  568. if (fe_id >= MSM_FRONTEND_DAI_MAX) {
  569. pr_err("%s Received invalid fe_id %lu\n",
  570. __func__, fe_id);
  571. ret = -EINVAL;
  572. goto done;
  573. }
  574. cstream = pdata->cstream[fe_id];
  575. if (cstream == NULL) {
  576. pr_err("%s cstream is null.\n", __func__);
  577. ret = -EINVAL;
  578. goto done;
  579. }
  580. prtd = cstream->runtime->private_data;
  581. if (!prtd) {
  582. pr_err("%s: prtd is null.\n", __func__);
  583. ret = -EINVAL;
  584. goto done;
  585. }
  586. if (prtd->audio_client == NULL) {
  587. pr_err("%s: audio_client is null.\n", __func__);
  588. ret = -EINVAL;
  589. goto done;
  590. }
  591. event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
  592. if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
  593. (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
  594. pr_err("%s: invalid event_type=%d",
  595. __func__, event_data->event_type);
  596. ret = -EINVAL;
  597. goto done;
  598. }
  599. if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
  600. - sizeof(struct msm_adsp_event_data)) {
  601. pr_err("%s param length=%d exceeds limit",
  602. __func__, event_data->payload_len);
  603. ret = -EINVAL;
  604. goto done;
  605. }
  606. ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
  607. if (ret < 0)
  608. pr_err("%s: failed to send stream event cmd, err = %d\n",
  609. __func__, ret);
  610. done:
  611. return ret;
  612. }
  613. static int msm_transcode_ion_fd_map_put(struct snd_kcontrol *kcontrol,
  614. struct snd_ctl_elem_value *ucontrol)
  615. {
  616. struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
  617. unsigned long fe_id = kcontrol->private_value;
  618. struct trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
  619. snd_soc_component_get_drvdata(comp);
  620. struct snd_compr_stream *cstream = NULL;
  621. struct msm_transcode_loopback *prtd;
  622. int fd;
  623. int ret = 0;
  624. if (fe_id >= MSM_FRONTEND_DAI_MAX) {
  625. pr_err("%s Received out of bounds invalid fe_id %lu\n",
  626. __func__, fe_id);
  627. ret = -EINVAL;
  628. goto done;
  629. }
  630. cstream = pdata->cstream[fe_id];
  631. if (cstream == NULL) {
  632. pr_err("%s cstream is null\n", __func__);
  633. ret = -EINVAL;
  634. goto done;
  635. }
  636. prtd = cstream->runtime->private_data;
  637. if (!prtd) {
  638. pr_err("%s: prtd is null\n", __func__);
  639. ret = -EINVAL;
  640. goto done;
  641. }
  642. if (prtd->audio_client == NULL) {
  643. pr_err("%s: audio_client is null\n", __func__);
  644. ret = -EINVAL;
  645. goto done;
  646. }
  647. memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd));
  648. ret = q6asm_send_ion_fd(prtd->audio_client, fd);
  649. if (ret < 0)
  650. pr_err("%s: failed to register ion fd\n", __func__);
  651. done:
  652. return ret;
  653. }
  654. static int msm_transcode_rtic_event_ack_put(struct snd_kcontrol *kcontrol,
  655. struct snd_ctl_elem_value *ucontrol)
  656. {
  657. struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
  658. unsigned long fe_id = kcontrol->private_value;
  659. struct trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
  660. snd_soc_component_get_drvdata(comp);
  661. struct snd_compr_stream *cstream = NULL;
  662. struct msm_transcode_loopback *prtd;
  663. int ret = 0;
  664. int param_length = 0;
  665. if (fe_id >= MSM_FRONTEND_DAI_MAX) {
  666. pr_err("%s Received invalid fe_id %lu\n",
  667. __func__, fe_id);
  668. ret = -EINVAL;
  669. goto done;
  670. }
  671. cstream = pdata->cstream[fe_id];
  672. if (cstream == NULL) {
  673. pr_err("%s cstream is null\n", __func__);
  674. ret = -EINVAL;
  675. goto done;
  676. }
  677. prtd = cstream->runtime->private_data;
  678. if (!prtd) {
  679. pr_err("%s: prtd is null\n", __func__);
  680. ret = -EINVAL;
  681. goto done;
  682. }
  683. if (prtd->audio_client == NULL) {
  684. pr_err("%s: audio_client is null\n", __func__);
  685. ret = -EINVAL;
  686. goto done;
  687. }
  688. memcpy(&param_length, ucontrol->value.bytes.data,
  689. sizeof(param_length));
  690. if ((param_length + sizeof(param_length))
  691. >= sizeof(ucontrol->value.bytes.data)) {
  692. pr_err("%s param length=%d exceeds limit",
  693. __func__, param_length);
  694. ret = -EINVAL;
  695. goto done;
  696. }
  697. ret = q6asm_send_rtic_event_ack(prtd->audio_client,
  698. ucontrol->value.bytes.data + sizeof(param_length),
  699. param_length);
  700. if (ret < 0)
  701. pr_err("%s: failed to send rtic event ack, err = %d\n",
  702. __func__, ret);
  703. done:
  704. return ret;
  705. }
  706. static int msm_transcode_playback_app_type_cfg_put(
  707. struct snd_kcontrol *kcontrol,
  708. struct snd_ctl_elem_value *ucontrol)
  709. {
  710. u64 fe_id = kcontrol->private_value;
  711. int session_type = SESSION_TYPE_RX;
  712. int be_id = ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_BE_ID];
  713. struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
  714. int ret = 0;
  715. cfg_data.app_type = ucontrol->value.integer.value[
  716. APP_TYPE_CONFIG_IDX_APP_TYPE];
  717. cfg_data.acdb_dev_id = ucontrol->value.integer.value[
  718. APP_TYPE_CONFIG_IDX_ACDB_ID];
  719. if (ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_SAMPLE_RATE] != 0)
  720. cfg_data.sample_rate = ucontrol->value.integer.value[
  721. APP_TYPE_CONFIG_IDX_SAMPLE_RATE];
  722. pr_debug("%s: fe_id %llu session_type %d be_id %d app_type %d acdb_dev_id %d sample_rate- %d\n",
  723. __func__, fe_id, session_type, be_id,
  724. cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
  725. ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
  726. be_id, &cfg_data);
  727. if (ret < 0)
  728. pr_err("%s: msm_transcode_playback_stream_app_type_cfg set failed returned %d\n",
  729. __func__, ret);
  730. return ret;
  731. }
  732. static int msm_transcode_playback_app_type_cfg_get(
  733. struct snd_kcontrol *kcontrol,
  734. struct snd_ctl_elem_value *ucontrol)
  735. {
  736. u64 fe_id = kcontrol->private_value;
  737. int session_type = SESSION_TYPE_RX;
  738. int be_id = 0;
  739. struct msm_pcm_stream_app_type_cfg cfg_data = {0};
  740. int ret = 0;
  741. ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
  742. &be_id, &cfg_data);
  743. if (ret < 0) {
  744. pr_err("%s: msm_transcode_playback_stream_app_type_cfg get failed returned %d\n",
  745. __func__, ret);
  746. goto done;
  747. }
  748. ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_APP_TYPE] =
  749. cfg_data.app_type;
  750. ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_ACDB_ID] =
  751. cfg_data.acdb_dev_id;
  752. ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_SAMPLE_RATE] =
  753. cfg_data.sample_rate;
  754. ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_BE_ID] = be_id;
  755. pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
  756. __func__, fe_id, session_type, be_id,
  757. cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
  758. done:
  759. return ret;
  760. }
  761. static int msm_transcode_set_volume(struct snd_compr_stream *cstream,
  762. uint32_t master_gain)
  763. {
  764. int rc = 0;
  765. struct msm_transcode_loopback *prtd;
  766. struct snd_soc_pcm_runtime *rtd;
  767. pr_debug("%s: master_gain %d\n", __func__, master_gain);
  768. if (!cstream || !cstream->runtime) {
  769. pr_err("%s: session not active\n", __func__);
  770. return -EINVAL;
  771. }
  772. rtd = cstream->private_data;
  773. prtd = cstream->runtime->private_data;
  774. if (!rtd || !rtd->platform || !prtd || !prtd->audio_client) {
  775. pr_err("%s: invalid rtd, prtd or audio client", __func__);
  776. return -EINVAL;
  777. }
  778. rc = q6asm_set_volume(prtd->audio_client, master_gain);
  779. if (rc < 0)
  780. pr_err("%s: Send vol gain command failed rc=%d\n",
  781. __func__, rc);
  782. return rc;
  783. }
  784. static int msm_transcode_volume_put(struct snd_kcontrol *kcontrol,
  785. struct snd_ctl_elem_value *ucontrol)
  786. {
  787. struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
  788. unsigned long fe_id = kcontrol->private_value;
  789. struct trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
  790. snd_soc_component_get_drvdata(comp);
  791. struct snd_compr_stream *cstream = NULL;
  792. uint32_t ret = 0;
  793. if (fe_id >= MSM_FRONTEND_DAI_MAX) {
  794. pr_err("%s Received out of bounds fe_id %lu\n",
  795. __func__, fe_id);
  796. return -EINVAL;
  797. }
  798. cstream = pdata->cstream[fe_id];
  799. pdata->master_gain = ucontrol->value.integer.value[0];
  800. pr_debug("%s: fe_id %lu master_gain %d\n",
  801. __func__, fe_id, pdata->master_gain);
  802. if (cstream)
  803. ret = msm_transcode_set_volume(cstream, pdata->master_gain);
  804. return ret;
  805. }
  806. static int msm_transcode_volume_get(struct snd_kcontrol *kcontrol,
  807. struct snd_ctl_elem_value *ucontrol)
  808. {
  809. struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
  810. unsigned long fe_id = kcontrol->private_value;
  811. struct trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
  812. snd_soc_component_get_drvdata(comp);
  813. if (fe_id >= MSM_FRONTEND_DAI_MAX) {
  814. pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id);
  815. return -EINVAL;
  816. }
  817. pr_debug("%s: fe_id %lu\n", __func__, fe_id);
  818. ucontrol->value.integer.value[0] = pdata->master_gain;
  819. return 0;
  820. }
  821. static int msm_transcode_audio_effects_config_info(struct snd_kcontrol *kcontrol,
  822. struct snd_ctl_elem_info *uinfo)
  823. {
  824. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  825. uinfo->count = MAX_PP_PARAMS_SZ;
  826. uinfo->value.integer.min = 0;
  827. uinfo->value.integer.max = 0xFFFFFFFF;
  828. return 0;
  829. }
  830. static int msm_transcode_audio_effects_config_get(struct snd_kcontrol *kcontrol,
  831. struct snd_ctl_elem_value *ucontrol)
  832. {
  833. struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
  834. unsigned long fe_id = kcontrol->private_value;
  835. struct trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
  836. snd_soc_component_get_drvdata(comp);
  837. struct msm_transcode_audio_effects *audio_effects = NULL;
  838. struct snd_compr_stream *cstream = NULL;
  839. pr_debug("%s: fe_id: %lu\n", __func__, fe_id);
  840. if (fe_id >= MSM_FRONTEND_DAI_MAX) {
  841. pr_err("%s Received out of bounds fe_id %lu\n",
  842. __func__, fe_id);
  843. return -EINVAL;
  844. }
  845. cstream = pdata->cstream[fe_id];
  846. audio_effects = pdata->audio_effects[fe_id];
  847. if (!cstream || !audio_effects) {
  848. pr_err("%s: stream or effects inactive\n", __func__);
  849. return -EINVAL;
  850. }
  851. return 0;
  852. }
  853. static int msm_transcode_audio_effects_config_put(struct snd_kcontrol *kcontrol,
  854. struct snd_ctl_elem_value *ucontrol)
  855. {
  856. struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
  857. unsigned long fe_id = kcontrol->private_value;
  858. struct trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
  859. snd_soc_component_get_drvdata(comp);
  860. struct msm_transcode_audio_effects *audio_effects = NULL;
  861. struct snd_compr_stream *cstream = NULL;
  862. struct msm_transcode_loopback *prtd = NULL;
  863. long *values = &(ucontrol->value.integer.value[0]);
  864. int effects_module;
  865. int ret = 0;
  866. pr_debug("%s: fe_id: %lu\n", __func__, fe_id);
  867. if (fe_id >= MSM_FRONTEND_DAI_MAX) {
  868. pr_err("%s Received out of bounds fe_id %lu\n",
  869. __func__, fe_id);
  870. ret = -EINVAL;
  871. goto exit;
  872. }
  873. cstream = pdata->cstream[fe_id];
  874. audio_effects = pdata->audio_effects[fe_id];
  875. if (!cstream || !audio_effects) {
  876. pr_err("%s: stream or effects inactive\n", __func__);
  877. ret = -EINVAL;
  878. goto exit;
  879. }
  880. prtd = cstream->runtime->private_data;
  881. if (!prtd) {
  882. pr_err("%s: cannot set audio effects\n", __func__);
  883. ret = -EINVAL;
  884. goto exit;
  885. }
  886. effects_module = *values++;
  887. switch (effects_module) {
  888. case VIRTUALIZER_MODULE:
  889. pr_debug("%s: VIRTUALIZER_MODULE\n", __func__);
  890. if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
  891. prtd->audio_client->topology))
  892. ret = msm_audio_effects_virtualizer_handler(
  893. prtd->audio_client,
  894. &(audio_effects->virtualizer),
  895. values);
  896. break;
  897. case REVERB_MODULE:
  898. pr_debug("%s: REVERB_MODULE\n", __func__);
  899. if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
  900. prtd->audio_client->topology))
  901. ret = msm_audio_effects_reverb_handler(prtd->audio_client,
  902. &(audio_effects->reverb),
  903. values);
  904. break;
  905. case BASS_BOOST_MODULE:
  906. pr_debug("%s: BASS_BOOST_MODULE\n", __func__);
  907. if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
  908. prtd->audio_client->topology))
  909. ret = msm_audio_effects_bass_boost_handler(prtd->audio_client,
  910. &(audio_effects->bass_boost),
  911. values);
  912. break;
  913. case PBE_MODULE:
  914. pr_debug("%s: PBE_MODULE\n", __func__);
  915. if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
  916. prtd->audio_client->topology))
  917. ret = msm_audio_effects_pbe_handler(prtd->audio_client,
  918. &(audio_effects->pbe),
  919. values);
  920. break;
  921. case EQ_MODULE:
  922. pr_debug("%s: EQ_MODULE\n", __func__);
  923. if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
  924. prtd->audio_client->topology))
  925. ret = msm_audio_effects_popless_eq_handler(prtd->audio_client,
  926. &(audio_effects->equalizer),
  927. values);
  928. break;
  929. case SOFT_VOLUME_MODULE:
  930. pr_debug("%s: SOFT_VOLUME_MODULE\n", __func__);
  931. break;
  932. case SOFT_VOLUME2_MODULE:
  933. pr_debug("%s: SOFT_VOLUME2_MODULE\n", __func__);
  934. if (msm_audio_effects_is_effmodule_supp_in_top(effects_module,
  935. prtd->audio_client->topology))
  936. ret = msm_audio_effects_volume_handler_v2(prtd->audio_client,
  937. &(audio_effects->volume),
  938. values, SOFT_VOLUME_INSTANCE_2);
  939. break;
  940. default:
  941. pr_err("%s Invalid effects config module\n", __func__);
  942. ret = -EINVAL;
  943. }
  944. exit:
  945. return ret;
  946. }
  947. static int msm_transcode_add_audio_effects_control(struct snd_soc_pcm_runtime *rtd)
  948. {
  949. const char *mixer_ctl_name = "Audio Effects Config";
  950. const char *deviceNo = "NN";
  951. char *mixer_str = NULL;
  952. int ctl_len = 0;
  953. int ret = 0;
  954. struct snd_kcontrol_new fe_audio_effects_config_control[1] = {
  955. {
  956. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  957. .name = "?",
  958. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  959. .info = msm_transcode_audio_effects_config_info,
  960. .get = msm_transcode_audio_effects_config_get,
  961. .put = msm_transcode_audio_effects_config_put,
  962. .private_value = 0,
  963. }
  964. };
  965. if (!rtd) {
  966. pr_err("%s NULL rtd\n", __func__);
  967. ret = -EINVAL;
  968. goto done;
  969. }
  970. pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n", __func__,
  971. rtd->dai_link->name, rtd->dai_link->id,
  972. rtd->dai_link->cpu_dai_name, rtd->pcm->device);
  973. ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
  974. mixer_str = kzalloc(ctl_len, GFP_KERNEL);
  975. if (!mixer_str) {
  976. ret = -ENOMEM;
  977. goto done;
  978. }
  979. snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
  980. fe_audio_effects_config_control[0].name = mixer_str;
  981. fe_audio_effects_config_control[0].private_value = rtd->dai_link->id;
  982. ret = snd_soc_add_platform_controls(rtd->platform,
  983. fe_audio_effects_config_control,
  984. ARRAY_SIZE(fe_audio_effects_config_control));
  985. if (ret < 0)
  986. pr_err("%s: failed to add ctl %s. err = %d\n", __func__, mixer_str, ret);
  987. kfree(mixer_str);
  988. done:
  989. return ret;
  990. }
  991. static int msm_transcode_stream_cmd_control(
  992. struct snd_soc_pcm_runtime *rtd)
  993. {
  994. const char *mixer_ctl_name = DSP_STREAM_CMD;
  995. const char *deviceNo = "NN";
  996. char *mixer_str = NULL;
  997. int ctl_len = 0, ret = 0;
  998. struct snd_kcontrol_new fe_loopback_stream_cmd_config_control[1] = {
  999. {
  1000. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1001. .name = "?",
  1002. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  1003. .info = msm_adsp_stream_cmd_info,
  1004. .put = msm_transcode_stream_cmd_put,
  1005. .private_value = 0,
  1006. }
  1007. };
  1008. if (!rtd) {
  1009. pr_err("%s NULL rtd\n", __func__);
  1010. ret = -EINVAL;
  1011. goto done;
  1012. }
  1013. ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
  1014. mixer_str = kzalloc(ctl_len, GFP_KERNEL);
  1015. if (!mixer_str) {
  1016. ret = -ENOMEM;
  1017. goto done;
  1018. }
  1019. snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
  1020. fe_loopback_stream_cmd_config_control[0].name = mixer_str;
  1021. fe_loopback_stream_cmd_config_control[0].private_value =
  1022. rtd->dai_link->id;
  1023. pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
  1024. ret = snd_soc_add_platform_controls(rtd->platform,
  1025. fe_loopback_stream_cmd_config_control,
  1026. ARRAY_SIZE(fe_loopback_stream_cmd_config_control));
  1027. if (ret < 0)
  1028. pr_err("%s: failed to add ctl %s. err = %d\n",
  1029. __func__, mixer_str, ret);
  1030. kfree(mixer_str);
  1031. done:
  1032. return ret;
  1033. }
  1034. static int msm_transcode_stream_callback_control(
  1035. struct snd_soc_pcm_runtime *rtd)
  1036. {
  1037. const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
  1038. const char *deviceNo = "NN";
  1039. char *mixer_str = NULL;
  1040. int ctl_len = 0, ret = 0;
  1041. struct snd_kcontrol *kctl;
  1042. struct snd_kcontrol_new fe_loopback_callback_config_control[1] = {
  1043. {
  1044. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1045. .name = "?",
  1046. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  1047. .info = msm_adsp_stream_callback_info,
  1048. .get = msm_adsp_stream_callback_get,
  1049. .private_value = 0,
  1050. }
  1051. };
  1052. if (!rtd) {
  1053. pr_err("%s: rtd is NULL\n", __func__);
  1054. ret = -EINVAL;
  1055. goto done;
  1056. }
  1057. ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
  1058. mixer_str = kzalloc(ctl_len, GFP_KERNEL);
  1059. if (!mixer_str) {
  1060. ret = -ENOMEM;
  1061. goto done;
  1062. }
  1063. snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
  1064. fe_loopback_callback_config_control[0].name = mixer_str;
  1065. fe_loopback_callback_config_control[0].private_value =
  1066. rtd->dai_link->id;
  1067. pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
  1068. ret = snd_soc_add_platform_controls(rtd->platform,
  1069. fe_loopback_callback_config_control,
  1070. ARRAY_SIZE(fe_loopback_callback_config_control));
  1071. if (ret < 0) {
  1072. pr_err("%s: failed to add ctl %s. err = %d\n",
  1073. __func__, mixer_str, ret);
  1074. ret = -EINVAL;
  1075. goto free_mixer_str;
  1076. }
  1077. kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
  1078. if (!kctl) {
  1079. pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str);
  1080. ret = -EINVAL;
  1081. goto free_mixer_str;
  1082. }
  1083. kctl->private_data = NULL;
  1084. free_mixer_str:
  1085. kfree(mixer_str);
  1086. done:
  1087. return ret;
  1088. }
  1089. static int msm_transcode_add_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
  1090. {
  1091. const char *mixer_ctl_name = "Playback ION FD";
  1092. const char *deviceNo = "NN";
  1093. char *mixer_str = NULL;
  1094. int ctl_len = 0, ret = 0;
  1095. struct snd_kcontrol_new fe_ion_fd_config_control[1] = {
  1096. {
  1097. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1098. .name = "?",
  1099. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  1100. .info = msm_adsp_stream_cmd_info,
  1101. .put = msm_transcode_ion_fd_map_put,
  1102. .private_value = 0,
  1103. }
  1104. };
  1105. if (!rtd) {
  1106. pr_err("%s NULL rtd\n", __func__);
  1107. ret = -EINVAL;
  1108. goto done;
  1109. }
  1110. ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
  1111. mixer_str = kzalloc(ctl_len, GFP_KERNEL);
  1112. if (!mixer_str) {
  1113. ret = -ENOMEM;
  1114. goto done;
  1115. }
  1116. snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
  1117. fe_ion_fd_config_control[0].name = mixer_str;
  1118. fe_ion_fd_config_control[0].private_value = rtd->dai_link->id;
  1119. pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
  1120. ret = snd_soc_add_platform_controls(rtd->platform,
  1121. fe_ion_fd_config_control,
  1122. ARRAY_SIZE(fe_ion_fd_config_control));
  1123. if (ret < 0)
  1124. pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
  1125. kfree(mixer_str);
  1126. done:
  1127. return ret;
  1128. }
  1129. static int msm_transcode_add_event_ack_cmd_control(
  1130. struct snd_soc_pcm_runtime *rtd)
  1131. {
  1132. const char *mixer_ctl_name = "Playback Event Ack";
  1133. const char *deviceNo = "NN";
  1134. char *mixer_str = NULL;
  1135. int ctl_len = 0, ret = 0;
  1136. struct snd_kcontrol_new fe_event_ack_config_control[1] = {
  1137. {
  1138. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1139. .name = "?",
  1140. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  1141. .info = msm_adsp_stream_cmd_info,
  1142. .put = msm_transcode_rtic_event_ack_put,
  1143. .private_value = 0,
  1144. }
  1145. };
  1146. if (!rtd) {
  1147. pr_err("%s NULL rtd\n", __func__);
  1148. ret = -EINVAL;
  1149. goto done;
  1150. }
  1151. ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
  1152. mixer_str = kzalloc(ctl_len, GFP_KERNEL);
  1153. if (!mixer_str) {
  1154. ret = -ENOMEM;
  1155. goto done;
  1156. }
  1157. snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
  1158. fe_event_ack_config_control[0].name = mixer_str;
  1159. fe_event_ack_config_control[0].private_value = rtd->dai_link->id;
  1160. pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
  1161. ret = snd_soc_add_platform_controls(rtd->platform,
  1162. fe_event_ack_config_control,
  1163. ARRAY_SIZE(fe_event_ack_config_control));
  1164. if (ret < 0)
  1165. pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
  1166. kfree(mixer_str);
  1167. done:
  1168. return ret;
  1169. }
  1170. static int msm_transcode_app_type_cfg_info(struct snd_kcontrol *kcontrol,
  1171. struct snd_ctl_elem_info *uinfo)
  1172. {
  1173. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  1174. uinfo->count = 5;
  1175. uinfo->value.integer.min = 0;
  1176. uinfo->value.integer.max = 0xFFFFFFFF;
  1177. return 0;
  1178. }
  1179. static int msm_transcode_add_app_type_cfg_control(
  1180. struct snd_soc_pcm_runtime *rtd)
  1181. {
  1182. char mixer_str[32];
  1183. struct snd_kcontrol_new fe_app_type_cfg_control[1] = {
  1184. {
  1185. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1186. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  1187. .info = msm_transcode_app_type_cfg_info,
  1188. .put = msm_transcode_playback_app_type_cfg_put,
  1189. .get = msm_transcode_playback_app_type_cfg_get,
  1190. .private_value = 0,
  1191. }
  1192. };
  1193. if (!rtd) {
  1194. pr_err("%s NULL rtd\n", __func__);
  1195. return -EINVAL;
  1196. }
  1197. if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
  1198. snprintf(mixer_str, sizeof(mixer_str),
  1199. "Audio Stream %d App Type Cfg",
  1200. rtd->pcm->device);
  1201. fe_app_type_cfg_control[0].name = mixer_str;
  1202. fe_app_type_cfg_control[0].private_value = rtd->dai_link->id;
  1203. fe_app_type_cfg_control[0].put =
  1204. msm_transcode_playback_app_type_cfg_put;
  1205. fe_app_type_cfg_control[0].get =
  1206. msm_transcode_playback_app_type_cfg_get;
  1207. pr_debug("Registering new mixer ctl %s", mixer_str);
  1208. snd_soc_add_platform_controls(rtd->platform,
  1209. fe_app_type_cfg_control,
  1210. ARRAY_SIZE(fe_app_type_cfg_control));
  1211. }
  1212. return 0;
  1213. }
  1214. static int msm_transcode_volume_info(struct snd_kcontrol *kcontrol,
  1215. struct snd_ctl_elem_info *uinfo)
  1216. {
  1217. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  1218. uinfo->count = 1;
  1219. uinfo->value.integer.min = 0;
  1220. uinfo->value.integer.max = TRANSCODE_LR_VOL_MAX_DB;
  1221. return 0;
  1222. }
  1223. static int msm_transcode_add_volume_control(struct snd_soc_pcm_runtime *rtd)
  1224. {
  1225. struct snd_kcontrol_new fe_volume_control[1] = {
  1226. {
  1227. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1228. .name = "Transcode Loopback Rx Volume",
  1229. .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
  1230. SNDRV_CTL_ELEM_ACCESS_READWRITE,
  1231. .info = msm_transcode_volume_info,
  1232. .get = msm_transcode_volume_get,
  1233. .put = msm_transcode_volume_put,
  1234. .private_value = 0,
  1235. }
  1236. };
  1237. if (!rtd) {
  1238. pr_err("%s NULL rtd\n", __func__);
  1239. return -EINVAL;
  1240. }
  1241. if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
  1242. fe_volume_control[0].private_value = rtd->dai_link->id;
  1243. pr_debug("Registering new mixer ctl %s",
  1244. fe_volume_control[0].name);
  1245. snd_soc_add_platform_controls(rtd->platform, fe_volume_control,
  1246. ARRAY_SIZE(fe_volume_control));
  1247. }
  1248. return 0;
  1249. }
  1250. static int msm_transcode_loopback_new(struct snd_soc_pcm_runtime *rtd)
  1251. {
  1252. int rc;
  1253. rc = msm_transcode_add_audio_effects_control(rtd);
  1254. if (rc)
  1255. pr_err("%s: Could not add Compr Audio Effects Control\n",
  1256. __func__);
  1257. rc = msm_transcode_stream_cmd_control(rtd);
  1258. if (rc)
  1259. pr_err("%s: ADSP Stream Cmd Control open failed\n", __func__);
  1260. rc = msm_transcode_stream_callback_control(rtd);
  1261. if (rc)
  1262. pr_err("%s: ADSP Stream callback Control open failed\n",
  1263. __func__);
  1264. rc = msm_transcode_add_ion_fd_cmd_control(rtd);
  1265. if (rc)
  1266. pr_err("%s: Could not add transcode ion fd Control\n",
  1267. __func__);
  1268. rc = msm_transcode_add_event_ack_cmd_control(rtd);
  1269. if (rc)
  1270. pr_err("%s: Could not add transcode event ack Control\n",
  1271. __func__);
  1272. rc = msm_transcode_add_app_type_cfg_control(rtd);
  1273. if (rc)
  1274. pr_err("%s: Could not add Compr App Type Cfg Control\n",
  1275. __func__);
  1276. rc = msm_transcode_add_volume_control(rtd);
  1277. if (rc)
  1278. pr_err("%s: Could not add transcode volume Control\n",
  1279. __func__);
  1280. return 0;
  1281. }
  1282. static struct snd_compr_ops msm_transcode_loopback_ops = {
  1283. .open = msm_transcode_loopback_open,
  1284. .free = msm_transcode_loopback_free,
  1285. .trigger = msm_transcode_loopback_trigger,
  1286. .set_params = msm_transcode_loopback_set_params,
  1287. .get_caps = msm_transcode_loopback_get_caps,
  1288. .set_metadata = msm_transcode_loopback_set_metadata,
  1289. };
  1290. static int msm_transcode_loopback_probe(struct snd_soc_platform *platform)
  1291. {
  1292. struct trans_loopback_pdata *pdata = NULL;
  1293. int i;
  1294. pr_debug("%s\n", __func__);
  1295. pdata = (struct trans_loopback_pdata *)
  1296. kzalloc(sizeof(struct trans_loopback_pdata),
  1297. GFP_KERNEL);
  1298. if (!pdata)
  1299. return -ENOMEM;
  1300. pdata->perf_mode = LOW_LATENCY_PCM_MODE;
  1301. for (i = 0; i < MSM_FRONTEND_DAI_MAX; i++)
  1302. pdata->audio_effects[i] = NULL;
  1303. snd_soc_platform_set_drvdata(platform, pdata);
  1304. return 0;
  1305. }
  1306. static int msm_transcode_loopback_remove(struct snd_soc_platform *platform)
  1307. {
  1308. struct trans_loopback_pdata *pdata = NULL;
  1309. pdata = (struct trans_loopback_pdata *)
  1310. snd_soc_platform_get_drvdata(platform);
  1311. kfree(pdata);
  1312. return 0;
  1313. }
  1314. static struct snd_soc_platform_driver msm_soc_platform = {
  1315. .probe = msm_transcode_loopback_probe,
  1316. .compr_ops = &msm_transcode_loopback_ops,
  1317. .pcm_new = msm_transcode_loopback_new,
  1318. .remove = msm_transcode_loopback_remove,
  1319. };
  1320. static int msm_transcode_dev_probe(struct platform_device *pdev)
  1321. {
  1322. pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
  1323. if (pdev->dev.of_node)
  1324. dev_set_name(&pdev->dev, "%s", "msm-transcode-loopback");
  1325. return snd_soc_register_platform(&pdev->dev,
  1326. &msm_soc_platform);
  1327. }
  1328. static int msm_transcode_remove(struct platform_device *pdev)
  1329. {
  1330. snd_soc_unregister_platform(&pdev->dev);
  1331. return 0;
  1332. }
  1333. static const struct of_device_id msm_transcode_loopback_dt_match[] = {
  1334. {.compatible = "qcom,msm-transcode-loopback"},
  1335. {}
  1336. };
  1337. MODULE_DEVICE_TABLE(of, msm_transcode_loopback_dt_match);
  1338. static struct platform_driver msm_transcode_loopback_driver = {
  1339. .driver = {
  1340. .name = "msm-transcode-loopback",
  1341. .owner = THIS_MODULE,
  1342. .of_match_table = msm_transcode_loopback_dt_match,
  1343. },
  1344. .probe = msm_transcode_dev_probe,
  1345. .remove = msm_transcode_remove,
  1346. };
  1347. int __init msm_transcode_loopback_init(void)
  1348. {
  1349. memset(&transcode_info, 0, sizeof(struct msm_transcode_loopback));
  1350. mutex_init(&transcode_info.lock);
  1351. return platform_driver_register(&msm_transcode_loopback_driver);
  1352. }
  1353. void msm_transcode_loopback_exit(void)
  1354. {
  1355. mutex_destroy(&transcode_info.lock);
  1356. platform_driver_unregister(&msm_transcode_loopback_driver);
  1357. }
  1358. MODULE_DESCRIPTION("Transcode loopback platform driver");
  1359. MODULE_LICENSE("GPL v2");