pcm.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // This file is provided under a dual BSD/GPLv2 license. When using or
  4. // redistributing this file, you may do so under either license.
  5. //
  6. // Copyright(c) 2018 Intel Corporation
  7. //
  8. // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
  9. //
  10. // PCM Layer, interface between ALSA and IPC.
  11. //
  12. #include <linux/pm_runtime.h>
  13. #include <sound/pcm_params.h>
  14. #include <sound/sof.h>
  15. #include <trace/events/sof.h>
  16. #include "sof-of-dev.h"
  17. #include "sof-priv.h"
  18. #include "sof-audio.h"
  19. #include "sof-utils.h"
  20. #include "ops.h"
  21. /*
  22. * sof pcm period elapse work
  23. */
  24. static void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
  25. {
  26. struct snd_sof_pcm_stream *sps =
  27. container_of(work, struct snd_sof_pcm_stream,
  28. period_elapsed_work);
  29. snd_pcm_period_elapsed(sps->substream);
  30. }
  31. void snd_sof_pcm_init_elapsed_work(struct work_struct *work)
  32. {
  33. INIT_WORK(work, snd_sof_pcm_period_elapsed_work);
  34. }
  35. /*
  36. * sof pcm period elapse, this could be called at irq thread context.
  37. */
  38. void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
  39. {
  40. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  41. struct snd_soc_component *component =
  42. snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
  43. struct snd_sof_pcm *spcm;
  44. spcm = snd_sof_find_spcm_dai(component, rtd);
  45. if (!spcm) {
  46. dev_err(component->dev,
  47. "error: period elapsed for unknown stream!\n");
  48. return;
  49. }
  50. /*
  51. * snd_pcm_period_elapsed() can be called in interrupt context
  52. * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(),
  53. * when the PCM is done draining or xrun happened, a STOP IPC will
  54. * then be sent and this IPC will hit IPC timeout.
  55. * To avoid sending IPC before the previous IPC is handled, we
  56. * schedule delayed work here to call the snd_pcm_period_elapsed().
  57. */
  58. schedule_work(&spcm->stream[substream->stream].period_elapsed_work);
  59. }
  60. EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);
  61. static int
  62. sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
  63. struct snd_sof_pcm *spcm, struct snd_pcm_hw_params *params,
  64. struct snd_sof_platform_stream_params *platform_params, int dir)
  65. {
  66. struct snd_soc_dai *dai;
  67. int ret, j;
  68. /* query DAPM for list of connected widgets and set them up */
  69. for_each_rtd_cpu_dais(rtd, j, dai) {
  70. struct snd_soc_dapm_widget_list *list;
  71. ret = snd_soc_dapm_dai_get_connected_widgets(dai, dir, &list,
  72. dpcm_end_walk_at_be);
  73. if (ret < 0) {
  74. spcm_err(spcm, dir, "dai %s has no valid %s path\n",
  75. dai->name, snd_pcm_direction_name(dir));
  76. return ret;
  77. }
  78. spcm->stream[dir].list = list;
  79. ret = sof_widget_list_prepare(sdev, spcm, params, platform_params, dir);
  80. if (ret < 0) {
  81. spcm_err(spcm, dir, "widget list prepare failed\n");
  82. spcm->stream[dir].list = NULL;
  83. snd_soc_dapm_dai_free_widgets(&list);
  84. return ret;
  85. }
  86. }
  87. return 0;
  88. }
  89. static struct snd_sof_widget *snd_sof_find_swidget_by_comp_id(struct snd_sof_dev *sdev,
  90. int comp_id)
  91. {
  92. struct snd_sof_widget *swidget;
  93. list_for_each_entry(swidget, &sdev->widget_list, list) {
  94. if (comp_id == swidget->comp_id)
  95. return swidget;
  96. }
  97. return NULL;
  98. }
  99. static int sof_pcm_hw_params(struct snd_soc_component *component,
  100. struct snd_pcm_substream *substream,
  101. struct snd_pcm_hw_params *params)
  102. {
  103. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  104. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  105. const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
  106. const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
  107. struct snd_sof_platform_stream_params *platform_params;
  108. struct snd_pcm_runtime *runtime = substream->runtime;
  109. struct snd_sof_widget *host_widget;
  110. struct snd_sof_pcm *spcm;
  111. int ret;
  112. /* nothing to do for BE */
  113. if (rtd->dai_link->no_pcm)
  114. return 0;
  115. spcm = snd_sof_find_spcm_dai(component, rtd);
  116. if (!spcm)
  117. return -EINVAL;
  118. spcm_dbg(spcm, substream->stream, "Entry: hw_params\n");
  119. if (!sdev->dspless_mode_selected) {
  120. /*
  121. * Make sure that the DSP is booted up, which might not be the
  122. * case if the on-demand DSP boot is used
  123. */
  124. ret = snd_sof_boot_dsp_firmware(sdev);
  125. if (ret)
  126. return ret;
  127. }
  128. /*
  129. * Handle repeated calls to hw_params() without free_pcm() in
  130. * between. At least ALSA OSS emulation depends on this.
  131. */
  132. if (spcm->prepared[substream->stream] && pcm_ops && pcm_ops->hw_free) {
  133. ret = pcm_ops->hw_free(component, substream);
  134. if (ret < 0)
  135. return ret;
  136. spcm->prepared[substream->stream] = false;
  137. }
  138. platform_params = &spcm->platform_params[substream->stream];
  139. ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, platform_params);
  140. if (ret < 0) {
  141. spcm_err(spcm, substream->stream, "platform hw params failed\n");
  142. return ret;
  143. }
  144. /* if this is a repeated hw_params without hw_free, skip setting up widgets */
  145. if (!spcm->stream[substream->stream].list) {
  146. ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, params, platform_params,
  147. substream->stream);
  148. if (ret < 0)
  149. return ret;
  150. }
  151. if (!sdev->dspless_mode_selected) {
  152. int host_comp_id = spcm->stream[substream->stream].comp_id;
  153. host_widget = snd_sof_find_swidget_by_comp_id(sdev, host_comp_id);
  154. if (!host_widget) {
  155. spcm_err(spcm, substream->stream,
  156. "failed to find host widget with comp_id %d\n", host_comp_id);
  157. return -EINVAL;
  158. }
  159. /* set the host DMA ID */
  160. if (tplg_ops && tplg_ops->host_config)
  161. tplg_ops->host_config(sdev, host_widget, platform_params);
  162. }
  163. /* create compressed page table for audio firmware */
  164. if (runtime->buffer_changed) {
  165. struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream);
  166. ret = snd_sof_create_page_table(component->dev, dmab,
  167. spcm->stream[substream->stream].page_table.area,
  168. runtime->dma_bytes);
  169. if (ret < 0)
  170. return ret;
  171. }
  172. /* save pcm hw_params */
  173. memcpy(&spcm->params[substream->stream], params, sizeof(*params));
  174. return 0;
  175. }
  176. static int sof_pcm_stream_free(struct snd_sof_dev *sdev,
  177. struct snd_pcm_substream *substream,
  178. struct snd_sof_pcm *spcm, int dir,
  179. bool free_widget_list)
  180. {
  181. const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
  182. int ret;
  183. int err = 0;
  184. if (spcm->prepared[substream->stream]) {
  185. /* stop DMA first if needed */
  186. if (pcm_ops && pcm_ops->platform_stop_during_hw_free)
  187. snd_sof_pcm_platform_trigger(sdev, substream,
  188. SNDRV_PCM_TRIGGER_STOP);
  189. /* free PCM in the DSP */
  190. if (pcm_ops && pcm_ops->hw_free) {
  191. ret = pcm_ops->hw_free(sdev->component, substream);
  192. if (ret < 0) {
  193. spcm_err(spcm, substream->stream,
  194. "pcm_ops->hw_free failed %d\n", ret);
  195. err = ret;
  196. }
  197. }
  198. spcm->prepared[substream->stream] = false;
  199. spcm->pending_stop[substream->stream] = false;
  200. }
  201. /* reset the DMA */
  202. ret = snd_sof_pcm_platform_hw_free(sdev, substream);
  203. if (ret < 0) {
  204. spcm_err(spcm, substream->stream,
  205. "platform hw free failed %d\n", ret);
  206. if (!err)
  207. err = ret;
  208. }
  209. /* free widget list */
  210. if (free_widget_list) {
  211. ret = sof_widget_list_free(sdev, spcm, dir);
  212. if (ret < 0) {
  213. spcm_err(spcm, substream->stream,
  214. "sof_widget_list_free failed %d\n", ret);
  215. if (!err)
  216. err = ret;
  217. }
  218. }
  219. return err;
  220. }
  221. int sof_pcm_free_all_streams(struct snd_sof_dev *sdev)
  222. {
  223. struct snd_pcm_substream *substream;
  224. struct snd_sof_pcm *spcm;
  225. int dir, ret;
  226. list_for_each_entry(spcm, &sdev->pcm_list, list) {
  227. for_each_pcm_streams(dir) {
  228. substream = spcm->stream[dir].substream;
  229. if (!substream || !substream->runtime ||
  230. spcm->stream[dir].suspend_ignored)
  231. continue;
  232. if (spcm->stream[dir].list) {
  233. ret = sof_pcm_stream_free(sdev, substream, spcm,
  234. dir, true);
  235. if (ret < 0)
  236. return ret;
  237. }
  238. }
  239. }
  240. return 0;
  241. }
  242. static int sof_pcm_hw_free(struct snd_soc_component *component,
  243. struct snd_pcm_substream *substream)
  244. {
  245. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  246. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  247. struct snd_sof_pcm *spcm;
  248. int ret;
  249. /* nothing to do for BE */
  250. if (rtd->dai_link->no_pcm)
  251. return 0;
  252. spcm = snd_sof_find_spcm_dai(component, rtd);
  253. if (!spcm)
  254. return -EINVAL;
  255. spcm_dbg(spcm, substream->stream, "Entry: hw_free\n");
  256. ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true);
  257. /* unprepare and free the list of DAPM widgets */
  258. sof_widget_list_unprepare(sdev, spcm, substream->stream);
  259. cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
  260. return ret;
  261. }
  262. static int sof_pcm_prepare(struct snd_soc_component *component,
  263. struct snd_pcm_substream *substream)
  264. {
  265. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  266. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  267. const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
  268. struct snd_sof_platform_stream_params *platform_params;
  269. struct snd_soc_dapm_widget_list *list;
  270. struct snd_pcm_hw_params *params;
  271. struct snd_sof_pcm *spcm;
  272. int dir = substream->stream;
  273. int ret;
  274. /* nothing to do for BE */
  275. if (rtd->dai_link->no_pcm)
  276. return 0;
  277. spcm = snd_sof_find_spcm_dai(component, rtd);
  278. if (!spcm)
  279. return -EINVAL;
  280. spcm_dbg(spcm, substream->stream, "Entry: prepare\n");
  281. if (spcm->prepared[substream->stream]) {
  282. if (!spcm->pending_stop[substream->stream])
  283. return 0;
  284. /*
  285. * this case should be reached in case of xruns where we absolutely
  286. * want to free-up and reset all PCM/DMA resources
  287. */
  288. ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true);
  289. if (ret < 0)
  290. return ret;
  291. }
  292. ret = sof_pcm_hw_params(component, substream, &spcm->params[substream->stream]);
  293. if (ret < 0) {
  294. spcm_err(spcm, substream->stream,
  295. "failed to set hw_params after resume\n");
  296. return ret;
  297. }
  298. list = spcm->stream[dir].list;
  299. params = &spcm->params[substream->stream];
  300. platform_params = &spcm->platform_params[substream->stream];
  301. ret = sof_widget_list_setup(sdev, spcm, params, platform_params, dir);
  302. if (ret < 0) {
  303. dev_err(sdev->dev, "failed widget list set up for pcm %d dir %d\n",
  304. spcm->pcm.pcm_id, dir);
  305. spcm->stream[dir].list = NULL;
  306. snd_soc_dapm_dai_free_widgets(&list);
  307. return ret;
  308. }
  309. if (pcm_ops && pcm_ops->hw_params) {
  310. ret = pcm_ops->hw_params(component, substream, params, platform_params);
  311. if (ret < 0)
  312. return ret;
  313. }
  314. spcm->prepared[substream->stream] = true;
  315. return 0;
  316. }
  317. /*
  318. * FE dai link trigger actions are always executed in non-atomic context because
  319. * they involve IPC's.
  320. */
  321. static int sof_pcm_trigger(struct snd_soc_component *component,
  322. struct snd_pcm_substream *substream, int cmd)
  323. {
  324. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  325. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  326. const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
  327. struct snd_sof_pcm *spcm;
  328. bool reset_hw_params = false;
  329. bool ipc_first = false;
  330. int ret = 0;
  331. /* nothing to do for BE */
  332. if (rtd->dai_link->no_pcm)
  333. return 0;
  334. spcm = snd_sof_find_spcm_dai(component, rtd);
  335. if (!spcm)
  336. return -EINVAL;
  337. spcm_dbg(spcm, substream->stream, "Entry: trigger (cmd: %d)\n", cmd);
  338. spcm->pending_stop[substream->stream] = false;
  339. switch (cmd) {
  340. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  341. ipc_first = true;
  342. break;
  343. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  344. if (pcm_ops && pcm_ops->ipc_first_on_start)
  345. ipc_first = true;
  346. break;
  347. case SNDRV_PCM_TRIGGER_START:
  348. if (spcm->stream[substream->stream].suspend_ignored) {
  349. /*
  350. * This case will be triggered when INFO_RESUME is
  351. * not supported, no need to re-start streams that
  352. * remained enabled in D0ix.
  353. */
  354. spcm->stream[substream->stream].suspend_ignored = false;
  355. return 0;
  356. }
  357. if (pcm_ops && pcm_ops->ipc_first_on_start)
  358. ipc_first = true;
  359. break;
  360. case SNDRV_PCM_TRIGGER_SUSPEND:
  361. /*
  362. * If DSP D0I3 is allowed during S0iX, set the suspend_ignored flag for
  363. * D0I3-compatible streams to keep the firmware pipeline running
  364. */
  365. if (pcm_ops && pcm_ops->d0i3_supported_in_s0ix &&
  366. sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
  367. spcm->stream[substream->stream].d0i3_compatible) {
  368. spcm->stream[substream->stream].suspend_ignored = true;
  369. return 0;
  370. }
  371. /* On suspend the DMA must be stopped in DSPless mode */
  372. if (sdev->dspless_mode_selected)
  373. reset_hw_params = true;
  374. fallthrough;
  375. case SNDRV_PCM_TRIGGER_STOP:
  376. ipc_first = true;
  377. if (pcm_ops && pcm_ops->reset_hw_params_during_stop)
  378. reset_hw_params = true;
  379. break;
  380. default:
  381. spcm_err(spcm, substream->stream, "Unhandled trigger cmd %d\n", cmd);
  382. return -EINVAL;
  383. }
  384. if (!ipc_first)
  385. snd_sof_pcm_platform_trigger(sdev, substream, cmd);
  386. if (pcm_ops && pcm_ops->trigger)
  387. ret = pcm_ops->trigger(component, substream, cmd);
  388. switch (cmd) {
  389. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  390. case SNDRV_PCM_TRIGGER_START:
  391. /* invoke platform trigger to start DMA only if pcm_ops is successful */
  392. if (ipc_first && !ret)
  393. snd_sof_pcm_platform_trigger(sdev, substream, cmd);
  394. break;
  395. case SNDRV_PCM_TRIGGER_SUSPEND:
  396. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  397. case SNDRV_PCM_TRIGGER_STOP:
  398. /* invoke platform trigger to stop DMA even if pcm_ops isn't set or if it failed */
  399. if (!pcm_ops || !pcm_ops->platform_stop_during_hw_free)
  400. snd_sof_pcm_platform_trigger(sdev, substream, cmd);
  401. /*
  402. * set the pending_stop flag to indicate that pipeline stop has been delayed.
  403. * This will be used later to stop the pipelines during prepare when recovering
  404. * from xruns.
  405. */
  406. if (pcm_ops && pcm_ops->platform_stop_during_hw_free &&
  407. cmd == SNDRV_PCM_TRIGGER_STOP)
  408. spcm->pending_stop[substream->stream] = true;
  409. break;
  410. default:
  411. break;
  412. }
  413. /* free PCM if reset_hw_params is set and the STOP IPC is successful */
  414. if (!ret && reset_hw_params)
  415. ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, false);
  416. return ret;
  417. }
  418. static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component,
  419. struct snd_pcm_substream *substream)
  420. {
  421. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  422. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  423. const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
  424. struct snd_sof_pcm *spcm;
  425. snd_pcm_uframes_t host, dai;
  426. int ret = -EOPNOTSUPP;
  427. /* nothing to do for BE */
  428. if (rtd->dai_link->no_pcm)
  429. return 0;
  430. if (pcm_ops && pcm_ops->pointer)
  431. ret = pcm_ops->pointer(component, substream, &host);
  432. if (ret != -EOPNOTSUPP)
  433. return ret ? ret : host;
  434. /* use dsp ops pointer callback directly if set */
  435. if (sof_ops(sdev)->pcm_pointer)
  436. return sof_ops(sdev)->pcm_pointer(sdev, substream);
  437. spcm = snd_sof_find_spcm_dai(component, rtd);
  438. if (!spcm)
  439. return -EINVAL;
  440. /* read position from DSP */
  441. host = bytes_to_frames(substream->runtime,
  442. spcm->stream[substream->stream].posn.host_posn);
  443. dai = bytes_to_frames(substream->runtime,
  444. spcm->stream[substream->stream].posn.dai_posn);
  445. trace_sof_pcm_pointer_position(sdev, spcm, substream, host, dai);
  446. return host;
  447. }
  448. static int sof_pcm_open(struct snd_soc_component *component,
  449. struct snd_pcm_substream *substream)
  450. {
  451. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  452. struct snd_pcm_runtime *runtime = substream->runtime;
  453. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  454. const struct snd_sof_dsp_ops *ops = sof_ops(sdev);
  455. struct snd_sof_pcm *spcm;
  456. struct snd_soc_tplg_stream_caps *caps;
  457. int ret;
  458. /* nothing to do for BE */
  459. if (rtd->dai_link->no_pcm)
  460. return 0;
  461. spcm = snd_sof_find_spcm_dai(component, rtd);
  462. if (!spcm)
  463. return -EINVAL;
  464. spcm_dbg(spcm, substream->stream, "Entry: open\n");
  465. caps = &spcm->pcm.caps[substream->stream];
  466. /* set runtime config */
  467. runtime->hw.info = ops->hw_info; /* platform-specific */
  468. /* set any runtime constraints based on topology */
  469. runtime->hw.formats = le64_to_cpu(caps->formats);
  470. runtime->hw.period_bytes_min = le32_to_cpu(caps->period_size_min);
  471. runtime->hw.period_bytes_max = le32_to_cpu(caps->period_size_max);
  472. runtime->hw.periods_min = le32_to_cpu(caps->periods_min);
  473. runtime->hw.periods_max = le32_to_cpu(caps->periods_max);
  474. /*
  475. * caps->buffer_size_min is not used since the
  476. * snd_pcm_hardware structure only defines buffer_bytes_max
  477. */
  478. runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max);
  479. /* set wait time - TODO: come from topology */
  480. substream->wait_time = 500;
  481. spcm->stream[substream->stream].posn.host_posn = 0;
  482. spcm->stream[substream->stream].posn.dai_posn = 0;
  483. spcm->stream[substream->stream].substream = substream;
  484. spcm->prepared[substream->stream] = false;
  485. ret = snd_sof_pcm_platform_open(sdev, substream);
  486. if (ret < 0) {
  487. spcm_err(spcm, substream->stream,
  488. "platform pcm open failed %d\n", ret);
  489. return ret;
  490. }
  491. spcm_dbg(spcm, substream->stream, "period bytes min %zd, max %zd\n",
  492. runtime->hw.period_bytes_min, runtime->hw.period_bytes_max);
  493. spcm_dbg(spcm, substream->stream, "period count min %d, max %d\n",
  494. runtime->hw.periods_min, runtime->hw.periods_max);
  495. spcm_dbg(spcm, substream->stream, "buffer bytes max %zd\n", runtime->hw.buffer_bytes_max);
  496. return 0;
  497. }
  498. static int sof_pcm_close(struct snd_soc_component *component,
  499. struct snd_pcm_substream *substream)
  500. {
  501. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  502. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  503. struct snd_sof_pcm *spcm;
  504. int err;
  505. /* nothing to do for BE */
  506. if (rtd->dai_link->no_pcm)
  507. return 0;
  508. spcm = snd_sof_find_spcm_dai(component, rtd);
  509. if (!spcm)
  510. return -EINVAL;
  511. spcm_dbg(spcm, substream->stream, "Entry: close\n");
  512. err = snd_sof_pcm_platform_close(sdev, substream);
  513. if (err < 0) {
  514. spcm_err(spcm, substream->stream,
  515. "platform pcm close failed %d\n", err);
  516. /*
  517. * keep going, no point in preventing the close
  518. * from happening
  519. */
  520. }
  521. spcm->stream[substream->stream].substream = NULL;
  522. return 0;
  523. }
  524. /*
  525. * Pre-allocate playback/capture audio buffer pages.
  526. * no need to explicitly release memory preallocated by sof_pcm_new in pcm_free
  527. * snd_pcm_lib_preallocate_free_for_all() is called by the core.
  528. */
  529. static int sof_pcm_new(struct snd_soc_component *component,
  530. struct snd_soc_pcm_runtime *rtd)
  531. {
  532. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  533. struct snd_sof_pcm *spcm;
  534. struct snd_pcm *pcm = rtd->pcm;
  535. struct snd_soc_tplg_stream_caps *caps;
  536. int stream = SNDRV_PCM_STREAM_PLAYBACK;
  537. /* find SOF PCM for this RTD */
  538. spcm = snd_sof_find_spcm_dai(component, rtd);
  539. if (!spcm) {
  540. dev_warn(component->dev, "warn: can't find PCM with DAI ID %d\n",
  541. rtd->dai_link->id);
  542. return 0;
  543. }
  544. dev_dbg(spcm->scomp->dev, "pcm%u (%s): Entry: pcm_construct\n",
  545. spcm->pcm.pcm_id, spcm->pcm.pcm_name);
  546. /* do we need to pre-allocate playback audio buffer pages */
  547. if (!spcm->pcm.playback)
  548. goto capture;
  549. caps = &spcm->pcm.caps[stream];
  550. if (!pcm->streams[stream].substream) {
  551. spcm_err(spcm, stream, "NULL playback substream!\n");
  552. return -EINVAL;
  553. }
  554. /* pre-allocate playback audio buffer pages */
  555. spcm_dbg(spcm, stream, "allocate %s playback DMA buffer size 0x%x max 0x%x\n",
  556. caps->name, caps->buffer_size_min, caps->buffer_size_max);
  557. snd_pcm_set_managed_buffer(pcm->streams[stream].substream,
  558. SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
  559. 0, le32_to_cpu(caps->buffer_size_max));
  560. /* Set the PCM device name for HDMI playback */
  561. if (!strncmp(pcm->id, "HDMI", 4)) {
  562. int hdmi_idx;
  563. /*
  564. * Make sure that the name is in"HDMI<SPACE>x" format as this is
  565. * expected by user space.
  566. * See alsa-lib's __snd_pcm_info_eld_fixup_check() which is
  567. * guarding the __snd_pcm_info_eld_fixup() in
  568. * snd_ctl_hw_pcm_info() and snd_pcm_hw_info() library functions
  569. */
  570. if (sscanf(pcm->id, "HDMI%d", &hdmi_idx) == 1)
  571. snprintf(pcm->name, sizeof(pcm->name), "HDMI %d",
  572. hdmi_idx);
  573. else
  574. strscpy(pcm->name, pcm->id, sizeof(pcm->name));
  575. }
  576. capture:
  577. stream = SNDRV_PCM_STREAM_CAPTURE;
  578. /* do we need to pre-allocate capture audio buffer pages */
  579. if (!spcm->pcm.capture)
  580. return 0;
  581. caps = &spcm->pcm.caps[stream];
  582. if (!pcm->streams[stream].substream) {
  583. spcm_err(spcm, stream, "NULL capture substream!\n");
  584. return -EINVAL;
  585. }
  586. /* pre-allocate capture audio buffer pages */
  587. spcm_dbg(spcm, stream, "allocate %s capture DMA buffer size 0x%x max 0x%x\n",
  588. caps->name, caps->buffer_size_min, caps->buffer_size_max);
  589. snd_pcm_set_managed_buffer(pcm->streams[stream].substream,
  590. SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
  591. 0, le32_to_cpu(caps->buffer_size_max));
  592. return 0;
  593. }
  594. /* fixup the BE DAI link to match any values from topology */
  595. int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params)
  596. {
  597. struct snd_interval *rate = hw_param_interval(params,
  598. SNDRV_PCM_HW_PARAM_RATE);
  599. struct snd_interval *channels = hw_param_interval(params,
  600. SNDRV_PCM_HW_PARAM_CHANNELS);
  601. struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
  602. struct snd_soc_component *component =
  603. snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
  604. struct snd_sof_dai *dai =
  605. snd_sof_find_dai(component, (char *)rtd->dai_link->name);
  606. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  607. const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
  608. /* no topology exists for this BE, try a common configuration */
  609. if (!dai) {
  610. dev_warn(component->dev,
  611. "warning: no topology found for BE DAI %s config\n",
  612. rtd->dai_link->name);
  613. /* set 48k, stereo, 16bits by default */
  614. rate->min = 48000;
  615. rate->max = 48000;
  616. channels->min = 2;
  617. channels->max = 2;
  618. snd_mask_none(fmt);
  619. snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
  620. return 0;
  621. }
  622. if (pcm_ops && pcm_ops->dai_link_fixup)
  623. return pcm_ops->dai_link_fixup(rtd, params);
  624. return 0;
  625. }
  626. EXPORT_SYMBOL(sof_pcm_dai_link_fixup);
  627. static int sof_pcm_probe(struct snd_soc_component *component)
  628. {
  629. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  630. struct snd_sof_pdata *plat_data = sdev->pdata;
  631. const char *tplg_filename;
  632. int ret;
  633. /*
  634. * make sure the device is pm_runtime_active before loading the
  635. * topology and initiating IPC or bus transactions
  636. */
  637. ret = pm_runtime_resume_and_get(component->dev);
  638. if (ret < 0 && ret != -EACCES)
  639. return ret;
  640. /* load the default topology */
  641. sdev->component = component;
  642. tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
  643. "%s/%s",
  644. plat_data->tplg_filename_prefix,
  645. plat_data->tplg_filename);
  646. if (!tplg_filename) {
  647. ret = -ENOMEM;
  648. goto pm_error;
  649. }
  650. ret = snd_sof_load_topology(component, tplg_filename);
  651. if (ret < 0)
  652. dev_err(component->dev, "error: failed to load DSP topology %d\n",
  653. ret);
  654. pm_error:
  655. pm_runtime_put_autosuspend(component->dev);
  656. return ret;
  657. }
  658. static void sof_pcm_remove(struct snd_soc_component *component)
  659. {
  660. /* remove topology */
  661. snd_soc_tplg_component_remove(component);
  662. }
  663. static int sof_pcm_ack(struct snd_soc_component *component,
  664. struct snd_pcm_substream *substream)
  665. {
  666. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  667. return snd_sof_pcm_platform_ack(sdev, substream);
  668. }
  669. static snd_pcm_sframes_t sof_pcm_delay(struct snd_soc_component *component,
  670. struct snd_pcm_substream *substream)
  671. {
  672. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
  673. const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
  674. if (pcm_ops && pcm_ops->delay)
  675. return pcm_ops->delay(component, substream);
  676. return 0;
  677. }
  678. void snd_sof_new_platform_drv(struct snd_sof_dev *sdev)
  679. {
  680. struct snd_soc_component_driver *pd = &sdev->plat_drv;
  681. struct snd_sof_pdata *plat_data = sdev->pdata;
  682. const char *drv_name;
  683. if (plat_data->machine)
  684. drv_name = plat_data->machine->drv_name;
  685. else if (plat_data->of_machine)
  686. drv_name = plat_data->of_machine->drv_name;
  687. else
  688. drv_name = NULL;
  689. pd->name = "sof-audio-component";
  690. pd->probe = sof_pcm_probe;
  691. pd->remove = sof_pcm_remove;
  692. pd->open = sof_pcm_open;
  693. pd->close = sof_pcm_close;
  694. pd->hw_params = sof_pcm_hw_params;
  695. pd->prepare = sof_pcm_prepare;
  696. pd->hw_free = sof_pcm_hw_free;
  697. pd->trigger = sof_pcm_trigger;
  698. pd->pointer = sof_pcm_pointer;
  699. pd->ack = sof_pcm_ack;
  700. pd->delay = sof_pcm_delay;
  701. #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS)
  702. pd->compress_ops = &sof_compressed_ops;
  703. #endif
  704. pd->pcm_construct = sof_pcm_new;
  705. pd->ignore_machine = drv_name;
  706. pd->be_pcm_base = SOF_BE_PCM_BASE;
  707. pd->use_dai_pcm_id = true;
  708. pd->topology_name_prefix = "sof";
  709. /* increment module refcount when a pcm is opened */
  710. pd->module_get_upon_open = 1;
  711. pd->legacy_dai_naming = 1;
  712. /*
  713. * The fixup is only needed when the DSP is in use as with the DSPless
  714. * mode we are directly using the audio interface
  715. */
  716. if (!sdev->dspless_mode_selected)
  717. pd->be_hw_params_fixup = sof_pcm_dai_link_fixup;
  718. }