soc-dpcm.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /* SPDX-License-Identifier: GPL-2.0
  2. *
  3. * linux/sound/soc-dpcm.h -- ALSA SoC Dynamic PCM Support
  4. *
  5. * Author: Liam Girdwood <lrg@ti.com>
  6. */
  7. #ifndef __LINUX_SND_SOC_DPCM_H
  8. #define __LINUX_SND_SOC_DPCM_H
  9. #include <linux/slab.h>
  10. #include <linux/list.h>
  11. #include <sound/pcm.h>
  12. struct snd_soc_pcm_runtime;
  13. /*
  14. * Types of runtime_update to perform. e.g. originated from FE PCM ops
  15. * or audio route changes triggered by muxes/mixers.
  16. */
  17. enum snd_soc_dpcm_update {
  18. SND_SOC_DPCM_UPDATE_NO = 0,
  19. SND_SOC_DPCM_UPDATE_BE,
  20. SND_SOC_DPCM_UPDATE_FE,
  21. };
  22. /*
  23. * Dynamic PCM Frontend -> Backend link management states.
  24. */
  25. enum snd_soc_dpcm_link_state {
  26. SND_SOC_DPCM_LINK_STATE_NEW = 0, /* newly created link */
  27. SND_SOC_DPCM_LINK_STATE_FREE, /* link to be dismantled */
  28. };
  29. /*
  30. * Dynamic PCM Frontend -> Backend link PCM states.
  31. */
  32. enum snd_soc_dpcm_state {
  33. SND_SOC_DPCM_STATE_NEW = 0,
  34. SND_SOC_DPCM_STATE_OPEN,
  35. SND_SOC_DPCM_STATE_HW_PARAMS,
  36. SND_SOC_DPCM_STATE_PREPARE,
  37. SND_SOC_DPCM_STATE_START,
  38. SND_SOC_DPCM_STATE_STOP,
  39. SND_SOC_DPCM_STATE_PAUSED,
  40. SND_SOC_DPCM_STATE_SUSPEND,
  41. SND_SOC_DPCM_STATE_HW_FREE,
  42. SND_SOC_DPCM_STATE_CLOSE,
  43. };
  44. /*
  45. * Dynamic PCM trigger ordering. Triggering flexibility is required as some
  46. * DSPs require triggering before/after their CPU platform and DAIs.
  47. *
  48. * i.e. some clients may want to manually order this call in their PCM
  49. * trigger() whilst others will just use the regular core ordering.
  50. */
  51. enum snd_soc_dpcm_trigger {
  52. SND_SOC_DPCM_TRIGGER_PRE = 0,
  53. SND_SOC_DPCM_TRIGGER_POST,
  54. };
  55. /*
  56. * Dynamic PCM link
  57. * This links together a FE and BE DAI at runtime and stores the link
  58. * state information and the hw_params configuration.
  59. */
  60. struct snd_soc_dpcm {
  61. /* FE and BE DAIs*/
  62. struct snd_soc_pcm_runtime *be;
  63. struct snd_soc_pcm_runtime *fe;
  64. /* link state */
  65. enum snd_soc_dpcm_link_state state;
  66. /* list of BE and FE for this DPCM link */
  67. struct list_head list_be;
  68. struct list_head list_fe;
  69. #ifdef CONFIG_DEBUG_FS
  70. struct dentry *debugfs_state;
  71. #endif
  72. };
  73. /*
  74. * Dynamic PCM runtime data.
  75. */
  76. struct snd_soc_dpcm_runtime {
  77. struct list_head be_clients;
  78. struct list_head fe_clients;
  79. int users;
  80. struct snd_pcm_hw_params hw_params;
  81. /* state and update */
  82. enum snd_soc_dpcm_update runtime_update;
  83. enum snd_soc_dpcm_state state;
  84. int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */
  85. int be_start; /* refcount protected by BE stream pcm lock */
  86. int be_pause; /* refcount protected by BE stream pcm lock */
  87. bool fe_pause; /* used to track STOP after PAUSE */
  88. };
  89. #define for_each_dpcm_fe(be, stream, _dpcm) \
  90. list_for_each_entry(_dpcm, &(be)->dpcm[stream].fe_clients, list_fe)
  91. #define for_each_dpcm_be(fe, stream, _dpcm) \
  92. list_for_each_entry(_dpcm, &(fe)->dpcm[stream].be_clients, list_be)
  93. #define for_each_dpcm_be_safe(fe, stream, _dpcm, __dpcm) \
  94. list_for_each_entry_safe(_dpcm, __dpcm, &(fe)->dpcm[stream].be_clients, list_be)
  95. #define for_each_dpcm_be_rollback(fe, stream, _dpcm) \
  96. list_for_each_entry_continue_reverse(_dpcm, &(fe)->dpcm[stream].be_clients, list_be)
  97. /* get the substream for this BE */
  98. struct snd_pcm_substream *
  99. snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream);
  100. /* update audio routing between PCMs and any DAI links */
  101. int snd_soc_dpcm_runtime_update(struct snd_soc_card *card);
  102. #ifdef CONFIG_DEBUG_FS
  103. void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
  104. #else
  105. static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
  106. {
  107. }
  108. #endif
  109. int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
  110. int stream, struct snd_soc_dapm_widget_list **list_);
  111. void dpcm_path_put(struct snd_soc_dapm_widget_list **list);
  112. int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
  113. struct snd_soc_dapm_widget_list **list_);
  114. int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream);
  115. void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream,
  116. int do_hw_free, struct snd_soc_dpcm *last);
  117. void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream);
  118. void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream);
  119. void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream);
  120. int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream);
  121. int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd);
  122. int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream);
  123. void dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event);
  124. bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, enum snd_soc_dapm_direction dir);
  125. int widget_in_list(struct snd_soc_dapm_widget_list *list,
  126. struct snd_soc_dapm_widget *widget);
  127. #define dpcm_be_dai_startup_rollback(fe, stream, last) \
  128. dpcm_be_dai_stop(fe, stream, 0, last)
  129. #define dpcm_be_dai_startup_unwind(fe, stream) dpcm_be_dai_stop(fe, stream, 0, NULL)
  130. #define dpcm_be_dai_shutdown(fe, stream) dpcm_be_dai_stop(fe, stream, 1, NULL)
  131. #endif