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

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