soc-dai.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // soc-dai.c
  4. //
  5. // Copyright (C) 2019 Renesas Electronics Corp.
  6. // Kuninori Morimoto <[email protected]>
  7. //
  8. #include <sound/soc.h>
  9. #include <sound/soc-dai.h>
  10. #include <sound/soc-link.h>
  11. #define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret)
  12. static inline int _soc_dai_ret(struct snd_soc_dai *dai,
  13. const char *func, int ret)
  14. {
  15. /* Positive, Zero values are not errors */
  16. if (ret >= 0)
  17. return ret;
  18. /* Negative values might be errors */
  19. switch (ret) {
  20. case -EPROBE_DEFER:
  21. case -ENOTSUPP:
  22. break;
  23. default:
  24. dev_err(dai->dev,
  25. "ASoC: error at %s on %s: %d\n",
  26. func, dai->name, ret);
  27. }
  28. return ret;
  29. }
  30. /*
  31. * We might want to check substream by using list.
  32. * In such case, we can update these macros.
  33. */
  34. #define soc_dai_mark_push(dai, substream, tgt) ((dai)->mark_##tgt = substream)
  35. #define soc_dai_mark_pop(dai, substream, tgt) ((dai)->mark_##tgt = NULL)
  36. #define soc_dai_mark_match(dai, substream, tgt) ((dai)->mark_##tgt == substream)
  37. /**
  38. * snd_soc_dai_set_sysclk - configure DAI system or master clock.
  39. * @dai: DAI
  40. * @clk_id: DAI specific clock ID
  41. * @freq: new clock frequency in Hz
  42. * @dir: new clock direction - input/output.
  43. *
  44. * Configures the DAI master (MCLK) or system (SYSCLK) clocking.
  45. */
  46. int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
  47. unsigned int freq, int dir)
  48. {
  49. int ret;
  50. if (dai->driver->ops &&
  51. dai->driver->ops->set_sysclk)
  52. ret = dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
  53. else
  54. ret = snd_soc_component_set_sysclk(dai->component, clk_id, 0,
  55. freq, dir);
  56. return soc_dai_ret(dai, ret);
  57. }
  58. EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
  59. /**
  60. * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
  61. * @dai: DAI
  62. * @div_id: DAI specific clock divider ID
  63. * @div: new clock divisor.
  64. *
  65. * Configures the clock dividers. This is used to derive the best DAI bit and
  66. * frame clocks from the system or master clock. It's best to set the DAI bit
  67. * and frame clocks as low as possible to save system power.
  68. */
  69. int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
  70. int div_id, int div)
  71. {
  72. int ret = -EINVAL;
  73. if (dai->driver->ops &&
  74. dai->driver->ops->set_clkdiv)
  75. ret = dai->driver->ops->set_clkdiv(dai, div_id, div);
  76. return soc_dai_ret(dai, ret);
  77. }
  78. EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
  79. /**
  80. * snd_soc_dai_set_pll - configure DAI PLL.
  81. * @dai: DAI
  82. * @pll_id: DAI specific PLL ID
  83. * @source: DAI specific source for the PLL
  84. * @freq_in: PLL input clock frequency in Hz
  85. * @freq_out: requested PLL output clock frequency in Hz
  86. *
  87. * Configures and enables PLL to generate output clock based on input clock.
  88. */
  89. int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
  90. unsigned int freq_in, unsigned int freq_out)
  91. {
  92. int ret;
  93. if (dai->driver->ops &&
  94. dai->driver->ops->set_pll)
  95. ret = dai->driver->ops->set_pll(dai, pll_id, source,
  96. freq_in, freq_out);
  97. else
  98. ret = snd_soc_component_set_pll(dai->component, pll_id, source,
  99. freq_in, freq_out);
  100. return soc_dai_ret(dai, ret);
  101. }
  102. EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
  103. /**
  104. * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
  105. * @dai: DAI
  106. * @ratio: Ratio of BCLK to Sample rate.
  107. *
  108. * Configures the DAI for a preset BCLK to sample rate ratio.
  109. */
  110. int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
  111. {
  112. int ret = -ENOTSUPP;
  113. if (dai->driver->ops &&
  114. dai->driver->ops->set_bclk_ratio)
  115. ret = dai->driver->ops->set_bclk_ratio(dai, ratio);
  116. return soc_dai_ret(dai, ret);
  117. }
  118. EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
  119. int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd)
  120. {
  121. struct snd_soc_dai *dai;
  122. int i, max = 0;
  123. /*
  124. * return max num if *ALL* DAIs have .auto_selectable_formats
  125. */
  126. for_each_rtd_dais(rtd, i, dai) {
  127. if (dai->driver->ops &&
  128. dai->driver->ops->num_auto_selectable_formats)
  129. max = max(max, dai->driver->ops->num_auto_selectable_formats);
  130. else
  131. return 0;
  132. }
  133. return max;
  134. }
  135. /**
  136. * snd_soc_dai_get_fmt - get supported audio format.
  137. * @dai: DAI
  138. * @priority: priority level of supported audio format.
  139. *
  140. * This should return only formats implemented with high
  141. * quality by the DAI so that the core can configure a
  142. * format which will work well with other devices.
  143. * For example devices which don't support both edges of the
  144. * LRCLK signal in I2S style formats should only list DSP
  145. * modes. This will mean that sometimes fewer formats
  146. * are reported here than are supported by set_fmt().
  147. */
  148. u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority)
  149. {
  150. const struct snd_soc_dai_ops *ops = dai->driver->ops;
  151. u64 fmt = 0;
  152. int i, max = 0, until = priority;
  153. /*
  154. * Collect auto_selectable_formats until priority
  155. *
  156. * ex)
  157. * auto_selectable_formats[] = { A, B, C };
  158. * (A, B, C = SND_SOC_POSSIBLE_DAIFMT_xxx)
  159. *
  160. * priority = 1 : A
  161. * priority = 2 : A | B
  162. * priority = 3 : A | B | C
  163. * priority = 4 : A | B | C
  164. * ...
  165. */
  166. if (ops)
  167. max = ops->num_auto_selectable_formats;
  168. if (max < until)
  169. until = max;
  170. for (i = 0; i < until; i++)
  171. fmt |= ops->auto_selectable_formats[i];
  172. return fmt;
  173. }
  174. /**
  175. * snd_soc_dai_set_fmt - configure DAI hardware audio format.
  176. * @dai: DAI
  177. * @fmt: SND_SOC_DAIFMT_* format value.
  178. *
  179. * Configures the DAI hardware format and clocking.
  180. */
  181. int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  182. {
  183. int ret = -ENOTSUPP;
  184. if (dai->driver->ops && dai->driver->ops->set_fmt)
  185. ret = dai->driver->ops->set_fmt(dai, fmt);
  186. return soc_dai_ret(dai, ret);
  187. }
  188. EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
  189. /**
  190. * snd_soc_xlate_tdm_slot_mask - generate tx/rx slot mask.
  191. * @slots: Number of slots in use.
  192. * @tx_mask: bitmask representing active TX slots.
  193. * @rx_mask: bitmask representing active RX slots.
  194. *
  195. * Generates the TDM tx and rx slot default masks for DAI.
  196. */
  197. static int snd_soc_xlate_tdm_slot_mask(unsigned int slots,
  198. unsigned int *tx_mask,
  199. unsigned int *rx_mask)
  200. {
  201. if (*tx_mask || *rx_mask)
  202. return 0;
  203. if (!slots)
  204. return -EINVAL;
  205. *tx_mask = (1 << slots) - 1;
  206. *rx_mask = (1 << slots) - 1;
  207. return 0;
  208. }
  209. /**
  210. * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation
  211. * @dai: The DAI to configure
  212. * @tx_mask: bitmask representing active TX slots.
  213. * @rx_mask: bitmask representing active RX slots.
  214. * @slots: Number of slots in use.
  215. * @slot_width: Width in bits for each slot.
  216. *
  217. * This function configures the specified DAI for TDM operation. @slot contains
  218. * the total number of slots of the TDM stream and @slot_with the width of each
  219. * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the
  220. * active slots of the TDM stream for the specified DAI, i.e. which slots the
  221. * DAI should write to or read from. If a bit is set the corresponding slot is
  222. * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to
  223. * the first slot, bit 1 to the second slot and so on. The first active slot
  224. * maps to the first channel of the DAI, the second active slot to the second
  225. * channel and so on.
  226. *
  227. * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask,
  228. * @rx_mask and @slot_width will be ignored.
  229. *
  230. * Returns 0 on success, a negative error code otherwise.
  231. */
  232. int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
  233. unsigned int tx_mask, unsigned int rx_mask,
  234. int slots, int slot_width)
  235. {
  236. int ret = -ENOTSUPP;
  237. if (dai->driver->ops &&
  238. dai->driver->ops->xlate_tdm_slot_mask)
  239. dai->driver->ops->xlate_tdm_slot_mask(slots,
  240. &tx_mask, &rx_mask);
  241. else
  242. snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
  243. dai->tx_mask = tx_mask;
  244. dai->rx_mask = rx_mask;
  245. if (dai->driver->ops &&
  246. dai->driver->ops->set_tdm_slot)
  247. ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
  248. slots, slot_width);
  249. return soc_dai_ret(dai, ret);
  250. }
  251. EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
  252. /**
  253. * snd_soc_dai_set_channel_map - configure DAI audio channel map
  254. * @dai: DAI
  255. * @tx_num: how many TX channels
  256. * @tx_slot: pointer to an array which imply the TX slot number channel
  257. * 0~num-1 uses
  258. * @rx_num: how many RX channels
  259. * @rx_slot: pointer to an array which imply the RX slot number channel
  260. * 0~num-1 uses
  261. *
  262. * configure the relationship between channel number and TDM slot number.
  263. */
  264. int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
  265. unsigned int tx_num, unsigned int *tx_slot,
  266. unsigned int rx_num, unsigned int *rx_slot)
  267. {
  268. int ret = -ENOTSUPP;
  269. if (dai->driver->ops &&
  270. dai->driver->ops->set_channel_map)
  271. ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
  272. rx_num, rx_slot);
  273. return soc_dai_ret(dai, ret);
  274. }
  275. EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
  276. /**
  277. * snd_soc_dai_get_channel_map - Get DAI audio channel map
  278. * @dai: DAI
  279. * @tx_num: how many TX channels
  280. * @tx_slot: pointer to an array which imply the TX slot number channel
  281. * 0~num-1 uses
  282. * @rx_num: how many RX channels
  283. * @rx_slot: pointer to an array which imply the RX slot number channel
  284. * 0~num-1 uses
  285. */
  286. int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
  287. unsigned int *tx_num, unsigned int *tx_slot,
  288. unsigned int *rx_num, unsigned int *rx_slot)
  289. {
  290. int ret = -ENOTSUPP;
  291. if (dai->driver->ops &&
  292. dai->driver->ops->get_channel_map)
  293. ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,
  294. rx_num, rx_slot);
  295. return soc_dai_ret(dai, ret);
  296. }
  297. EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);
  298. /**
  299. * snd_soc_dai_set_tristate - configure DAI system or master clock.
  300. * @dai: DAI
  301. * @tristate: tristate enable
  302. *
  303. * Tristates the DAI so that others can use it.
  304. */
  305. int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
  306. {
  307. int ret = -EINVAL;
  308. if (dai->driver->ops &&
  309. dai->driver->ops->set_tristate)
  310. ret = dai->driver->ops->set_tristate(dai, tristate);
  311. return soc_dai_ret(dai, ret);
  312. }
  313. EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
  314. /**
  315. * snd_soc_dai_digital_mute - configure DAI system or master clock.
  316. * @dai: DAI
  317. * @mute: mute enable
  318. * @direction: stream to mute
  319. *
  320. * Mutes the DAI DAC.
  321. */
  322. int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
  323. int direction)
  324. {
  325. int ret = -ENOTSUPP;
  326. /*
  327. * ignore if direction was CAPTURE
  328. * and it had .no_capture_mute flag
  329. */
  330. if (dai->driver->ops &&
  331. dai->driver->ops->mute_stream &&
  332. (direction == SNDRV_PCM_STREAM_PLAYBACK ||
  333. !dai->driver->ops->no_capture_mute))
  334. ret = dai->driver->ops->mute_stream(dai, mute, direction);
  335. return soc_dai_ret(dai, ret);
  336. }
  337. EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
  338. int snd_soc_dai_hw_params(struct snd_soc_dai *dai,
  339. struct snd_pcm_substream *substream,
  340. struct snd_pcm_hw_params *params)
  341. {
  342. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  343. int ret = 0;
  344. if (dai->driver->ops &&
  345. dai->driver->ops->hw_params) {
  346. /* perform any topology hw_params fixups before DAI */
  347. ret = snd_soc_link_be_hw_params_fixup(rtd, params);
  348. if (ret < 0)
  349. goto end;
  350. ret = dai->driver->ops->hw_params(substream, params, dai);
  351. }
  352. /* mark substream if succeeded */
  353. if (ret == 0)
  354. soc_dai_mark_push(dai, substream, hw_params);
  355. end:
  356. return soc_dai_ret(dai, ret);
  357. }
  358. void snd_soc_dai_hw_free(struct snd_soc_dai *dai,
  359. struct snd_pcm_substream *substream,
  360. int rollback)
  361. {
  362. if (rollback && !soc_dai_mark_match(dai, substream, hw_params))
  363. return;
  364. if (dai->driver->ops &&
  365. dai->driver->ops->hw_free)
  366. dai->driver->ops->hw_free(substream, dai);
  367. /* remove marked substream */
  368. soc_dai_mark_pop(dai, substream, hw_params);
  369. }
  370. int snd_soc_dai_startup(struct snd_soc_dai *dai,
  371. struct snd_pcm_substream *substream)
  372. {
  373. int ret = 0;
  374. if (dai->driver->ops &&
  375. dai->driver->ops->startup)
  376. ret = dai->driver->ops->startup(substream, dai);
  377. /* mark substream if succeeded */
  378. if (ret == 0)
  379. soc_dai_mark_push(dai, substream, startup);
  380. return soc_dai_ret(dai, ret);
  381. }
  382. void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
  383. struct snd_pcm_substream *substream,
  384. int rollback)
  385. {
  386. if (rollback && !soc_dai_mark_match(dai, substream, startup))
  387. return;
  388. if (dai->driver->ops &&
  389. dai->driver->ops->shutdown)
  390. dai->driver->ops->shutdown(substream, dai);
  391. /* remove marked substream */
  392. soc_dai_mark_pop(dai, substream, startup);
  393. }
  394. int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
  395. struct snd_soc_pcm_runtime *rtd, int num)
  396. {
  397. int ret = -ENOTSUPP;
  398. if (dai->driver->compress_new)
  399. ret = dai->driver->compress_new(rtd, num);
  400. return soc_dai_ret(dai, ret);
  401. }
  402. /*
  403. * snd_soc_dai_stream_valid() - check if a DAI supports the given stream
  404. *
  405. * Returns true if the DAI supports the indicated stream type.
  406. */
  407. bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir)
  408. {
  409. struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir);
  410. /* If the codec specifies any channels at all, it supports the stream */
  411. return stream->channels_min;
  412. }
  413. /*
  414. * snd_soc_dai_link_set_capabilities() - set dai_link properties based on its DAIs
  415. */
  416. void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
  417. {
  418. bool supported[SNDRV_PCM_STREAM_LAST + 1];
  419. int direction;
  420. for_each_pcm_streams(direction) {
  421. struct snd_soc_dai_link_component *cpu;
  422. struct snd_soc_dai_link_component *codec;
  423. struct snd_soc_dai *dai;
  424. bool supported_cpu = false;
  425. bool supported_codec = false;
  426. int i;
  427. for_each_link_cpus(dai_link, i, cpu) {
  428. dai = snd_soc_find_dai_with_mutex(cpu);
  429. if (dai && snd_soc_dai_stream_valid(dai, direction)) {
  430. supported_cpu = true;
  431. break;
  432. }
  433. }
  434. for_each_link_codecs(dai_link, i, codec) {
  435. dai = snd_soc_find_dai_with_mutex(codec);
  436. if (dai && snd_soc_dai_stream_valid(dai, direction)) {
  437. supported_codec = true;
  438. break;
  439. }
  440. }
  441. supported[direction] = supported_cpu && supported_codec;
  442. }
  443. dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK];
  444. dai_link->dpcm_capture = supported[SNDRV_PCM_STREAM_CAPTURE];
  445. }
  446. EXPORT_SYMBOL_GPL(snd_soc_dai_link_set_capabilities);
  447. void snd_soc_dai_action(struct snd_soc_dai *dai,
  448. int stream, int action)
  449. {
  450. /* see snd_soc_dai_stream_active() */
  451. dai->stream_active[stream] += action;
  452. /* see snd_soc_component_active() */
  453. dai->component->active += action;
  454. }
  455. EXPORT_SYMBOL_GPL(snd_soc_dai_action);
  456. int snd_soc_dai_active(struct snd_soc_dai *dai)
  457. {
  458. int stream, active;
  459. active = 0;
  460. for_each_pcm_streams(stream)
  461. active += dai->stream_active[stream];
  462. return active;
  463. }
  464. EXPORT_SYMBOL_GPL(snd_soc_dai_active);
  465. int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order)
  466. {
  467. struct snd_soc_dai *dai;
  468. int i;
  469. for_each_rtd_dais(rtd, i, dai) {
  470. if (dai->driver->probe_order != order)
  471. continue;
  472. if (dai->driver->probe) {
  473. int ret = dai->driver->probe(dai);
  474. if (ret < 0)
  475. return soc_dai_ret(dai, ret);
  476. }
  477. dai->probed = 1;
  478. }
  479. return 0;
  480. }
  481. int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order)
  482. {
  483. struct snd_soc_dai *dai;
  484. int i, r, ret = 0;
  485. for_each_rtd_dais(rtd, i, dai) {
  486. if (dai->driver->remove_order != order)
  487. continue;
  488. if (dai->probed &&
  489. dai->driver->remove) {
  490. r = dai->driver->remove(dai);
  491. if (r < 0)
  492. ret = r; /* use last error */
  493. }
  494. dai->probed = 0;
  495. }
  496. return ret;
  497. }
  498. int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd)
  499. {
  500. struct snd_soc_dai *dai;
  501. int i;
  502. for_each_rtd_dais(rtd, i, dai) {
  503. if (dai->driver->pcm_new) {
  504. int ret = dai->driver->pcm_new(rtd, dai);
  505. if (ret < 0)
  506. return soc_dai_ret(dai, ret);
  507. }
  508. }
  509. return 0;
  510. }
  511. int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream)
  512. {
  513. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  514. struct snd_soc_dai *dai;
  515. int i, ret;
  516. for_each_rtd_dais(rtd, i, dai) {
  517. if (dai->driver->ops &&
  518. dai->driver->ops->prepare) {
  519. ret = dai->driver->ops->prepare(substream, dai);
  520. if (ret < 0)
  521. return soc_dai_ret(dai, ret);
  522. }
  523. }
  524. return 0;
  525. }
  526. static int soc_dai_trigger(struct snd_soc_dai *dai,
  527. struct snd_pcm_substream *substream, int cmd)
  528. {
  529. int ret = 0;
  530. if (dai->driver->ops &&
  531. dai->driver->ops->trigger)
  532. ret = dai->driver->ops->trigger(substream, cmd, dai);
  533. return soc_dai_ret(dai, ret);
  534. }
  535. int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream,
  536. int cmd, int rollback)
  537. {
  538. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  539. struct snd_soc_dai *dai;
  540. int i, r, ret = 0;
  541. switch (cmd) {
  542. case SNDRV_PCM_TRIGGER_START:
  543. case SNDRV_PCM_TRIGGER_RESUME:
  544. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  545. for_each_rtd_dais(rtd, i, dai) {
  546. ret = soc_dai_trigger(dai, substream, cmd);
  547. if (ret < 0)
  548. break;
  549. soc_dai_mark_push(dai, substream, trigger);
  550. }
  551. break;
  552. case SNDRV_PCM_TRIGGER_STOP:
  553. case SNDRV_PCM_TRIGGER_SUSPEND:
  554. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  555. for_each_rtd_dais(rtd, i, dai) {
  556. if (rollback && !soc_dai_mark_match(dai, substream, trigger))
  557. continue;
  558. r = soc_dai_trigger(dai, substream, cmd);
  559. if (r < 0)
  560. ret = r; /* use last ret */
  561. soc_dai_mark_pop(dai, substream, trigger);
  562. }
  563. }
  564. return ret;
  565. }
  566. int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
  567. int cmd)
  568. {
  569. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  570. struct snd_soc_dai *dai;
  571. int i, ret;
  572. for_each_rtd_dais(rtd, i, dai) {
  573. if (dai->driver->ops &&
  574. dai->driver->ops->bespoke_trigger) {
  575. ret = dai->driver->ops->bespoke_trigger(substream,
  576. cmd, dai);
  577. if (ret < 0)
  578. return soc_dai_ret(dai, ret);
  579. }
  580. }
  581. return 0;
  582. }
  583. void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
  584. snd_pcm_sframes_t *cpu_delay,
  585. snd_pcm_sframes_t *codec_delay)
  586. {
  587. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  588. struct snd_soc_dai *dai;
  589. int i;
  590. /*
  591. * We're looking for the delay through the full audio path so it needs to
  592. * be the maximum of the DAIs doing transmit and the maximum of the DAIs
  593. * doing receive (ie, all CPUs and all CODECs) rather than just the maximum
  594. * of all DAIs.
  595. */
  596. /* for CPU */
  597. for_each_rtd_cpu_dais(rtd, i, dai)
  598. if (dai->driver->ops &&
  599. dai->driver->ops->delay)
  600. *cpu_delay = max(*cpu_delay, dai->driver->ops->delay(substream, dai));
  601. /* for Codec */
  602. for_each_rtd_codec_dais(rtd, i, dai)
  603. if (dai->driver->ops &&
  604. dai->driver->ops->delay)
  605. *codec_delay = max(*codec_delay, dai->driver->ops->delay(substream, dai));
  606. }
  607. int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,
  608. struct snd_compr_stream *cstream)
  609. {
  610. int ret = 0;
  611. if (dai->driver->cops &&
  612. dai->driver->cops->startup)
  613. ret = dai->driver->cops->startup(cstream, dai);
  614. /* mark cstream if succeeded */
  615. if (ret == 0)
  616. soc_dai_mark_push(dai, cstream, compr_startup);
  617. return soc_dai_ret(dai, ret);
  618. }
  619. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup);
  620. void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai,
  621. struct snd_compr_stream *cstream,
  622. int rollback)
  623. {
  624. if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup))
  625. return;
  626. if (dai->driver->cops &&
  627. dai->driver->cops->shutdown)
  628. dai->driver->cops->shutdown(cstream, dai);
  629. /* remove marked cstream */
  630. soc_dai_mark_pop(dai, cstream, compr_startup);
  631. }
  632. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown);
  633. int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai,
  634. struct snd_compr_stream *cstream, int cmd)
  635. {
  636. int ret = 0;
  637. if (dai->driver->cops &&
  638. dai->driver->cops->trigger)
  639. ret = dai->driver->cops->trigger(cstream, cmd, dai);
  640. return soc_dai_ret(dai, ret);
  641. }
  642. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger);
  643. int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai,
  644. struct snd_compr_stream *cstream,
  645. struct snd_compr_params *params)
  646. {
  647. int ret = 0;
  648. if (dai->driver->cops &&
  649. dai->driver->cops->set_params)
  650. ret = dai->driver->cops->set_params(cstream, params, dai);
  651. return soc_dai_ret(dai, ret);
  652. }
  653. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params);
  654. int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai,
  655. struct snd_compr_stream *cstream,
  656. struct snd_codec *params)
  657. {
  658. int ret = 0;
  659. if (dai->driver->cops &&
  660. dai->driver->cops->get_params)
  661. ret = dai->driver->cops->get_params(cstream, params, dai);
  662. return soc_dai_ret(dai, ret);
  663. }
  664. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params);
  665. int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,
  666. struct snd_compr_stream *cstream,
  667. size_t bytes)
  668. {
  669. int ret = 0;
  670. if (dai->driver->cops &&
  671. dai->driver->cops->ack)
  672. ret = dai->driver->cops->ack(cstream, bytes, dai);
  673. return soc_dai_ret(dai, ret);
  674. }
  675. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack);
  676. int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
  677. struct snd_compr_stream *cstream,
  678. struct snd_compr_tstamp *tstamp)
  679. {
  680. int ret = 0;
  681. if (dai->driver->cops &&
  682. dai->driver->cops->pointer)
  683. ret = dai->driver->cops->pointer(cstream, tstamp, dai);
  684. return soc_dai_ret(dai, ret);
  685. }
  686. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer);
  687. int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,
  688. struct snd_compr_stream *cstream,
  689. struct snd_compr_metadata *metadata)
  690. {
  691. int ret = 0;
  692. if (dai->driver->cops &&
  693. dai->driver->cops->set_metadata)
  694. ret = dai->driver->cops->set_metadata(cstream, metadata, dai);
  695. return soc_dai_ret(dai, ret);
  696. }
  697. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata);
  698. int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,
  699. struct snd_compr_stream *cstream,
  700. struct snd_compr_metadata *metadata)
  701. {
  702. int ret = 0;
  703. if (dai->driver->cops &&
  704. dai->driver->cops->get_metadata)
  705. ret = dai->driver->cops->get_metadata(cstream, metadata, dai);
  706. return soc_dai_ret(dai, ret);
  707. }
  708. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata);