soc-dai.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // soc-dai.c
  4. //
  5. // Copyright (C) 2019 Renesas Electronics Corp.
  6. // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
  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(const 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 (SND_SOC_CLOCK_IN or SND_SOC_CLOCK_OUT)
  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(const 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(const 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. int stream;
  238. unsigned int *tdm_mask[] = {
  239. &tx_mask,
  240. &rx_mask,
  241. };
  242. if (slots) {
  243. if (dai->driver->ops &&
  244. dai->driver->ops->xlate_tdm_slot_mask)
  245. ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
  246. else
  247. ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
  248. if (ret)
  249. goto err;
  250. }
  251. for_each_pcm_streams(stream)
  252. snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]);
  253. if (dai->driver->ops &&
  254. dai->driver->ops->set_tdm_slot)
  255. ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
  256. slots, slot_width);
  257. err:
  258. return soc_dai_ret(dai, ret);
  259. }
  260. EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
  261. /**
  262. * snd_soc_dai_set_channel_map - configure DAI audio channel map
  263. * @dai: DAI
  264. * @tx_num: how many TX channels
  265. * @tx_slot: pointer to an array which imply the TX slot number channel
  266. * 0~num-1 uses
  267. * @rx_num: how many RX channels
  268. * @rx_slot: pointer to an array which imply the RX slot number channel
  269. * 0~num-1 uses
  270. *
  271. * configure the relationship between channel number and TDM slot number.
  272. */
  273. int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
  274. unsigned int tx_num, const unsigned int *tx_slot,
  275. unsigned int rx_num, const unsigned int *rx_slot)
  276. {
  277. int ret = -ENOTSUPP;
  278. if (dai->driver->ops &&
  279. dai->driver->ops->set_channel_map)
  280. ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
  281. rx_num, rx_slot);
  282. return soc_dai_ret(dai, ret);
  283. }
  284. EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
  285. /**
  286. * snd_soc_dai_get_channel_map - Get DAI audio channel map
  287. * @dai: DAI
  288. * @tx_num: how many TX channels
  289. * @tx_slot: pointer to an array which imply the TX slot number channel
  290. * 0~num-1 uses
  291. * @rx_num: how many RX channels
  292. * @rx_slot: pointer to an array which imply the RX slot number channel
  293. * 0~num-1 uses
  294. */
  295. int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai,
  296. unsigned int *tx_num, unsigned int *tx_slot,
  297. unsigned int *rx_num, unsigned int *rx_slot)
  298. {
  299. int ret = -ENOTSUPP;
  300. if (dai->driver->ops &&
  301. dai->driver->ops->get_channel_map)
  302. ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,
  303. rx_num, rx_slot);
  304. return soc_dai_ret(dai, ret);
  305. }
  306. EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);
  307. /**
  308. * snd_soc_dai_set_tristate - configure DAI system or master clock.
  309. * @dai: DAI
  310. * @tristate: tristate enable
  311. *
  312. * Tristates the DAI so that others can use it.
  313. */
  314. int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
  315. {
  316. int ret = -EINVAL;
  317. if (dai->driver->ops &&
  318. dai->driver->ops->set_tristate)
  319. ret = dai->driver->ops->set_tristate(dai, tristate);
  320. return soc_dai_ret(dai, ret);
  321. }
  322. EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
  323. /**
  324. * snd_soc_dai_digital_mute - configure DAI system or master clock.
  325. * @dai: DAI
  326. * @mute: mute enable
  327. * @direction: stream to mute
  328. *
  329. * Mutes the DAI DAC.
  330. */
  331. int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
  332. int direction)
  333. {
  334. int ret = -ENOTSUPP;
  335. /*
  336. * ignore if direction was CAPTURE
  337. * and it had .no_capture_mute flag
  338. */
  339. if (dai->driver->ops &&
  340. dai->driver->ops->mute_stream &&
  341. (direction == SNDRV_PCM_STREAM_PLAYBACK ||
  342. !dai->driver->ops->no_capture_mute))
  343. ret = dai->driver->ops->mute_stream(dai, mute, direction);
  344. return soc_dai_ret(dai, ret);
  345. }
  346. EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
  347. int snd_soc_dai_hw_params(struct snd_soc_dai *dai,
  348. struct snd_pcm_substream *substream,
  349. struct snd_pcm_hw_params *params)
  350. {
  351. int ret = 0;
  352. if (dai->driver->ops &&
  353. dai->driver->ops->hw_params)
  354. ret = dai->driver->ops->hw_params(substream, params, dai);
  355. /* mark substream if succeeded */
  356. if (ret == 0)
  357. soc_dai_mark_push(dai, substream, hw_params);
  358. return soc_dai_ret(dai, ret);
  359. }
  360. void snd_soc_dai_hw_free(struct snd_soc_dai *dai,
  361. struct snd_pcm_substream *substream,
  362. int rollback)
  363. {
  364. if (rollback && !soc_dai_mark_match(dai, substream, hw_params))
  365. return;
  366. if (dai->driver->ops &&
  367. dai->driver->ops->hw_free)
  368. dai->driver->ops->hw_free(substream, dai);
  369. /* remove marked substream */
  370. soc_dai_mark_pop(dai, substream, hw_params);
  371. }
  372. int snd_soc_dai_startup(struct snd_soc_dai *dai,
  373. struct snd_pcm_substream *substream)
  374. {
  375. int ret = 0;
  376. if (!snd_soc_dai_stream_valid(dai, substream->stream))
  377. return 0;
  378. if (dai->driver->ops &&
  379. dai->driver->ops->startup)
  380. ret = dai->driver->ops->startup(substream, dai);
  381. /* mark substream if succeeded */
  382. if (ret == 0)
  383. soc_dai_mark_push(dai, substream, startup);
  384. return soc_dai_ret(dai, ret);
  385. }
  386. void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
  387. struct snd_pcm_substream *substream,
  388. int rollback)
  389. {
  390. if (!snd_soc_dai_stream_valid(dai, substream->stream))
  391. return;
  392. if (rollback && !soc_dai_mark_match(dai, substream, startup))
  393. return;
  394. if (dai->driver->ops &&
  395. dai->driver->ops->shutdown)
  396. dai->driver->ops->shutdown(substream, dai);
  397. /* remove marked substream */
  398. soc_dai_mark_pop(dai, substream, startup);
  399. }
  400. int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
  401. struct snd_soc_pcm_runtime *rtd, int num)
  402. {
  403. int ret = -ENOTSUPP;
  404. if (dai->driver->ops &&
  405. dai->driver->ops->compress_new)
  406. ret = dai->driver->ops->compress_new(rtd, num);
  407. return soc_dai_ret(dai, ret);
  408. }
  409. /*
  410. * snd_soc_dai_stream_valid() - check if a DAI supports the given stream
  411. *
  412. * Returns true if the DAI supports the indicated stream type.
  413. */
  414. bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int dir)
  415. {
  416. const struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir);
  417. /* If the codec specifies any channels at all, it supports the stream */
  418. return stream->channels_min;
  419. }
  420. void snd_soc_dai_action(struct snd_soc_dai *dai,
  421. int stream, int action)
  422. {
  423. /* see snd_soc_dai_stream_active() */
  424. dai->stream[stream].active += action;
  425. /* see snd_soc_component_active() */
  426. dai->component->active += action;
  427. }
  428. EXPORT_SYMBOL_GPL(snd_soc_dai_action);
  429. int snd_soc_dai_active(const struct snd_soc_dai *dai)
  430. {
  431. int stream, active;
  432. active = 0;
  433. for_each_pcm_streams(stream)
  434. active += dai->stream[stream].active;
  435. return active;
  436. }
  437. EXPORT_SYMBOL_GPL(snd_soc_dai_active);
  438. int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order)
  439. {
  440. struct snd_soc_dai *dai;
  441. int i;
  442. for_each_rtd_dais(rtd, i, dai) {
  443. if (dai->probed)
  444. continue;
  445. if (dai->driver->ops) {
  446. if (dai->driver->ops->probe_order != order)
  447. continue;
  448. if (dai->driver->ops->probe) {
  449. int ret = dai->driver->ops->probe(dai);
  450. if (ret < 0)
  451. return soc_dai_ret(dai, ret);
  452. }
  453. }
  454. dai->probed = 1;
  455. }
  456. return 0;
  457. }
  458. int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order)
  459. {
  460. struct snd_soc_dai *dai;
  461. int i, r, ret = 0;
  462. for_each_rtd_dais(rtd, i, dai) {
  463. if (!dai->probed)
  464. continue;
  465. if (dai->driver->ops) {
  466. if (dai->driver->ops->remove_order != order)
  467. continue;
  468. if (dai->driver->ops->remove) {
  469. r = dai->driver->ops->remove(dai);
  470. if (r < 0)
  471. ret = r; /* use last error */
  472. }
  473. }
  474. dai->probed = 0;
  475. }
  476. return ret;
  477. }
  478. int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd)
  479. {
  480. struct snd_soc_dai *dai;
  481. int i;
  482. for_each_rtd_dais(rtd, i, dai) {
  483. if (dai->driver->ops &&
  484. dai->driver->ops->pcm_new) {
  485. int ret = dai->driver->ops->pcm_new(rtd, dai);
  486. if (ret < 0)
  487. return soc_dai_ret(dai, ret);
  488. }
  489. }
  490. return 0;
  491. }
  492. int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream)
  493. {
  494. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  495. struct snd_soc_dai *dai;
  496. int i, ret;
  497. for_each_rtd_dais(rtd, i, dai) {
  498. if (!snd_soc_dai_stream_valid(dai, substream->stream))
  499. continue;
  500. if (dai->driver->ops &&
  501. dai->driver->ops->prepare) {
  502. ret = dai->driver->ops->prepare(substream, dai);
  503. if (ret < 0)
  504. return soc_dai_ret(dai, ret);
  505. }
  506. }
  507. return 0;
  508. }
  509. static int soc_dai_trigger(struct snd_soc_dai *dai,
  510. struct snd_pcm_substream *substream, int cmd)
  511. {
  512. int ret = 0;
  513. if (!snd_soc_dai_stream_valid(dai, substream->stream))
  514. return 0;
  515. if (dai->driver->ops &&
  516. dai->driver->ops->trigger)
  517. ret = dai->driver->ops->trigger(substream, cmd, dai);
  518. return soc_dai_ret(dai, ret);
  519. }
  520. int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream,
  521. int cmd, int rollback)
  522. {
  523. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  524. struct snd_soc_dai *dai;
  525. int i, r, ret = 0;
  526. switch (cmd) {
  527. case SNDRV_PCM_TRIGGER_START:
  528. case SNDRV_PCM_TRIGGER_RESUME:
  529. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  530. for_each_rtd_dais(rtd, i, dai) {
  531. ret = soc_dai_trigger(dai, substream, cmd);
  532. if (ret < 0)
  533. break;
  534. if (dai->driver->ops && dai->driver->ops->mute_unmute_on_trigger)
  535. snd_soc_dai_digital_mute(dai, 0, substream->stream);
  536. soc_dai_mark_push(dai, substream, trigger);
  537. }
  538. break;
  539. case SNDRV_PCM_TRIGGER_STOP:
  540. case SNDRV_PCM_TRIGGER_SUSPEND:
  541. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  542. for_each_rtd_dais(rtd, i, dai) {
  543. if (rollback && !soc_dai_mark_match(dai, substream, trigger))
  544. continue;
  545. if (dai->driver->ops && dai->driver->ops->mute_unmute_on_trigger)
  546. snd_soc_dai_digital_mute(dai, 1, substream->stream);
  547. r = soc_dai_trigger(dai, substream, cmd);
  548. if (r < 0)
  549. ret = r; /* use last ret */
  550. soc_dai_mark_pop(dai, substream, trigger);
  551. }
  552. }
  553. return ret;
  554. }
  555. void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
  556. snd_pcm_sframes_t *cpu_delay,
  557. snd_pcm_sframes_t *codec_delay)
  558. {
  559. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  560. struct snd_soc_dai *dai;
  561. int i;
  562. /*
  563. * We're looking for the delay through the full audio path so it needs to
  564. * be the maximum of the DAIs doing transmit and the maximum of the DAIs
  565. * doing receive (ie, all CPUs and all CODECs) rather than just the maximum
  566. * of all DAIs.
  567. */
  568. /* for CPU */
  569. for_each_rtd_cpu_dais(rtd, i, dai)
  570. if (dai->driver->ops &&
  571. dai->driver->ops->delay)
  572. *cpu_delay = max(*cpu_delay, dai->driver->ops->delay(substream, dai));
  573. /* for Codec */
  574. for_each_rtd_codec_dais(rtd, i, dai)
  575. if (dai->driver->ops &&
  576. dai->driver->ops->delay)
  577. *codec_delay = max(*codec_delay, dai->driver->ops->delay(substream, dai));
  578. }
  579. int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,
  580. struct snd_compr_stream *cstream)
  581. {
  582. int ret = 0;
  583. if (dai->driver->cops &&
  584. dai->driver->cops->startup)
  585. ret = dai->driver->cops->startup(cstream, dai);
  586. /* mark cstream if succeeded */
  587. if (ret == 0)
  588. soc_dai_mark_push(dai, cstream, compr_startup);
  589. return soc_dai_ret(dai, ret);
  590. }
  591. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup);
  592. void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai,
  593. struct snd_compr_stream *cstream,
  594. int rollback)
  595. {
  596. if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup))
  597. return;
  598. if (dai->driver->cops &&
  599. dai->driver->cops->shutdown)
  600. dai->driver->cops->shutdown(cstream, dai);
  601. /* remove marked cstream */
  602. soc_dai_mark_pop(dai, cstream, compr_startup);
  603. }
  604. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown);
  605. int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai,
  606. struct snd_compr_stream *cstream, int cmd)
  607. {
  608. int ret = 0;
  609. if (dai->driver->cops &&
  610. dai->driver->cops->trigger)
  611. ret = dai->driver->cops->trigger(cstream, cmd, dai);
  612. return soc_dai_ret(dai, ret);
  613. }
  614. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger);
  615. int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai,
  616. struct snd_compr_stream *cstream,
  617. struct snd_compr_params *params)
  618. {
  619. int ret = 0;
  620. if (dai->driver->cops &&
  621. dai->driver->cops->set_params)
  622. ret = dai->driver->cops->set_params(cstream, params, dai);
  623. return soc_dai_ret(dai, ret);
  624. }
  625. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params);
  626. int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai,
  627. struct snd_compr_stream *cstream,
  628. struct snd_codec *params)
  629. {
  630. int ret = 0;
  631. if (dai->driver->cops &&
  632. dai->driver->cops->get_params)
  633. ret = dai->driver->cops->get_params(cstream, params, dai);
  634. return soc_dai_ret(dai, ret);
  635. }
  636. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params);
  637. int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,
  638. struct snd_compr_stream *cstream,
  639. size_t bytes)
  640. {
  641. int ret = 0;
  642. if (dai->driver->cops &&
  643. dai->driver->cops->ack)
  644. ret = dai->driver->cops->ack(cstream, bytes, dai);
  645. return soc_dai_ret(dai, ret);
  646. }
  647. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack);
  648. int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
  649. struct snd_compr_stream *cstream,
  650. struct snd_compr_tstamp *tstamp)
  651. {
  652. int ret = 0;
  653. if (dai->driver->cops &&
  654. dai->driver->cops->pointer)
  655. ret = dai->driver->cops->pointer(cstream, tstamp, dai);
  656. return soc_dai_ret(dai, ret);
  657. }
  658. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer);
  659. int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,
  660. struct snd_compr_stream *cstream,
  661. struct snd_compr_metadata *metadata)
  662. {
  663. int ret = 0;
  664. if (dai->driver->cops &&
  665. dai->driver->cops->set_metadata)
  666. ret = dai->driver->cops->set_metadata(cstream, metadata, dai);
  667. return soc_dai_ret(dai, ret);
  668. }
  669. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata);
  670. int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,
  671. struct snd_compr_stream *cstream,
  672. struct snd_compr_metadata *metadata)
  673. {
  674. int ret = 0;
  675. if (dai->driver->cops &&
  676. dai->driver->cops->get_metadata)
  677. ret = dai->driver->cops->get_metadata(cstream, metadata, dai);
  678. return soc_dai_ret(dai, ret);
  679. }
  680. EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata);