soc-link.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // soc-link.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-link.h>
  10. #define soc_link_ret(rtd, ret) _soc_link_ret(rtd, __func__, ret)
  11. static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd,
  12. const char *func, int ret)
  13. {
  14. /* Positive, Zero values are not errors */
  15. if (ret >= 0)
  16. return ret;
  17. /* Negative values might be errors */
  18. switch (ret) {
  19. case -EPROBE_DEFER:
  20. case -ENOTSUPP:
  21. break;
  22. default:
  23. dev_err(rtd->dev,
  24. "ASoC: error at %s on %s: %d\n",
  25. func, rtd->dai_link->name, ret);
  26. }
  27. return ret;
  28. }
  29. /*
  30. * We might want to check substream by using list.
  31. * In such case, we can update these macros.
  32. */
  33. #define soc_link_mark_push(rtd, substream, tgt) ((rtd)->mark_##tgt = substream)
  34. #define soc_link_mark_pop(rtd, substream, tgt) ((rtd)->mark_##tgt = NULL)
  35. #define soc_link_mark_match(rtd, substream, tgt) ((rtd)->mark_##tgt == substream)
  36. int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd)
  37. {
  38. int ret = 0;
  39. if (rtd->dai_link->init)
  40. ret = rtd->dai_link->init(rtd);
  41. return soc_link_ret(rtd, ret);
  42. }
  43. void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd)
  44. {
  45. if (rtd->dai_link->exit)
  46. rtd->dai_link->exit(rtd);
  47. }
  48. int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  49. struct snd_pcm_hw_params *params)
  50. {
  51. int ret = 0;
  52. if (rtd->dai_link->be_hw_params_fixup)
  53. ret = rtd->dai_link->be_hw_params_fixup(rtd, params);
  54. return soc_link_ret(rtd, ret);
  55. }
  56. int snd_soc_link_startup(struct snd_pcm_substream *substream)
  57. {
  58. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  59. int ret = 0;
  60. if (rtd->dai_link->ops &&
  61. rtd->dai_link->ops->startup)
  62. ret = rtd->dai_link->ops->startup(substream);
  63. /* mark substream if succeeded */
  64. if (ret == 0)
  65. soc_link_mark_push(rtd, substream, startup);
  66. return soc_link_ret(rtd, ret);
  67. }
  68. void snd_soc_link_shutdown(struct snd_pcm_substream *substream,
  69. int rollback)
  70. {
  71. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  72. if (rollback && !soc_link_mark_match(rtd, substream, startup))
  73. return;
  74. if (rtd->dai_link->ops &&
  75. rtd->dai_link->ops->shutdown)
  76. rtd->dai_link->ops->shutdown(substream);
  77. /* remove marked substream */
  78. soc_link_mark_pop(rtd, substream, startup);
  79. }
  80. int snd_soc_link_prepare(struct snd_pcm_substream *substream)
  81. {
  82. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  83. int ret = 0;
  84. if (rtd->dai_link->ops &&
  85. rtd->dai_link->ops->prepare)
  86. ret = rtd->dai_link->ops->prepare(substream);
  87. return soc_link_ret(rtd, ret);
  88. }
  89. int snd_soc_link_hw_params(struct snd_pcm_substream *substream,
  90. struct snd_pcm_hw_params *params)
  91. {
  92. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  93. int ret = 0;
  94. if (rtd->dai_link->ops &&
  95. rtd->dai_link->ops->hw_params)
  96. ret = rtd->dai_link->ops->hw_params(substream, params);
  97. return soc_link_ret(rtd, ret);
  98. }
  99. void snd_soc_link_hw_free(struct snd_pcm_substream *substream)
  100. {
  101. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  102. if (rtd->dai_link->ops &&
  103. rtd->dai_link->ops->hw_free)
  104. rtd->dai_link->ops->hw_free(substream);
  105. }
  106. int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd)
  107. {
  108. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  109. int ret = 0;
  110. if (rtd->dai_link->ops &&
  111. rtd->dai_link->ops->trigger)
  112. ret = rtd->dai_link->ops->trigger(substream, cmd);
  113. return soc_link_ret(rtd, ret);
  114. }
  115. int snd_soc_link_compr_startup(struct snd_compr_stream *cstream)
  116. {
  117. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  118. int ret = 0;
  119. if (rtd->dai_link->compr_ops &&
  120. rtd->dai_link->compr_ops->startup)
  121. ret = rtd->dai_link->compr_ops->startup(cstream);
  122. return soc_link_ret(rtd, ret);
  123. }
  124. EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup);
  125. void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream)
  126. {
  127. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  128. if (rtd->dai_link->compr_ops &&
  129. rtd->dai_link->compr_ops->shutdown)
  130. rtd->dai_link->compr_ops->shutdown(cstream);
  131. }
  132. EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown);
  133. int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream)
  134. {
  135. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  136. int ret = 0;
  137. if (rtd->dai_link->compr_ops &&
  138. rtd->dai_link->compr_ops->set_params)
  139. ret = rtd->dai_link->compr_ops->set_params(cstream);
  140. return soc_link_ret(rtd, ret);
  141. }
  142. EXPORT_SYMBOL_GPL(snd_soc_link_compr_set_params);