sof-function-topology-lib.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // This file is provided under a dual BSD/GPLv2 license. When using or
  4. // redistributing this file, you may do so under either license.
  5. //
  6. // Copyright(c) 2025 Intel Corporation.
  7. //
  8. #include <linux/device.h>
  9. #include <linux/errno.h>
  10. #include <linux/firmware.h>
  11. #include <sound/soc.h>
  12. #include <sound/soc-acpi.h>
  13. #include "sof-function-topology-lib.h"
  14. enum tplg_device_id {
  15. TPLG_DEVICE_SDCA_JACK,
  16. TPLG_DEVICE_SDCA_AMP,
  17. TPLG_DEVICE_SDCA_MIC,
  18. TPLG_DEVICE_INTEL_PCH_DMIC,
  19. TPLG_DEVICE_HDMI,
  20. TPLG_DEVICE_MAX
  21. };
  22. #define SDCA_DEVICE_MASK (BIT(TPLG_DEVICE_SDCA_JACK) | BIT(TPLG_DEVICE_SDCA_AMP) | \
  23. BIT(TPLG_DEVICE_SDCA_MIC))
  24. #define SOF_INTEL_PLATFORM_NAME_MAX 4
  25. int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_mach *mach,
  26. const char *prefix, const char ***tplg_files)
  27. {
  28. struct snd_soc_acpi_mach_params mach_params = mach->mach_params;
  29. struct snd_soc_dai_link *dai_link;
  30. const struct firmware *fw;
  31. char platform[SOF_INTEL_PLATFORM_NAME_MAX];
  32. unsigned long tplg_mask = 0;
  33. int tplg_num = 0;
  34. int tplg_dev;
  35. int ret;
  36. int i;
  37. ret = sscanf(mach->sof_tplg_filename, "sof-%3s-*.tplg", platform);
  38. if (ret != 1) {
  39. dev_err(card->dev, "Invalid platform name %s of tplg %s\n",
  40. platform, mach->sof_tplg_filename);
  41. return -EINVAL;
  42. }
  43. for_each_card_prelinks(card, i, dai_link) {
  44. char *tplg_dev_name;
  45. dev_dbg(card->dev, "dai_link %s id %d\n", dai_link->name, dai_link->id);
  46. if (strstr(dai_link->name, "SimpleJack")) {
  47. tplg_dev = TPLG_DEVICE_SDCA_JACK;
  48. tplg_dev_name = "sdca-jack";
  49. } else if (strstr(dai_link->name, "SmartAmp")) {
  50. tplg_dev = TPLG_DEVICE_SDCA_AMP;
  51. tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,
  52. "sdca-%damp", dai_link->num_cpus);
  53. if (!tplg_dev_name)
  54. return -ENOMEM;
  55. } else if (strstr(dai_link->name, "SmartMic")) {
  56. tplg_dev = TPLG_DEVICE_SDCA_MIC;
  57. tplg_dev_name = "sdca-mic";
  58. } else if (strstr(dai_link->name, "dmic")) {
  59. switch (mach_params.dmic_num) {
  60. case 2:
  61. tplg_dev_name = "dmic-2ch";
  62. break;
  63. case 4:
  64. tplg_dev_name = "dmic-4ch";
  65. break;
  66. default:
  67. dev_warn(card->dev,
  68. "unsupported number of dmics: %d\n",
  69. mach_params.dmic_num);
  70. continue;
  71. }
  72. tplg_dev = TPLG_DEVICE_INTEL_PCH_DMIC;
  73. } else if (strstr(dai_link->name, "iDisp")) {
  74. tplg_dev = TPLG_DEVICE_HDMI;
  75. tplg_dev_name = "hdmi-pcm5";
  76. } else {
  77. /* The dai link is not supported by separated tplg yet */
  78. dev_dbg(card->dev,
  79. "dai_link %s is not supported by separated tplg yet\n",
  80. dai_link->name);
  81. return 0;
  82. }
  83. if (tplg_mask & BIT(tplg_dev))
  84. continue;
  85. tplg_mask |= BIT(tplg_dev);
  86. /*
  87. * The tplg file naming rule is sof-<platform>-<function>-id<BE id number>.tplg
  88. * where <platform> is only required for the DMIC function as the nhlt blob
  89. * is platform dependent.
  90. */
  91. switch (tplg_dev) {
  92. case TPLG_DEVICE_INTEL_PCH_DMIC:
  93. (*tplg_files)[tplg_num] = devm_kasprintf(card->dev, GFP_KERNEL,
  94. "%s/sof-%s-%s-id%d.tplg",
  95. prefix, platform,
  96. tplg_dev_name, dai_link->id);
  97. break;
  98. default:
  99. (*tplg_files)[tplg_num] = devm_kasprintf(card->dev, GFP_KERNEL,
  100. "%s/sof-%s-id%d.tplg",
  101. prefix, tplg_dev_name,
  102. dai_link->id);
  103. break;
  104. }
  105. if (!(*tplg_files)[tplg_num])
  106. return -ENOMEM;
  107. tplg_num++;
  108. }
  109. dev_dbg(card->dev, "tplg_mask %#lx tplg_num %d\n", tplg_mask, tplg_num);
  110. /* Check presence of sub-topologies */
  111. for (i = 0; i < tplg_num; i++) {
  112. ret = firmware_request_nowarn(&fw, (*tplg_files)[i], card->dev);
  113. if (!ret) {
  114. release_firmware(fw);
  115. } else {
  116. dev_dbg(card->dev, "Failed to open topology file: %s\n", (*tplg_files)[i]);
  117. return 0;
  118. }
  119. }
  120. return tplg_num;
  121. }