sdw.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (c) 2018, Linaro Limited.
  3. // Copyright (c) 2018, The Linux Foundation. All rights reserved.
  4. #include <linux/module.h>
  5. #include <sound/soc.h>
  6. #include "qdsp6/q6afe.h"
  7. #include "sdw.h"
  8. int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
  9. struct sdw_stream_runtime *sruntime,
  10. bool *stream_prepared)
  11. {
  12. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  13. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  14. int ret;
  15. if (!sruntime)
  16. return 0;
  17. switch (cpu_dai->id) {
  18. case WSA_CODEC_DMA_RX_0:
  19. case WSA_CODEC_DMA_RX_1:
  20. case RX_CODEC_DMA_RX_0:
  21. case RX_CODEC_DMA_RX_1:
  22. case TX_CODEC_DMA_TX_0:
  23. case TX_CODEC_DMA_TX_1:
  24. case TX_CODEC_DMA_TX_2:
  25. case TX_CODEC_DMA_TX_3:
  26. break;
  27. default:
  28. return 0;
  29. }
  30. if (*stream_prepared) {
  31. sdw_disable_stream(sruntime);
  32. sdw_deprepare_stream(sruntime);
  33. *stream_prepared = false;
  34. }
  35. ret = sdw_prepare_stream(sruntime);
  36. if (ret)
  37. return ret;
  38. /**
  39. * NOTE: there is a strict hw requirement about the ordering of port
  40. * enables and actual WSA881x PA enable. PA enable should only happen
  41. * after soundwire ports are enabled if not DC on the line is
  42. * accumulated resulting in Click/Pop Noise
  43. * PA enable/mute are handled as part of codec DAPM and digital mute.
  44. */
  45. ret = sdw_enable_stream(sruntime);
  46. if (ret) {
  47. sdw_deprepare_stream(sruntime);
  48. return ret;
  49. }
  50. *stream_prepared = true;
  51. return ret;
  52. }
  53. EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
  54. int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
  55. struct snd_pcm_hw_params *params,
  56. struct sdw_stream_runtime **psruntime)
  57. {
  58. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  59. struct snd_soc_dai *codec_dai;
  60. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  61. struct sdw_stream_runtime *sruntime;
  62. int i;
  63. switch (cpu_dai->id) {
  64. case WSA_CODEC_DMA_RX_0:
  65. case RX_CODEC_DMA_RX_0:
  66. case RX_CODEC_DMA_RX_1:
  67. case TX_CODEC_DMA_TX_0:
  68. case TX_CODEC_DMA_TX_1:
  69. case TX_CODEC_DMA_TX_2:
  70. case TX_CODEC_DMA_TX_3:
  71. for_each_rtd_codec_dais(rtd, i, codec_dai) {
  72. sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
  73. if (sruntime != ERR_PTR(-ENOTSUPP))
  74. *psruntime = sruntime;
  75. }
  76. break;
  77. }
  78. return 0;
  79. }
  80. EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params);
  81. int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
  82. struct sdw_stream_runtime *sruntime, bool *stream_prepared)
  83. {
  84. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  85. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  86. switch (cpu_dai->id) {
  87. case WSA_CODEC_DMA_RX_0:
  88. case WSA_CODEC_DMA_RX_1:
  89. case RX_CODEC_DMA_RX_0:
  90. case RX_CODEC_DMA_RX_1:
  91. case TX_CODEC_DMA_TX_0:
  92. case TX_CODEC_DMA_TX_1:
  93. case TX_CODEC_DMA_TX_2:
  94. case TX_CODEC_DMA_TX_3:
  95. if (sruntime && *stream_prepared) {
  96. sdw_disable_stream(sruntime);
  97. sdw_deprepare_stream(sruntime);
  98. *stream_prepared = false;
  99. }
  100. break;
  101. default:
  102. break;
  103. }
  104. return 0;
  105. }
  106. EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
  107. MODULE_LICENSE("GPL v2");