acp-sdw-sof-mach.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. // Copyright(c) 2024 Advanced Micro Devices, Inc.
  3. /*
  4. * acp-sdw-sof-mach - ASoC Machine driver for AMD SoundWire platforms
  5. */
  6. #include <linux/bitmap.h>
  7. #include <linux/device.h>
  8. #include <linux/dmi.h>
  9. #include <linux/module.h>
  10. #include <linux/soundwire/sdw.h>
  11. #include <linux/soundwire/sdw_type.h>
  12. #include <sound/soc.h>
  13. #include <sound/soc-acpi.h>
  14. #include "soc_amd_sdw_common.h"
  15. #include "../../codecs/rt711.h"
  16. static unsigned long sof_sdw_quirk = RT711_JD1;
  17. static int quirk_override = -1;
  18. module_param_named(quirk, quirk_override, int, 0444);
  19. MODULE_PARM_DESC(quirk, "Board-specific quirk override");
  20. static void log_quirks(struct device *dev)
  21. {
  22. if (SOC_JACK_JDSRC(sof_sdw_quirk))
  23. dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
  24. SOC_JACK_JDSRC(sof_sdw_quirk));
  25. if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC)
  26. dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n");
  27. }
  28. static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
  29. {
  30. sof_sdw_quirk = (unsigned long)id->driver_data;
  31. return 1;
  32. }
  33. static const struct dmi_system_id sof_sdw_quirk_table[] = {
  34. {
  35. .callback = sof_sdw_quirk_cb,
  36. .matches = {
  37. DMI_MATCH(DMI_SYS_VENDOR, "AMD"),
  38. DMI_MATCH(DMI_PRODUCT_NAME, "Birman-PHX"),
  39. },
  40. .driver_data = (void *)RT711_JD2,
  41. },
  42. {}
  43. };
  44. static struct snd_soc_dai_link_component platform_component[] = {
  45. {
  46. /* name might be overridden during probe */
  47. .name = "0000:04:00.5",
  48. }
  49. };
  50. static const struct snd_soc_ops sdw_ops = {
  51. .startup = asoc_sdw_startup,
  52. .prepare = asoc_sdw_prepare,
  53. .trigger = asoc_sdw_trigger,
  54. .hw_params = asoc_sdw_hw_params,
  55. .hw_free = asoc_sdw_hw_free,
  56. .shutdown = asoc_sdw_shutdown,
  57. };
  58. static int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev)
  59. {
  60. switch (sdw_link_id) {
  61. case AMD_SDW0:
  62. switch (be_id) {
  63. case SOC_SDW_JACK_OUT_DAI_ID:
  64. *cpu_pin_id = ACP63_SW0_AUDIO0_TX;
  65. break;
  66. case SOC_SDW_JACK_IN_DAI_ID:
  67. *cpu_pin_id = ACP63_SW0_AUDIO0_RX;
  68. break;
  69. case SOC_SDW_AMP_OUT_DAI_ID:
  70. *cpu_pin_id = ACP63_SW0_AUDIO1_TX;
  71. break;
  72. case SOC_SDW_AMP_IN_DAI_ID:
  73. *cpu_pin_id = ACP63_SW0_AUDIO1_RX;
  74. break;
  75. case SOC_SDW_DMIC_DAI_ID:
  76. *cpu_pin_id = ACP63_SW0_AUDIO2_RX;
  77. break;
  78. default:
  79. dev_err(dev, "Invalid be id:%d\n", be_id);
  80. return -EINVAL;
  81. }
  82. break;
  83. case AMD_SDW1:
  84. switch (be_id) {
  85. case SOC_SDW_JACK_OUT_DAI_ID:
  86. case SOC_SDW_AMP_OUT_DAI_ID:
  87. *cpu_pin_id = ACP63_SW1_AUDIO0_TX;
  88. break;
  89. case SOC_SDW_JACK_IN_DAI_ID:
  90. case SOC_SDW_AMP_IN_DAI_ID:
  91. case SOC_SDW_DMIC_DAI_ID:
  92. *cpu_pin_id = ACP63_SW1_AUDIO0_RX;
  93. break;
  94. default:
  95. dev_err(dev, "invalid be_id:%d\n", be_id);
  96. return -EINVAL;
  97. }
  98. break;
  99. default:
  100. dev_err(dev, "Invalid link id:%d\n", sdw_link_id);
  101. return -EINVAL;
  102. }
  103. return 0;
  104. }
  105. static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
  106. static int create_sdw_dailink(struct snd_soc_card *card,
  107. struct asoc_sdw_dailink *sof_dai,
  108. struct snd_soc_dai_link **dai_links,
  109. int *be_id, struct snd_soc_codec_conf **codec_conf)
  110. {
  111. struct device *dev = card->dev;
  112. struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
  113. struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private;
  114. struct asoc_sdw_endpoint *sof_end;
  115. int cpu_pin_id;
  116. int stream;
  117. int ret;
  118. list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
  119. if (sof_end->name_prefix) {
  120. (*codec_conf)->dlc.name = sof_end->codec_name;
  121. (*codec_conf)->name_prefix = sof_end->name_prefix;
  122. (*codec_conf)++;
  123. }
  124. if (sof_end->include_sidecar) {
  125. ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf);
  126. if (ret)
  127. return ret;
  128. }
  129. }
  130. for_each_pcm_streams(stream) {
  131. static const char * const sdw_stream_name[] = {
  132. "SDW%d-PIN%d-PLAYBACK",
  133. "SDW%d-PIN%d-CAPTURE",
  134. "SDW%d-PIN%d-PLAYBACK-%s",
  135. "SDW%d-PIN%d-CAPTURE-%s",
  136. };
  137. struct snd_soc_dai_link_ch_map *codec_maps;
  138. struct snd_soc_dai_link_component *codecs;
  139. struct snd_soc_dai_link_component *cpus;
  140. int num_cpus = hweight32(sof_dai->link_mask[stream]);
  141. int num_codecs = sof_dai->num_devs[stream];
  142. int playback, capture;
  143. int j = 0;
  144. char *name;
  145. if (!sof_dai->num_devs[stream])
  146. continue;
  147. sof_end = list_first_entry(&sof_dai->endpoints,
  148. struct asoc_sdw_endpoint, list);
  149. *be_id = sof_end->dai_info->dailink[stream];
  150. if (*be_id < 0) {
  151. dev_err(dev, "Invalid dailink id %d\n", *be_id);
  152. return -EINVAL;
  153. }
  154. switch (amd_ctx->acp_rev) {
  155. case ACP63_PCI_REV:
  156. ret = get_acp63_cpu_pin_id(ffs(sof_end->link_mask - 1),
  157. *be_id, &cpu_pin_id, dev);
  158. if (ret)
  159. return ret;
  160. break;
  161. default:
  162. return -EINVAL;
  163. }
  164. /* create stream name according to first link id */
  165. if (ctx->append_dai_type) {
  166. name = devm_kasprintf(dev, GFP_KERNEL,
  167. sdw_stream_name[stream + 2],
  168. ffs(sof_end->link_mask) - 1,
  169. cpu_pin_id,
  170. type_strings[sof_end->dai_info->dai_type]);
  171. } else {
  172. name = devm_kasprintf(dev, GFP_KERNEL,
  173. sdw_stream_name[stream],
  174. ffs(sof_end->link_mask) - 1,
  175. cpu_pin_id);
  176. }
  177. if (!name)
  178. return -ENOMEM;
  179. cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL);
  180. if (!cpus)
  181. return -ENOMEM;
  182. codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL);
  183. if (!codecs)
  184. return -ENOMEM;
  185. codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL);
  186. if (!codec_maps)
  187. return -ENOMEM;
  188. list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
  189. if (!sof_end->dai_info->direction[stream])
  190. continue;
  191. int link_num = ffs(sof_end->link_mask) - 1;
  192. cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
  193. "SDW%d Pin%d",
  194. link_num, cpu_pin_id);
  195. dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name);
  196. if (!cpus->dai_name)
  197. return -ENOMEM;
  198. codec_maps[j].cpu = 0;
  199. codec_maps[j].codec = j;
  200. codecs[j].name = sof_end->codec_name;
  201. codecs[j].dai_name = sof_end->dai_info->dai_name;
  202. j++;
  203. }
  204. WARN_ON(j != num_codecs);
  205. playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
  206. capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
  207. asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
  208. cpus, num_cpus, platform_component,
  209. ARRAY_SIZE(platform_component), codecs, num_codecs,
  210. asoc_sdw_rtd_init, &sdw_ops);
  211. /*
  212. * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
  213. * based on wait_for_completion(), tag them as 'nonatomic'.
  214. */
  215. (*dai_links)->nonatomic = true;
  216. (*dai_links)->ch_maps = codec_maps;
  217. list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
  218. if (sof_end->dai_info->init)
  219. sof_end->dai_info->init(card, *dai_links,
  220. sof_end->codec_info,
  221. playback);
  222. }
  223. (*dai_links)++;
  224. }
  225. return 0;
  226. }
  227. static int create_sdw_dailinks(struct snd_soc_card *card,
  228. struct snd_soc_dai_link **dai_links, int *be_id,
  229. struct asoc_sdw_dailink *sof_dais,
  230. struct snd_soc_codec_conf **codec_conf)
  231. {
  232. int ret;
  233. /* generate DAI links by each sdw link */
  234. while (sof_dais->initialised) {
  235. int current_be_id;
  236. ret = create_sdw_dailink(card, sof_dais, dai_links,
  237. &current_be_id, codec_conf);
  238. if (ret)
  239. return ret;
  240. /* Update the be_id to match the highest ID used for SDW link */
  241. if (*be_id < current_be_id)
  242. *be_id = current_be_id;
  243. sof_dais++;
  244. }
  245. return 0;
  246. }
  247. static int create_dmic_dailinks(struct snd_soc_card *card,
  248. struct snd_soc_dai_link **dai_links, int *be_id)
  249. {
  250. struct device *dev = card->dev;
  251. int ret;
  252. ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec",
  253. 0, 1, // DMIC only supports capture
  254. "acp-sof-dmic", platform_component->name,
  255. ARRAY_SIZE(platform_component),
  256. "dmic-codec", "dmic-hifi",
  257. asoc_sdw_dmic_init, NULL);
  258. if (ret)
  259. return ret;
  260. (*dai_links)++;
  261. return 0;
  262. }
  263. static int sof_card_dai_links_create(struct snd_soc_card *card)
  264. {
  265. struct device *dev = card->dev;
  266. struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
  267. int sdw_be_num = 0, dmic_num = 0;
  268. struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
  269. struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
  270. struct snd_soc_codec_conf *codec_conf;
  271. struct asoc_sdw_endpoint *sof_ends;
  272. struct asoc_sdw_dailink *sof_dais;
  273. struct snd_soc_dai_link *dai_links;
  274. int num_devs = 0;
  275. int num_ends = 0;
  276. int num_links;
  277. int be_id = 0;
  278. int ret;
  279. ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends);
  280. if (ret < 0) {
  281. dev_err(dev, "failed to count devices/endpoints: %d\n", ret);
  282. return ret;
  283. }
  284. /* One per DAI link, worst case is a DAI link for every endpoint */
  285. sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL);
  286. if (!sof_dais)
  287. return -ENOMEM;
  288. /* One per endpoint, ie. each DAI on each codec/amp */
  289. sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL);
  290. if (!sof_ends) {
  291. ret = -ENOMEM;
  292. goto err_dai;
  293. }
  294. ret = asoc_sdw_parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs);
  295. if (ret < 0)
  296. goto err_end;
  297. sdw_be_num = ret;
  298. /* enable dmic */
  299. if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC || mach_params->dmic_num)
  300. dmic_num = 1;
  301. dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num);
  302. codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
  303. if (!codec_conf) {
  304. ret = -ENOMEM;
  305. goto err_end;
  306. }
  307. /* allocate BE dailinks */
  308. num_links = sdw_be_num + dmic_num;
  309. dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
  310. if (!dai_links) {
  311. ret = -ENOMEM;
  312. goto err_end;
  313. }
  314. card->codec_conf = codec_conf;
  315. card->num_configs = num_devs;
  316. card->dai_link = dai_links;
  317. card->num_links = num_links;
  318. /* SDW */
  319. if (sdw_be_num) {
  320. ret = create_sdw_dailinks(card, &dai_links, &be_id,
  321. sof_dais, &codec_conf);
  322. if (ret)
  323. goto err_end;
  324. }
  325. /* dmic */
  326. if (dmic_num > 0) {
  327. if (ctx->ignore_internal_dmic) {
  328. dev_warn(dev, "Ignoring ACP DMIC\n");
  329. } else {
  330. ret = create_dmic_dailinks(card, &dai_links, &be_id);
  331. if (ret)
  332. goto err_end;
  333. }
  334. }
  335. WARN_ON(codec_conf != card->codec_conf + card->num_configs);
  336. WARN_ON(dai_links != card->dai_link + card->num_links);
  337. err_end:
  338. kfree(sof_ends);
  339. err_dai:
  340. kfree(sof_dais);
  341. return ret;
  342. }
  343. static int mc_probe(struct platform_device *pdev)
  344. {
  345. struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
  346. struct snd_soc_card *card;
  347. struct amd_mc_ctx *amd_ctx;
  348. struct asoc_sdw_mc_private *ctx;
  349. int amp_num = 0, i;
  350. int ret;
  351. amd_ctx = devm_kzalloc(&pdev->dev, sizeof(*amd_ctx), GFP_KERNEL);
  352. if (!amd_ctx)
  353. return -ENOMEM;
  354. amd_ctx->acp_rev = mach->mach_params.subsystem_rev;
  355. amd_ctx->max_sdw_links = ACP63_SDW_MAX_LINKS;
  356. ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
  357. if (!ctx)
  358. return -ENOMEM;
  359. ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count();
  360. ctx->private = amd_ctx;
  361. card = &ctx->card;
  362. card->dev = &pdev->dev;
  363. card->name = "amd-soundwire";
  364. card->owner = THIS_MODULE;
  365. card->late_probe = asoc_sdw_card_late_probe;
  366. snd_soc_card_set_drvdata(card, ctx);
  367. dmi_check_system(sof_sdw_quirk_table);
  368. if (quirk_override != -1) {
  369. dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n",
  370. sof_sdw_quirk, quirk_override);
  371. sof_sdw_quirk = quirk_override;
  372. }
  373. log_quirks(card->dev);
  374. ctx->mc_quirk = sof_sdw_quirk;
  375. /* reset amp_num to ensure amp_num++ starts from 0 in each probe */
  376. for (i = 0; i < ctx->codec_info_list_count; i++)
  377. codec_info_list[i].amp_num = 0;
  378. ret = sof_card_dai_links_create(card);
  379. if (ret < 0)
  380. return ret;
  381. /*
  382. * the default amp_num is zero for each codec and
  383. * amp_num will only be increased for active amp
  384. * codecs on used platform
  385. */
  386. for (i = 0; i < ctx->codec_info_list_count; i++)
  387. amp_num += codec_info_list[i].amp_num;
  388. card->components = devm_kasprintf(card->dev, GFP_KERNEL,
  389. " cfg-amp:%d", amp_num);
  390. if (!card->components)
  391. return -ENOMEM;
  392. /* Register the card */
  393. ret = devm_snd_soc_register_card(card->dev, card);
  394. if (ret) {
  395. dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret);
  396. asoc_sdw_mc_dailink_exit_loop(card);
  397. return ret;
  398. }
  399. platform_set_drvdata(pdev, card);
  400. return ret;
  401. }
  402. static void mc_remove(struct platform_device *pdev)
  403. {
  404. struct snd_soc_card *card = platform_get_drvdata(pdev);
  405. asoc_sdw_mc_dailink_exit_loop(card);
  406. }
  407. static const struct platform_device_id mc_id_table[] = {
  408. { "amd_sof_sdw", },
  409. {}
  410. };
  411. MODULE_DEVICE_TABLE(platform, mc_id_table);
  412. static struct platform_driver sof_sdw_driver = {
  413. .driver = {
  414. .name = "amd_sof_sdw",
  415. .pm = &snd_soc_pm_ops,
  416. },
  417. .probe = mc_probe,
  418. .remove = mc_remove,
  419. .id_table = mc_id_table,
  420. };
  421. module_platform_driver(sof_sdw_driver);
  422. MODULE_DESCRIPTION("ASoC AMD SoundWire Generic Machine driver");
  423. MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com");
  424. MODULE_LICENSE("GPL");
  425. MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);