mtk-dsp-sof-common.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * mtk-dsp-sof-common.c -- MediaTek dsp sof common ctrl
  4. *
  5. * Copyright (c) 2022 MediaTek Inc.
  6. * Author: Chunxu Li <[email protected]>
  7. */
  8. #include "mtk-dsp-sof-common.h"
  9. #include "mtk-soc-card.h"
  10. /* fixup the BE DAI link to match any values from topology */
  11. int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
  12. struct snd_pcm_hw_params *params)
  13. {
  14. struct snd_soc_card *card = rtd->card;
  15. struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
  16. struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
  17. int i, j, ret = 0;
  18. for (i = 0; i < sof_priv->num_streams; i++) {
  19. struct snd_soc_dai *cpu_dai;
  20. struct snd_soc_pcm_runtime *runtime;
  21. struct snd_soc_dai_link *sof_dai_link = NULL;
  22. const struct sof_conn_stream *conn = &sof_priv->conn_streams[i];
  23. if (strcmp(rtd->dai_link->name, conn->normal_link))
  24. continue;
  25. for_each_card_rtds(card, runtime) {
  26. if (strcmp(runtime->dai_link->name, conn->sof_link))
  27. continue;
  28. for_each_rtd_cpu_dais(runtime, j, cpu_dai) {
  29. if (cpu_dai->stream_active[conn->stream_dir] > 0) {
  30. sof_dai_link = runtime->dai_link;
  31. break;
  32. }
  33. }
  34. break;
  35. }
  36. if (sof_dai_link && sof_dai_link->be_hw_params_fixup)
  37. ret = sof_dai_link->be_hw_params_fixup(runtime, params);
  38. break;
  39. }
  40. return ret;
  41. }
  42. EXPORT_SYMBOL_GPL(mtk_sof_dai_link_fixup);
  43. int mtk_sof_card_probe(struct snd_soc_card *card)
  44. {
  45. int i;
  46. struct snd_soc_dai_link *dai_link;
  47. /* Set stream_name to help sof bind widgets */
  48. for_each_card_prelinks(card, i, dai_link) {
  49. if (dai_link->no_pcm && !dai_link->stream_name && dai_link->name)
  50. dai_link->stream_name = dai_link->name;
  51. }
  52. return 0;
  53. }
  54. EXPORT_SYMBOL_GPL(mtk_sof_card_probe);
  55. int mtk_sof_card_late_probe(struct snd_soc_card *card)
  56. {
  57. struct snd_soc_pcm_runtime *rtd;
  58. struct snd_soc_component *sof_comp = NULL;
  59. struct mtk_soc_card_data *soc_card_data =
  60. snd_soc_card_get_drvdata(card);
  61. struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
  62. int i;
  63. /* 1. find sof component */
  64. for_each_card_rtds(card, rtd) {
  65. sof_comp = snd_soc_rtdcom_lookup(rtd, "sof-audio-component");
  66. if (sof_comp)
  67. break;
  68. }
  69. if (!sof_comp) {
  70. dev_info(card->dev, "probe without sof-audio-component\n");
  71. return 0;
  72. }
  73. /* 2. add route path and fixup callback */
  74. for (i = 0; i < sof_priv->num_streams; i++) {
  75. const struct sof_conn_stream *conn = &sof_priv->conn_streams[i];
  76. struct snd_soc_pcm_runtime *sof_rtd = NULL;
  77. struct snd_soc_pcm_runtime *normal_rtd = NULL;
  78. for_each_card_rtds(card, rtd) {
  79. if (!strcmp(rtd->dai_link->name, conn->sof_link)) {
  80. sof_rtd = rtd;
  81. continue;
  82. }
  83. if (!strcmp(rtd->dai_link->name, conn->normal_link)) {
  84. normal_rtd = rtd;
  85. continue;
  86. }
  87. if (normal_rtd && sof_rtd)
  88. break;
  89. }
  90. if (normal_rtd && sof_rtd) {
  91. int j;
  92. struct snd_soc_dai *cpu_dai;
  93. for_each_rtd_cpu_dais(sof_rtd, j, cpu_dai) {
  94. struct snd_soc_dapm_route route;
  95. struct snd_soc_dapm_path *p = NULL;
  96. struct snd_soc_dapm_widget *play_widget =
  97. cpu_dai->playback_widget;
  98. struct snd_soc_dapm_widget *cap_widget =
  99. cpu_dai->capture_widget;
  100. memset(&route, 0, sizeof(route));
  101. if (conn->stream_dir == SNDRV_PCM_STREAM_CAPTURE &&
  102. cap_widget) {
  103. snd_soc_dapm_widget_for_each_sink_path(cap_widget, p) {
  104. route.source = conn->sof_dma;
  105. route.sink = p->sink->name;
  106. snd_soc_dapm_add_routes(&card->dapm, &route, 1);
  107. }
  108. } else if (conn->stream_dir == SNDRV_PCM_STREAM_PLAYBACK &&
  109. play_widget) {
  110. snd_soc_dapm_widget_for_each_source_path(play_widget, p) {
  111. route.source = p->source->name;
  112. route.sink = conn->sof_dma;
  113. snd_soc_dapm_add_routes(&card->dapm, &route, 1);
  114. }
  115. } else {
  116. dev_err(cpu_dai->dev, "stream dir and widget not pair\n");
  117. }
  118. }
  119. sof_rtd->dai_link->be_hw_params_fixup =
  120. sof_comp->driver->be_hw_params_fixup;
  121. if (sof_priv->sof_dai_link_fixup)
  122. normal_rtd->dai_link->be_hw_params_fixup =
  123. sof_priv->sof_dai_link_fixup;
  124. else
  125. normal_rtd->dai_link->be_hw_params_fixup = mtk_sof_dai_link_fixup;
  126. }
  127. }
  128. return 0;
  129. }
  130. EXPORT_SYMBOL_GPL(mtk_sof_card_late_probe);
  131. int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np,
  132. const char *propname, struct snd_soc_dai_link *pre_dai_links,
  133. int pre_num_links)
  134. {
  135. struct device *dev = card->dev;
  136. struct snd_soc_dai_link *parsed_dai_link;
  137. const char *dai_name = NULL;
  138. int i, j, ret, num_links, parsed_num_links = 0;
  139. num_links = of_property_count_strings(np, "mediatek,dai-link");
  140. if (num_links < 0 || num_links > card->num_links) {
  141. dev_dbg(dev, "number of dai-link is invalid\n");
  142. return -EINVAL;
  143. }
  144. parsed_dai_link = devm_kcalloc(dev, num_links, sizeof(*parsed_dai_link), GFP_KERNEL);
  145. if (!parsed_dai_link)
  146. return -ENOMEM;
  147. for (i = 0; i < num_links; i++) {
  148. ret = of_property_read_string_index(np, propname, i, &dai_name);
  149. if (ret) {
  150. dev_dbg(dev, "ASoC: Property '%s' index %d could not be read: %d\n",
  151. propname, i, ret);
  152. return ret;
  153. }
  154. dev_dbg(dev, "ASoC: Property get dai_name:%s\n", dai_name);
  155. for (j = 0; j < pre_num_links; j++) {
  156. if (!strcmp(dai_name, pre_dai_links[j].name)) {
  157. memcpy(&parsed_dai_link[parsed_num_links++], &pre_dai_links[j],
  158. sizeof(struct snd_soc_dai_link));
  159. break;
  160. }
  161. }
  162. }
  163. if (parsed_num_links != num_links)
  164. return -EINVAL;
  165. card->dai_link = parsed_dai_link;
  166. card->num_links = parsed_num_links;
  167. return 0;
  168. }
  169. EXPORT_SYMBOL_GPL(mtk_sof_dailink_parse_of);