sof_board_helpers.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // Copyright(c) 2023 Intel Corporation
  4. #include <sound/soc.h>
  5. #include "../common/soc-intel-quirks.h"
  6. #include "hda_dsp_common.h"
  7. #include "sof_board_helpers.h"
  8. /*
  9. * Intel HDMI DAI Link
  10. */
  11. static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
  12. {
  13. struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
  14. struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
  15. ctx->hdmi.hdmi_comp = dai->component;
  16. return 0;
  17. }
  18. int sof_intel_board_card_late_probe(struct snd_soc_card *card)
  19. {
  20. struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
  21. if (!ctx->hdmi_num)
  22. return 0;
  23. if (!ctx->hdmi.idisp_codec)
  24. return 0;
  25. if (!ctx->hdmi.hdmi_comp)
  26. return -EINVAL;
  27. return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp);
  28. }
  29. EXPORT_SYMBOL_NS(sof_intel_board_card_late_probe, SND_SOC_INTEL_SOF_BOARD_HELPERS);
  30. /*
  31. * DMIC DAI Link
  32. */
  33. static const struct snd_soc_dapm_widget dmic_widgets[] = {
  34. SND_SOC_DAPM_MIC("SoC DMIC", NULL),
  35. };
  36. static const struct snd_soc_dapm_route dmic_routes[] = {
  37. {"DMic", NULL, "SoC DMIC"},
  38. };
  39. static int dmic_init(struct snd_soc_pcm_runtime *rtd)
  40. {
  41. struct snd_soc_card *card = rtd->card;
  42. int ret;
  43. ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
  44. ARRAY_SIZE(dmic_widgets));
  45. if (ret) {
  46. dev_err(rtd->dev, "fail to add dmic widgets, ret %d\n", ret);
  47. return ret;
  48. }
  49. ret = snd_soc_dapm_add_routes(&card->dapm, dmic_routes,
  50. ARRAY_SIZE(dmic_routes));
  51. if (ret) {
  52. dev_err(rtd->dev, "fail to add dmic routes, ret %d\n", ret);
  53. return ret;
  54. }
  55. return 0;
  56. }
  57. /*
  58. * HDA External Codec DAI Link
  59. */
  60. static const struct snd_soc_dapm_widget hda_widgets[] = {
  61. SND_SOC_DAPM_MIC("Analog In", NULL),
  62. SND_SOC_DAPM_MIC("Digital In", NULL),
  63. SND_SOC_DAPM_MIC("Alt Analog In", NULL),
  64. SND_SOC_DAPM_HP("Analog Out", NULL),
  65. SND_SOC_DAPM_SPK("Digital Out", NULL),
  66. SND_SOC_DAPM_HP("Alt Analog Out", NULL),
  67. };
  68. static const struct snd_soc_dapm_route hda_routes[] = {
  69. { "Codec Input Pin1", NULL, "Analog In" },
  70. { "Codec Input Pin2", NULL, "Digital In" },
  71. { "Codec Input Pin3", NULL, "Alt Analog In" },
  72. { "Analog Out", NULL, "Codec Output Pin1" },
  73. { "Digital Out", NULL, "Codec Output Pin2" },
  74. { "Alt Analog Out", NULL, "Codec Output Pin3" },
  75. /* CODEC BE connections */
  76. { "codec0_in", NULL, "Analog CPU Capture" },
  77. { "Analog CPU Capture", NULL, "Analog Codec Capture" },
  78. { "codec1_in", NULL, "Digital CPU Capture" },
  79. { "Digital CPU Capture", NULL, "Digital Codec Capture" },
  80. { "codec2_in", NULL, "Alt Analog CPU Capture" },
  81. { "Alt Analog CPU Capture", NULL, "Alt Analog Codec Capture" },
  82. { "Analog Codec Playback", NULL, "Analog CPU Playback" },
  83. { "Analog CPU Playback", NULL, "codec0_out" },
  84. { "Digital Codec Playback", NULL, "Digital CPU Playback" },
  85. { "Digital CPU Playback", NULL, "codec1_out" },
  86. { "Alt Analog Codec Playback", NULL, "Alt Analog CPU Playback" },
  87. { "Alt Analog CPU Playback", NULL, "codec2_out" },
  88. };
  89. static int hda_init(struct snd_soc_pcm_runtime *rtd)
  90. {
  91. struct snd_soc_card *card = rtd->card;
  92. int ret;
  93. ret = snd_soc_dapm_new_controls(&card->dapm, hda_widgets,
  94. ARRAY_SIZE(hda_widgets));
  95. if (ret) {
  96. dev_err(rtd->dev, "fail to add hda widgets, ret %d\n", ret);
  97. return ret;
  98. }
  99. ret = snd_soc_dapm_add_routes(&card->dapm, hda_routes,
  100. ARRAY_SIZE(hda_routes));
  101. if (ret)
  102. dev_err(rtd->dev, "fail to add hda routes, ret %d\n", ret);
  103. return ret;
  104. }
  105. /*
  106. * DAI Link Helpers
  107. */
  108. enum sof_dmic_be_type {
  109. SOF_DMIC_01,
  110. SOF_DMIC_16K,
  111. };
  112. enum sof_hda_be_type {
  113. SOF_HDA_ANALOG,
  114. SOF_HDA_DIGITAL,
  115. };
  116. /* DEFAULT_LINK_ORDER: the order used in sof_rt5682 */
  117. #define DEFAULT_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_CODEC, \
  118. SOF_LINK_DMIC01, \
  119. SOF_LINK_DMIC16K, \
  120. SOF_LINK_IDISP_HDMI, \
  121. SOF_LINK_AMP, \
  122. SOF_LINK_BT_OFFLOAD, \
  123. SOF_LINK_HDMI_IN)
  124. static struct snd_soc_dai_link_component dmic_component[] = {
  125. {
  126. .name = "dmic-codec",
  127. .dai_name = "dmic-hifi",
  128. }
  129. };
  130. SND_SOC_DAILINK_DEF(hda_analog_cpus,
  131. DAILINK_COMP_ARRAY(COMP_CPU("Analog CPU DAI")));
  132. SND_SOC_DAILINK_DEF(hda_analog_codecs,
  133. DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Analog Codec DAI")));
  134. SND_SOC_DAILINK_DEF(hda_digital_cpus,
  135. DAILINK_COMP_ARRAY(COMP_CPU("Digital CPU DAI")));
  136. SND_SOC_DAILINK_DEF(hda_digital_codecs,
  137. DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Digital Codec DAI")));
  138. static struct snd_soc_dai_link_component platform_component[] = {
  139. {
  140. /* name might be overridden during probe */
  141. .name = "0000:00:1f.3"
  142. }
  143. };
  144. static int set_ssp_codec_link(struct device *dev, struct snd_soc_dai_link *link,
  145. int be_id, enum snd_soc_acpi_intel_codec codec_type,
  146. int ssp_codec)
  147. {
  148. struct snd_soc_dai_link_component *cpus;
  149. dev_dbg(dev, "link %d: ssp codec %s, ssp %d\n", be_id,
  150. snd_soc_acpi_intel_get_codec_name(codec_type), ssp_codec);
  151. /* link name */
  152. link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec);
  153. if (!link->name)
  154. return -ENOMEM;
  155. /* cpus */
  156. cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
  157. GFP_KERNEL);
  158. if (!cpus)
  159. return -ENOMEM;
  160. if (soc_intel_is_byt() || soc_intel_is_cht()) {
  161. /* backward-compatibility for BYT/CHT boards */
  162. cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "ssp%d-port",
  163. ssp_codec);
  164. } else {
  165. cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin",
  166. ssp_codec);
  167. }
  168. if (!cpus->dai_name)
  169. return -ENOMEM;
  170. link->cpus = cpus;
  171. link->num_cpus = 1;
  172. /* codecs - caller to handle */
  173. /* platforms */
  174. link->platforms = platform_component;
  175. link->num_platforms = ARRAY_SIZE(platform_component);
  176. link->id = be_id;
  177. link->no_pcm = 1;
  178. link->dpcm_capture = 1;
  179. link->dpcm_playback = 1;
  180. return 0;
  181. }
  182. static int set_dmic_link(struct device *dev, struct snd_soc_dai_link *link,
  183. int be_id, enum sof_dmic_be_type be_type)
  184. {
  185. struct snd_soc_dai_link_component *cpus;
  186. /* cpus */
  187. cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
  188. GFP_KERNEL);
  189. if (!cpus)
  190. return -ENOMEM;
  191. switch (be_type) {
  192. case SOF_DMIC_01:
  193. dev_dbg(dev, "link %d: dmic01\n", be_id);
  194. link->name = "dmic01";
  195. cpus->dai_name = "DMIC01 Pin";
  196. break;
  197. case SOF_DMIC_16K:
  198. dev_dbg(dev, "link %d: dmic16k\n", be_id);
  199. link->name = "dmic16k";
  200. cpus->dai_name = "DMIC16k Pin";
  201. break;
  202. default:
  203. dev_err(dev, "invalid be type %d\n", be_type);
  204. return -EINVAL;
  205. }
  206. link->cpus = cpus;
  207. link->num_cpus = 1;
  208. /* codecs */
  209. link->codecs = dmic_component;
  210. link->num_codecs = ARRAY_SIZE(dmic_component);
  211. /* platforms */
  212. link->platforms = platform_component;
  213. link->num_platforms = ARRAY_SIZE(platform_component);
  214. link->id = be_id;
  215. if (be_type == SOF_DMIC_01)
  216. link->init = dmic_init;
  217. link->ignore_suspend = 1;
  218. link->no_pcm = 1;
  219. link->dpcm_capture = 1;
  220. return 0;
  221. }
  222. static int set_idisp_hdmi_link(struct device *dev, struct snd_soc_dai_link *link,
  223. int be_id, int hdmi_id, bool idisp_codec)
  224. {
  225. struct snd_soc_dai_link_component *cpus, *codecs;
  226. dev_dbg(dev, "link %d: idisp hdmi %d, idisp codec %d\n", be_id, hdmi_id,
  227. idisp_codec);
  228. /* link name */
  229. link->name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", hdmi_id);
  230. if (!link->name)
  231. return -ENOMEM;
  232. /* cpus */
  233. cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
  234. GFP_KERNEL);
  235. if (!cpus)
  236. return -ENOMEM;
  237. cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", hdmi_id);
  238. if (!cpus->dai_name)
  239. return -ENOMEM;
  240. link->cpus = cpus;
  241. link->num_cpus = 1;
  242. /* codecs */
  243. if (idisp_codec) {
  244. codecs = devm_kzalloc(dev,
  245. sizeof(struct snd_soc_dai_link_component),
  246. GFP_KERNEL);
  247. if (!codecs)
  248. return -ENOMEM;
  249. codecs->name = "ehdaudio0D2";
  250. codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL,
  251. "intel-hdmi-hifi%d", hdmi_id);
  252. if (!codecs->dai_name)
  253. return -ENOMEM;
  254. link->codecs = codecs;
  255. } else {
  256. link->codecs = &snd_soc_dummy_dlc;
  257. }
  258. link->num_codecs = 1;
  259. /* platforms */
  260. link->platforms = platform_component;
  261. link->num_platforms = ARRAY_SIZE(platform_component);
  262. link->id = be_id;
  263. link->init = (hdmi_id == 1) ? hdmi_init : NULL;
  264. link->no_pcm = 1;
  265. link->dpcm_playback = 1;
  266. return 0;
  267. }
  268. static int set_ssp_amp_link(struct device *dev, struct snd_soc_dai_link *link,
  269. int be_id, enum snd_soc_acpi_intel_codec amp_type,
  270. int ssp_amp)
  271. {
  272. struct snd_soc_dai_link_component *cpus;
  273. dev_dbg(dev, "link %d: ssp amp %s, ssp %d\n", be_id,
  274. snd_soc_acpi_intel_get_codec_name(amp_type), ssp_amp);
  275. /* link name */
  276. link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_amp);
  277. if (!link->name)
  278. return -ENOMEM;
  279. /* cpus */
  280. cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
  281. GFP_KERNEL);
  282. if (!cpus)
  283. return -ENOMEM;
  284. cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_amp);
  285. if (!cpus->dai_name)
  286. return -ENOMEM;
  287. link->cpus = cpus;
  288. link->num_cpus = 1;
  289. /* codecs - caller to handle */
  290. /* platforms */
  291. link->platforms = platform_component;
  292. link->num_platforms = ARRAY_SIZE(platform_component);
  293. link->id = be_id;
  294. link->no_pcm = 1;
  295. link->dpcm_capture = 1; /* feedback stream or firmware-generated echo reference */
  296. link->dpcm_playback = 1;
  297. return 0;
  298. }
  299. static int set_bt_offload_link(struct device *dev, struct snd_soc_dai_link *link,
  300. int be_id, int ssp_bt)
  301. {
  302. struct snd_soc_dai_link_component *cpus;
  303. dev_dbg(dev, "link %d: bt offload, ssp %d\n", be_id, ssp_bt);
  304. /* link name */
  305. link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", ssp_bt);
  306. if (!link->name)
  307. return -ENOMEM;
  308. /* cpus */
  309. cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
  310. GFP_KERNEL);
  311. if (!cpus)
  312. return -ENOMEM;
  313. cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_bt);
  314. if (!cpus->dai_name)
  315. return -ENOMEM;
  316. link->cpus = cpus;
  317. link->num_cpus = 1;
  318. /* codecs */
  319. link->codecs = &snd_soc_dummy_dlc;
  320. link->num_codecs = 1;
  321. /* platforms */
  322. link->platforms = platform_component;
  323. link->num_platforms = ARRAY_SIZE(platform_component);
  324. link->id = be_id;
  325. link->no_pcm = 1;
  326. link->dpcm_capture = 1;
  327. link->dpcm_playback = 1;
  328. return 0;
  329. }
  330. static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link,
  331. int be_id, int ssp_hdmi)
  332. {
  333. struct snd_soc_dai_link_component *cpus;
  334. dev_dbg(dev, "link %d: hdmi-in, ssp %d\n", be_id, ssp_hdmi);
  335. /* link name */
  336. link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", ssp_hdmi);
  337. if (!link->name)
  338. return -ENOMEM;
  339. /* cpus */
  340. cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
  341. GFP_KERNEL);
  342. if (!cpus)
  343. return -ENOMEM;
  344. cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_hdmi);
  345. if (!cpus->dai_name)
  346. return -ENOMEM;
  347. link->cpus = cpus;
  348. link->num_cpus = 1;
  349. /* codecs */
  350. link->codecs = &snd_soc_dummy_dlc;
  351. link->num_codecs = 1;
  352. /* platforms */
  353. link->platforms = platform_component;
  354. link->num_platforms = ARRAY_SIZE(platform_component);
  355. link->id = be_id;
  356. link->no_pcm = 1;
  357. link->dpcm_capture = 1;
  358. return 0;
  359. }
  360. static int set_hda_codec_link(struct device *dev, struct snd_soc_dai_link *link,
  361. int be_id, enum sof_hda_be_type be_type)
  362. {
  363. switch (be_type) {
  364. case SOF_HDA_ANALOG:
  365. dev_dbg(dev, "link %d: hda analog\n", be_id);
  366. link->name = "Analog Playback and Capture";
  367. /* cpus */
  368. link->cpus = hda_analog_cpus;
  369. link->num_cpus = ARRAY_SIZE(hda_analog_cpus);
  370. /* codecs */
  371. link->codecs = hda_analog_codecs;
  372. link->num_codecs = ARRAY_SIZE(hda_analog_codecs);
  373. break;
  374. case SOF_HDA_DIGITAL:
  375. dev_dbg(dev, "link %d: hda digital\n", be_id);
  376. link->name = "Digital Playback and Capture";
  377. /* cpus */
  378. link->cpus = hda_digital_cpus;
  379. link->num_cpus = ARRAY_SIZE(hda_digital_cpus);
  380. /* codecs */
  381. link->codecs = hda_digital_codecs;
  382. link->num_codecs = ARRAY_SIZE(hda_digital_codecs);
  383. break;
  384. default:
  385. dev_err(dev, "invalid be type %d\n", be_type);
  386. return -EINVAL;
  387. }
  388. /* platforms */
  389. link->platforms = platform_component;
  390. link->num_platforms = ARRAY_SIZE(platform_component);
  391. link->id = be_id;
  392. if (be_type == SOF_HDA_ANALOG)
  393. link->init = hda_init;
  394. link->no_pcm = 1;
  395. link->dpcm_capture = 1;
  396. link->dpcm_playback = 1;
  397. return 0;
  398. }
  399. static int calculate_num_links(struct sof_card_private *ctx)
  400. {
  401. int num_links = 0;
  402. /* headphone codec */
  403. if (ctx->codec_type != CODEC_NONE)
  404. num_links++;
  405. /* dmic01 and dmic16k */
  406. if (ctx->dmic_be_num > 0)
  407. num_links++;
  408. if (ctx->dmic_be_num > 1)
  409. num_links++;
  410. /* idisp HDMI */
  411. num_links += ctx->hdmi_num;
  412. /* speaker amp */
  413. if (ctx->amp_type != CODEC_NONE)
  414. num_links++;
  415. /* BT audio offload */
  416. if (ctx->bt_offload_present)
  417. num_links++;
  418. /* HDMI-In */
  419. num_links += hweight32(ctx->ssp_mask_hdmi_in);
  420. /* HDA external codec */
  421. if (ctx->hda_codec_present)
  422. num_links += 2;
  423. return num_links;
  424. }
  425. int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
  426. struct sof_card_private *ctx)
  427. {
  428. struct snd_soc_dai_link *links;
  429. int num_links;
  430. int i;
  431. int idx = 0;
  432. int ret;
  433. int ssp_hdmi_in = 0;
  434. unsigned long link_order, link;
  435. unsigned long link_ids, be_id;
  436. num_links = calculate_num_links(ctx);
  437. links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link),
  438. GFP_KERNEL);
  439. if (!links)
  440. return -ENOMEM;
  441. if (ctx->link_order_overwrite)
  442. link_order = ctx->link_order_overwrite;
  443. else
  444. link_order = DEFAULT_LINK_ORDER;
  445. if (ctx->link_id_overwrite)
  446. link_ids = ctx->link_id_overwrite;
  447. else
  448. link_ids = 0;
  449. dev_dbg(dev, "create dai links, link_order 0x%lx, id_overwrite 0x%lx\n",
  450. link_order, link_ids);
  451. while (link_order) {
  452. link = link_order & SOF_LINK_ORDER_MASK;
  453. link_order >>= SOF_LINK_ORDER_SHIFT;
  454. if (ctx->link_id_overwrite) {
  455. be_id = link_ids & SOF_LINK_IDS_MASK;
  456. link_ids >>= SOF_LINK_IDS_SHIFT;
  457. } else {
  458. /* use array index as link id */
  459. be_id = idx;
  460. }
  461. switch (link) {
  462. case SOF_LINK_CODEC:
  463. /* headphone codec */
  464. if (ctx->codec_type == CODEC_NONE)
  465. continue;
  466. ret = set_ssp_codec_link(dev, &links[idx], be_id,
  467. ctx->codec_type, ctx->ssp_codec);
  468. if (ret) {
  469. dev_err(dev, "fail to set codec link, ret %d\n",
  470. ret);
  471. return ret;
  472. }
  473. ctx->codec_link = &links[idx];
  474. idx++;
  475. break;
  476. case SOF_LINK_DMIC01:
  477. /* dmic01 */
  478. if (ctx->dmic_be_num == 0)
  479. continue;
  480. /* at least we have dmic01 */
  481. ret = set_dmic_link(dev, &links[idx], be_id, SOF_DMIC_01);
  482. if (ret) {
  483. dev_err(dev, "fail to set dmic01 link, ret %d\n",
  484. ret);
  485. return ret;
  486. }
  487. idx++;
  488. break;
  489. case SOF_LINK_DMIC16K:
  490. /* dmic16k */
  491. if (ctx->dmic_be_num <= 1)
  492. continue;
  493. /* set up 2 BE links at most */
  494. ret = set_dmic_link(dev, &links[idx], be_id,
  495. SOF_DMIC_16K);
  496. if (ret) {
  497. dev_err(dev, "fail to set dmic16k link, ret %d\n",
  498. ret);
  499. return ret;
  500. }
  501. idx++;
  502. break;
  503. case SOF_LINK_IDISP_HDMI:
  504. /* idisp HDMI */
  505. for (i = 1; i <= ctx->hdmi_num; i++) {
  506. ret = set_idisp_hdmi_link(dev, &links[idx],
  507. be_id, i,
  508. ctx->hdmi.idisp_codec);
  509. if (ret) {
  510. dev_err(dev, "fail to set hdmi link, ret %d\n",
  511. ret);
  512. return ret;
  513. }
  514. idx++;
  515. be_id++;
  516. }
  517. break;
  518. case SOF_LINK_AMP:
  519. /* speaker amp */
  520. if (ctx->amp_type == CODEC_NONE)
  521. continue;
  522. ret = set_ssp_amp_link(dev, &links[idx], be_id,
  523. ctx->amp_type, ctx->ssp_amp);
  524. if (ret) {
  525. dev_err(dev, "fail to set amp link, ret %d\n",
  526. ret);
  527. return ret;
  528. }
  529. ctx->amp_link = &links[idx];
  530. idx++;
  531. break;
  532. case SOF_LINK_BT_OFFLOAD:
  533. /* BT audio offload */
  534. if (!ctx->bt_offload_present)
  535. continue;
  536. ret = set_bt_offload_link(dev, &links[idx], be_id,
  537. ctx->ssp_bt);
  538. if (ret) {
  539. dev_err(dev, "fail to set bt link, ret %d\n",
  540. ret);
  541. return ret;
  542. }
  543. idx++;
  544. break;
  545. case SOF_LINK_HDMI_IN:
  546. /* HDMI-In */
  547. for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) {
  548. ret = set_hdmi_in_link(dev, &links[idx], be_id,
  549. ssp_hdmi_in);
  550. if (ret) {
  551. dev_err(dev, "fail to set hdmi-in link, ret %d\n",
  552. ret);
  553. return ret;
  554. }
  555. idx++;
  556. be_id++;
  557. }
  558. break;
  559. case SOF_LINK_HDA:
  560. /* HDA external codec */
  561. if (!ctx->hda_codec_present)
  562. continue;
  563. ret = set_hda_codec_link(dev, &links[idx], be_id,
  564. SOF_HDA_ANALOG);
  565. if (ret) {
  566. dev_err(dev, "fail to set hda analog link, ret %d\n",
  567. ret);
  568. return ret;
  569. }
  570. idx++;
  571. be_id++;
  572. ret = set_hda_codec_link(dev, &links[idx], be_id,
  573. SOF_HDA_DIGITAL);
  574. if (ret) {
  575. dev_err(dev, "fail to set hda digital link, ret %d\n",
  576. ret);
  577. return ret;
  578. }
  579. idx++;
  580. break;
  581. case SOF_LINK_NONE:
  582. /* caught here if it's not used as terminator in macro */
  583. fallthrough;
  584. default:
  585. dev_err(dev, "invalid link type %ld\n", link);
  586. return -EINVAL;
  587. }
  588. }
  589. if (idx != num_links) {
  590. dev_err(dev, "link number mismatch, idx %d, num_links %d\n", idx,
  591. num_links);
  592. return -EINVAL;
  593. }
  594. card->dai_link = links;
  595. card->num_links = num_links;
  596. return 0;
  597. }
  598. EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
  599. struct sof_card_private *
  600. sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk)
  601. {
  602. struct sof_card_private *ctx;
  603. dev_dbg(dev, "create ctx, board_quirk 0x%lx\n", board_quirk);
  604. ctx = devm_kzalloc(dev, sizeof(struct sof_card_private), GFP_KERNEL);
  605. if (!ctx)
  606. return NULL;
  607. ctx->codec_type = snd_soc_acpi_intel_detect_codec_type(dev);
  608. ctx->amp_type = snd_soc_acpi_intel_detect_amp_type(dev);
  609. ctx->dmic_be_num = 2;
  610. ctx->hdmi_num = (board_quirk & SOF_NUM_IDISP_HDMI_MASK) >>
  611. SOF_NUM_IDISP_HDMI_SHIFT;
  612. /* default number of HDMI DAI's */
  613. if (!ctx->hdmi_num)
  614. ctx->hdmi_num = 3;
  615. /* port number/mask of peripherals attached to ssp interface */
  616. if (ctx->codec_type != CODEC_NONE)
  617. ctx->ssp_codec = (board_quirk & SOF_SSP_PORT_CODEC_MASK) >>
  618. SOF_SSP_PORT_CODEC_SHIFT;
  619. if (ctx->amp_type != CODEC_NONE)
  620. ctx->ssp_amp = (board_quirk & SOF_SSP_PORT_AMP_MASK) >>
  621. SOF_SSP_PORT_AMP_SHIFT;
  622. if (board_quirk & SOF_BT_OFFLOAD_PRESENT) {
  623. ctx->bt_offload_present = true;
  624. ctx->ssp_bt = (board_quirk & SOF_SSP_PORT_BT_OFFLOAD_MASK) >>
  625. SOF_SSP_PORT_BT_OFFLOAD_SHIFT;
  626. }
  627. ctx->ssp_mask_hdmi_in = (board_quirk & SOF_SSP_MASK_HDMI_CAPTURE_MASK) >>
  628. SOF_SSP_MASK_HDMI_CAPTURE_SHIFT;
  629. return ctx;
  630. }
  631. EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, SND_SOC_INTEL_SOF_BOARD_HELPERS);
  632. MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers");
  633. MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
  634. MODULE_LICENSE("GPL");
  635. MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
  636. MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH);