soc-compress.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. /*
  2. * soc-compress.c -- ALSA SoC Compress
  3. *
  4. * Copyright (C) 2012 Intel Corp.
  5. *
  6. * Authors: Namarta Kohli <namartax.kohli@intel.com>
  7. * Ramesh Babu K V <ramesh.babu@linux.intel.com>
  8. * Vinod Koul <vinod.koul@linux.intel.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by the
  12. * Free Software Foundation; either version 2 of the License, or (at your
  13. * option) any later version.
  14. *
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/init.h>
  18. #include <linux/delay.h>
  19. #include <linux/slab.h>
  20. #include <linux/workqueue.h>
  21. #include <sound/core.h>
  22. #include <sound/compress_params.h>
  23. #include <sound/compress_driver.h>
  24. #include <sound/soc.h>
  25. #include <sound/initval.h>
  26. #include <sound/soc-dpcm.h>
  27. static int soc_compr_open(struct snd_compr_stream *cstream)
  28. {
  29. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  30. struct snd_soc_platform *platform = rtd->platform;
  31. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  32. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  33. int ret = 0;
  34. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  35. if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
  36. ret = platform->driver->compr_ops->open(cstream);
  37. if (ret < 0) {
  38. pr_err("compress asoc: can't open platform %s\n", platform->name);
  39. goto out;
  40. }
  41. }
  42. if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
  43. ret = rtd->dai_link->compr_ops->startup(cstream);
  44. if (ret < 0) {
  45. pr_err("compress asoc: %s startup failed\n", rtd->dai_link->name);
  46. goto machine_err;
  47. }
  48. }
  49. if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  50. cpu_dai->playback_active++;
  51. codec_dai->playback_active++;
  52. } else {
  53. cpu_dai->capture_active++;
  54. codec_dai->capture_active++;
  55. }
  56. cpu_dai->active++;
  57. codec_dai->active++;
  58. rtd->codec->active++;
  59. mutex_unlock(&rtd->pcm_mutex);
  60. return 0;
  61. machine_err:
  62. if (platform->driver->compr_ops && platform->driver->compr_ops->free)
  63. platform->driver->compr_ops->free(cstream);
  64. out:
  65. mutex_unlock(&rtd->pcm_mutex);
  66. return ret;
  67. }
  68. static int soc_compr_open_fe(struct snd_compr_stream *cstream)
  69. {
  70. struct snd_soc_pcm_runtime *fe = cstream->private_data;
  71. struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
  72. struct snd_soc_platform *platform = fe->platform;
  73. struct snd_soc_dpcm_params *dpcm;
  74. struct snd_soc_dapm_widget_list *list;
  75. struct snd_soc_dai *cpu_dai = fe->cpu_dai;
  76. struct snd_soc_dai *codec_dai = fe->codec_dai;
  77. int stream;
  78. int ret = 0;
  79. if (cstream->direction == SND_COMPRESS_PLAYBACK)
  80. stream = SNDRV_PCM_STREAM_PLAYBACK;
  81. else
  82. stream = SNDRV_PCM_STREAM_CAPTURE;
  83. mutex_lock(&fe->card->dpcm_mutex);
  84. if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
  85. ret = platform->driver->compr_ops->open(cstream);
  86. if (ret < 0) {
  87. pr_err("compress asoc: can't open platform %s\n", platform->name);
  88. goto out;
  89. }
  90. }
  91. if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
  92. ret = fe->dai_link->compr_ops->startup(cstream);
  93. if (ret < 0) {
  94. pr_err("compress asoc: %s startup failed\n", fe->dai_link->name);
  95. goto machine_err;
  96. }
  97. }
  98. fe->dpcm[stream].runtime = fe_substream->runtime;
  99. if (dpcm_path_get(fe, stream, &list) <= 0) {
  100. dev_dbg(fe->dev, "ASoC: %s no valid %s route\n",
  101. fe->dai_link->name, stream ? "capture" : "playback");
  102. }
  103. /* calculate valid and active FE <-> BE dpcms */
  104. dpcm_process_paths(fe, stream, &list, 1);
  105. fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
  106. ret = dpcm_be_dai_startup(fe, stream);
  107. if (ret < 0) {
  108. /* clean up all links */
  109. list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
  110. dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
  111. dpcm_be_disconnect(fe, stream);
  112. fe->dpcm[stream].runtime = NULL;
  113. goto fe_err;
  114. }
  115. dpcm_clear_pending_state(fe, stream);
  116. dpcm_path_put(&list);
  117. fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
  118. fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
  119. if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  120. cpu_dai->playback_active++;
  121. codec_dai->playback_active++;
  122. } else {
  123. cpu_dai->capture_active++;
  124. codec_dai->capture_active++;
  125. }
  126. cpu_dai->active++;
  127. codec_dai->active++;
  128. fe->codec->active++;
  129. mutex_unlock(&fe->card->dpcm_mutex);
  130. return 0;
  131. fe_err:
  132. if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
  133. fe->dai_link->compr_ops->shutdown(cstream);
  134. machine_err:
  135. if (platform->driver->compr_ops && platform->driver->compr_ops->free)
  136. platform->driver->compr_ops->free(cstream);
  137. out:
  138. fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
  139. mutex_unlock(&fe->card->dpcm_mutex);
  140. return ret;
  141. }
  142. /*
  143. * Power down the audio subsystem pmdown_time msecs after close is called.
  144. * This is to ensure there are no pops or clicks in between any music tracks
  145. * due to DAPM power cycling.
  146. */
  147. static void close_delayed_work(struct work_struct *work)
  148. {
  149. struct snd_soc_pcm_runtime *rtd =
  150. container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
  151. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  152. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  153. dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
  154. codec_dai->driver->playback.stream_name,
  155. codec_dai->playback_active ? "active" : "inactive",
  156. codec_dai->pop_wait ? "yes" : "no");
  157. /* are we waiting on this codec DAI stream */
  158. if (codec_dai->pop_wait == 1) {
  159. codec_dai->pop_wait = 0;
  160. snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
  161. SND_SOC_DAPM_STREAM_STOP);
  162. }
  163. mutex_unlock(&rtd->pcm_mutex);
  164. }
  165. static int soc_compr_free(struct snd_compr_stream *cstream)
  166. {
  167. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  168. struct snd_soc_platform *platform = rtd->platform;
  169. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  170. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  171. struct snd_soc_codec *codec = rtd->codec;
  172. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  173. if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  174. cpu_dai->playback_active--;
  175. codec_dai->playback_active--;
  176. snd_soc_dai_digital_mute(codec_dai, 1);
  177. } else {
  178. cpu_dai->capture_active--;
  179. codec_dai->capture_active--;
  180. }
  181. cpu_dai->active--;
  182. codec_dai->active--;
  183. codec->active--;
  184. if (!cpu_dai->active)
  185. cpu_dai->rate = 0;
  186. if (!codec_dai->active)
  187. codec_dai->rate = 0;
  188. if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
  189. rtd->dai_link->compr_ops->shutdown(cstream);
  190. if (platform->driver->compr_ops && platform->driver->compr_ops->free)
  191. platform->driver->compr_ops->free(cstream);
  192. cpu_dai->runtime = NULL;
  193. if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  194. if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
  195. rtd->dai_link->ignore_pmdown_time) {
  196. snd_soc_dapm_stream_event(rtd,
  197. codec_dai->driver->playback.stream_name,
  198. SND_SOC_DAPM_STREAM_STOP);
  199. } else {
  200. codec_dai->pop_wait = 1;
  201. schedule_delayed_work(&rtd->delayed_work,
  202. msecs_to_jiffies(rtd->pmdown_time));
  203. }
  204. } else {
  205. /* capture streams can be powered down now */
  206. snd_soc_dapm_stream_event(rtd,
  207. codec_dai->driver->capture.stream_name,
  208. SND_SOC_DAPM_STREAM_STOP);
  209. }
  210. mutex_unlock(&rtd->pcm_mutex);
  211. return 0;
  212. }
  213. static int soc_compr_free_fe(struct snd_compr_stream *cstream)
  214. {
  215. struct snd_soc_pcm_runtime *fe = cstream->private_data;
  216. struct snd_soc_platform *platform = fe->platform;
  217. struct snd_soc_dpcm_params *dpcm;
  218. int stream, ret;
  219. struct snd_soc_dai *cpu_dai = fe->cpu_dai;
  220. struct snd_soc_dai *codec_dai = fe->codec_dai;
  221. struct snd_soc_codec *codec = fe->codec;
  222. if (cstream->direction == SND_COMPRESS_PLAYBACK)
  223. stream = SNDRV_PCM_STREAM_PLAYBACK;
  224. else
  225. stream = SNDRV_PCM_STREAM_CAPTURE;
  226. mutex_lock(&fe->card->dpcm_mutex);
  227. if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  228. cpu_dai->playback_active--;
  229. codec_dai->playback_active--;
  230. snd_soc_dai_digital_mute(codec_dai, 1);
  231. } else {
  232. cpu_dai->capture_active--;
  233. codec_dai->capture_active--;
  234. }
  235. cpu_dai->active--;
  236. codec_dai->active--;
  237. codec->active--;
  238. fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
  239. ret = dpcm_be_dai_hw_free(fe, stream);
  240. if (ret < 0)
  241. dev_err(fe->dev, "compressed hw_free failed %d\n", ret);
  242. ret = dpcm_be_dai_shutdown(fe, stream);
  243. /* mark FE's links ready to prune */
  244. list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
  245. dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
  246. if (stream == SNDRV_PCM_STREAM_PLAYBACK)
  247. dpcm_dapm_stream_event(fe, stream,
  248. fe->cpu_dai->driver->playback.stream_name,
  249. SND_SOC_DAPM_STREAM_STOP);
  250. else
  251. dpcm_dapm_stream_event(fe, stream,
  252. fe->cpu_dai->driver->capture.stream_name,
  253. SND_SOC_DAPM_STREAM_STOP);
  254. fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
  255. fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
  256. dpcm_be_disconnect(fe, stream);
  257. fe->dpcm[stream].runtime = NULL;
  258. if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
  259. fe->dai_link->compr_ops->shutdown(cstream);
  260. if (platform->driver->compr_ops && platform->driver->compr_ops->free)
  261. platform->driver->compr_ops->free(cstream);
  262. //cpu_dai->runtime = NULL;
  263. mutex_unlock(&fe->card->dpcm_mutex);
  264. return 0;
  265. }
  266. static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
  267. {
  268. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  269. struct snd_soc_platform *platform = rtd->platform;
  270. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  271. int ret = 0;
  272. /* for partial drain and drain cmd, don't acquire lock while invoking DSP.
  273. * These calls will be blocked till these operation can complete which
  274. * will be a while. And during that time, app can invoke STOP, PAUSE etc
  275. */
  276. if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
  277. cmd == SND_COMPR_TRIGGER_DRAIN) {
  278. if (platform->driver->compr_ops &&
  279. platform->driver->compr_ops->trigger)
  280. return platform->driver->compr_ops->trigger(cstream, cmd);
  281. }
  282. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  283. if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
  284. ret = platform->driver->compr_ops->trigger(cstream, cmd);
  285. if (ret < 0)
  286. goto out;
  287. }
  288. if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  289. switch (cmd) {
  290. case SNDRV_PCM_TRIGGER_START:
  291. snd_soc_dai_digital_mute(codec_dai, 0);
  292. break;
  293. case SNDRV_PCM_TRIGGER_STOP:
  294. snd_soc_dai_digital_mute(codec_dai, 1);
  295. break;
  296. }
  297. }
  298. out:
  299. mutex_unlock(&rtd->pcm_mutex);
  300. return ret;
  301. }
  302. static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
  303. {
  304. struct snd_soc_pcm_runtime *fe = cstream->private_data;
  305. struct snd_soc_platform *platform = fe->platform;
  306. int ret = 0, stream;
  307. /* for partial drain and drain cmd, don't acquire lock while invoking DSP.
  308. * These calls will be blocked till these operation can complete which
  309. * will be a while. And during that time, app can invoke STOP, PAUSE etc
  310. */
  311. if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
  312. cmd == SND_COMPR_TRIGGER_DRAIN) {
  313. if (platform->driver->compr_ops &&
  314. platform->driver->compr_ops->trigger)
  315. return platform->driver->compr_ops->trigger(cstream, cmd);
  316. }
  317. if (cstream->direction == SND_COMPRESS_PLAYBACK)
  318. stream = SNDRV_PCM_STREAM_PLAYBACK;
  319. else
  320. stream = SNDRV_PCM_STREAM_CAPTURE;
  321. mutex_lock(&fe->card->dpcm_mutex);
  322. if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
  323. ret = platform->driver->compr_ops->trigger(cstream, cmd);
  324. if (ret < 0)
  325. goto out;
  326. }
  327. fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
  328. ret = dpcm_be_dai_trigger(fe, stream, cmd);
  329. switch (cmd) {
  330. case SNDRV_PCM_TRIGGER_START:
  331. case SNDRV_PCM_TRIGGER_RESUME:
  332. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  333. fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
  334. break;
  335. case SNDRV_PCM_TRIGGER_STOP:
  336. case SNDRV_PCM_TRIGGER_SUSPEND:
  337. fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
  338. break;
  339. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  340. fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
  341. break;
  342. }
  343. out:
  344. fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
  345. mutex_unlock(&fe->card->dpcm_mutex);
  346. return ret;
  347. }
  348. static int soc_compr_set_params(struct snd_compr_stream *cstream,
  349. struct snd_compr_params *params)
  350. {
  351. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  352. struct snd_soc_platform *platform = rtd->platform;
  353. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  354. int ret = 0;
  355. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  356. /* first we call set_params for the platform driver
  357. * this should configure the soc side
  358. * if the machine has compressed ops then we call that as well
  359. * expectation is that platform and machine will configure everything
  360. * for this compress path, like configuring pcm port for codec
  361. */
  362. if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
  363. ret = platform->driver->compr_ops->set_params(cstream, params);
  364. if (ret < 0)
  365. goto err;
  366. }
  367. if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
  368. ret = rtd->dai_link->compr_ops->set_params(cstream);
  369. if (ret < 0)
  370. goto err;
  371. }
  372. snd_soc_dapm_stream_event(rtd,
  373. codec_dai->driver->playback.stream_name,
  374. SND_SOC_DAPM_STREAM_START);
  375. /* cancel any delayed stream shutdown that is pending */
  376. codec_dai->pop_wait = 0;
  377. mutex_unlock(&rtd->pcm_mutex);
  378. cancel_delayed_work_sync(&rtd->delayed_work);
  379. return ret;
  380. err:
  381. mutex_unlock(&rtd->pcm_mutex);
  382. return ret;
  383. }
  384. static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
  385. struct snd_compr_params *params)
  386. {
  387. struct snd_soc_pcm_runtime *fe = cstream->private_data;
  388. struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
  389. struct snd_soc_platform *platform = fe->platform;
  390. int ret = 0, stream;
  391. if (cstream->direction == SND_COMPRESS_PLAYBACK)
  392. stream = SNDRV_PCM_STREAM_PLAYBACK;
  393. else
  394. stream = SNDRV_PCM_STREAM_CAPTURE;
  395. mutex_lock(&fe->card->dpcm_mutex);
  396. /* first we call set_params for the platform driver
  397. * this should configure the soc side
  398. * if the machine has compressed ops then we call that as well
  399. * expectation is that platform and machine will configure everything
  400. * for this compress path, like configuring pcm port for codec
  401. */
  402. if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
  403. ret = platform->driver->compr_ops->set_params(cstream, params);
  404. if (ret < 0)
  405. goto out;
  406. }
  407. if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
  408. ret = fe->dai_link->compr_ops->set_params(cstream);
  409. if (ret < 0)
  410. goto out;
  411. }
  412. memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
  413. sizeof(struct snd_pcm_hw_params));
  414. fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
  415. ret = dpcm_be_dai_hw_params(fe, stream);
  416. if (ret < 0)
  417. goto out;
  418. ret = dpcm_be_dai_prepare(fe, stream);
  419. if (ret < 0)
  420. goto out;
  421. if (stream == SNDRV_PCM_STREAM_PLAYBACK)
  422. dpcm_dapm_stream_event(fe, stream,
  423. fe->cpu_dai->driver->playback.stream_name,
  424. SND_SOC_DAPM_STREAM_START);
  425. else
  426. dpcm_dapm_stream_event(fe, stream,
  427. fe->cpu_dai->driver->capture.stream_name,
  428. SND_SOC_DAPM_STREAM_START);
  429. fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
  430. out:
  431. fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
  432. mutex_unlock(&fe->card->dpcm_mutex);
  433. return ret;
  434. }
  435. static int soc_compr_get_params(struct snd_compr_stream *cstream,
  436. struct snd_codec *params)
  437. {
  438. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  439. struct snd_soc_platform *platform = rtd->platform;
  440. int ret = 0;
  441. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  442. if (platform->driver->compr_ops && platform->driver->compr_ops->get_params)
  443. ret = platform->driver->compr_ops->get_params(cstream, params);
  444. mutex_unlock(&rtd->pcm_mutex);
  445. return ret;
  446. }
  447. static int soc_compr_get_caps(struct snd_compr_stream *cstream,
  448. struct snd_compr_caps *caps)
  449. {
  450. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  451. struct snd_soc_platform *platform = rtd->platform;
  452. int ret = 0;
  453. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  454. if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps)
  455. ret = platform->driver->compr_ops->get_caps(cstream, caps);
  456. mutex_unlock(&rtd->pcm_mutex);
  457. return ret;
  458. }
  459. static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
  460. struct snd_compr_codec_caps *codec)
  461. {
  462. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  463. struct snd_soc_platform *platform = rtd->platform;
  464. int ret = 0;
  465. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  466. if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps)
  467. ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
  468. mutex_unlock(&rtd->pcm_mutex);
  469. return ret;
  470. }
  471. static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
  472. {
  473. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  474. struct snd_soc_platform *platform = rtd->platform;
  475. int ret = 0;
  476. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  477. if (platform->driver->compr_ops && platform->driver->compr_ops->ack)
  478. ret = platform->driver->compr_ops->ack(cstream, bytes);
  479. mutex_unlock(&rtd->pcm_mutex);
  480. return ret;
  481. }
  482. static int soc_compr_pointer(struct snd_compr_stream *cstream,
  483. struct snd_compr_tstamp *tstamp)
  484. {
  485. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  486. struct snd_soc_platform *platform = rtd->platform;
  487. int ret = 0;
  488. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  489. if (platform->driver->compr_ops && platform->driver->compr_ops->pointer)
  490. ret = platform->driver->compr_ops->pointer(cstream, tstamp);
  491. mutex_unlock(&rtd->pcm_mutex);
  492. return ret;
  493. }
  494. static int soc_compr_copy(struct snd_compr_stream *cstream,
  495. char __user *buf, size_t count)
  496. {
  497. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  498. struct snd_soc_platform *platform = rtd->platform;
  499. int ret = 0;
  500. mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  501. if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
  502. ret = platform->driver->compr_ops->copy(cstream, buf, count);
  503. mutex_unlock(&rtd->pcm_mutex);
  504. return ret;
  505. }
  506. static int sst_compr_set_metadata(struct snd_compr_stream *cstream,
  507. struct snd_compr_metadata *metadata)
  508. {
  509. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  510. struct snd_soc_platform *platform = rtd->platform;
  511. int ret = 0;
  512. if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata)
  513. ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
  514. return ret;
  515. }
  516. static int sst_compr_get_metadata(struct snd_compr_stream *cstream,
  517. struct snd_compr_metadata *metadata)
  518. {
  519. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  520. struct snd_soc_platform *platform = rtd->platform;
  521. int ret = 0;
  522. if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata)
  523. ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
  524. return ret;
  525. }
  526. /* ASoC Compress operations */
  527. static struct snd_compr_ops soc_compr_ops = {
  528. .open = soc_compr_open,
  529. .free = soc_compr_free,
  530. .set_params = soc_compr_set_params,
  531. .set_metadata = sst_compr_set_metadata,
  532. .get_metadata = sst_compr_get_metadata,
  533. .get_params = soc_compr_get_params,
  534. .trigger = soc_compr_trigger,
  535. .pointer = soc_compr_pointer,
  536. .ack = soc_compr_ack,
  537. .get_caps = soc_compr_get_caps,
  538. .get_codec_caps = soc_compr_get_codec_caps
  539. };
  540. /* ASoC Dynamic Compress operations */
  541. static struct snd_compr_ops soc_compr_dyn_ops = {
  542. .open = soc_compr_open_fe,
  543. .free = soc_compr_free_fe,
  544. .set_params = soc_compr_set_params_fe,
  545. .get_params = soc_compr_get_params,
  546. .set_metadata = sst_compr_set_metadata,
  547. .get_metadata = sst_compr_get_metadata,
  548. .trigger = soc_compr_trigger_fe,
  549. .pointer = soc_compr_pointer,
  550. .ack = soc_compr_ack,
  551. .get_caps = soc_compr_get_caps,
  552. .get_codec_caps = soc_compr_get_codec_caps
  553. };
  554. /* create a new compress */
  555. int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
  556. {
  557. struct snd_soc_codec *codec = rtd->codec;
  558. struct snd_soc_platform *platform = rtd->platform;
  559. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  560. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  561. struct snd_compr *compr;
  562. struct snd_pcm *be_pcm;
  563. char new_name[64];
  564. int ret = 0, direction = 0;
  565. /* check client and interface hw capabilities */
  566. snprintf(new_name, sizeof(new_name), "%s %s-%d",
  567. rtd->dai_link->stream_name, codec_dai->name, num);
  568. direction = SND_COMPRESS_PLAYBACK;
  569. compr = kzalloc(sizeof(*compr), GFP_KERNEL);
  570. if (compr == NULL) {
  571. snd_printk(KERN_ERR "Cannot allocate compr\n");
  572. return -ENOMEM;
  573. }
  574. compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
  575. GFP_KERNEL);
  576. if (compr->ops == NULL) {
  577. dev_err(rtd->card->dev, "Cannot allocate compressed ops\n");
  578. ret = -ENOMEM;
  579. goto compr_err;
  580. }
  581. if (rtd->dai_link->dynamic) {
  582. snprintf(new_name, sizeof(new_name), "(%s)",
  583. rtd->dai_link->stream_name);
  584. ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
  585. 1, 0, &be_pcm);
  586. if (ret < 0) {
  587. dev_err(rtd->card->dev, "ASoC: can't create compressed for %s\n",
  588. rtd->dai_link->name);
  589. goto compr_err;
  590. }
  591. rtd->pcm = be_pcm;
  592. rtd->fe_compr = 1;
  593. be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
  594. //be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
  595. memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
  596. } else
  597. memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
  598. /* Add copy callback for not memory mapped DSPs */
  599. if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
  600. compr->ops->copy = soc_compr_copy;
  601. mutex_init(&compr->lock);
  602. ret = snd_compress_new(rtd->card->snd_card, num, direction, compr);
  603. if (ret < 0) {
  604. pr_err("compress asoc: can't create compress for codec %s\n",
  605. codec->name);
  606. goto compr_err;
  607. }
  608. /* DAPM dai link stream work */
  609. INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
  610. rtd->compr = compr;
  611. compr->private_data = rtd;
  612. if (platform->driver->pcm_new) {
  613. ret = platform->driver->pcm_new(rtd);
  614. if (ret < 0) {
  615. pr_err("asoc: compress pcm constructor failed\n");
  616. goto compr_err;
  617. }
  618. }
  619. printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
  620. cpu_dai->name);
  621. return ret;
  622. compr_err:
  623. kfree(compr);
  624. return ret;
  625. }