sof_sdw.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. // Copyright (c) 2020 Intel Corporation
  3. /*
  4. * sof_sdw - ASOC Machine driver for Intel SoundWire platforms
  5. */
  6. #include <linux/acpi.h>
  7. #include <linux/bitmap.h>
  8. #include <linux/device.h>
  9. #include <linux/dmi.h>
  10. #include <linux/module.h>
  11. #include <linux/soundwire/sdw.h>
  12. #include <linux/soundwire/sdw_type.h>
  13. #include <linux/soundwire/sdw_intel.h>
  14. #include <sound/core.h>
  15. #include <sound/soc-acpi.h>
  16. #include "sof_sdw_common.h"
  17. #include "../../codecs/rt711.h"
  18. static unsigned long sof_sdw_quirk = RT711_JD1;
  19. static int quirk_override = -1;
  20. module_param_named(quirk, quirk_override, int, 0444);
  21. MODULE_PARM_DESC(quirk, "Board-specific quirk override");
  22. #define DMIC_DEFAULT_CHANNELS 2
  23. static void log_quirks(struct device *dev)
  24. {
  25. if (SOC_SDW_JACK_JDSRC(sof_sdw_quirk))
  26. dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
  27. SOC_SDW_JACK_JDSRC(sof_sdw_quirk));
  28. if (sof_sdw_quirk & SOC_SDW_FOUR_SPK)
  29. dev_err(dev, "quirk SOC_SDW_FOUR_SPK enabled but no longer supported\n");
  30. if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
  31. dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n");
  32. if (sof_sdw_quirk & SOC_SDW_PCH_DMIC)
  33. dev_dbg(dev, "quirk SOC_SDW_PCH_DMIC enabled\n");
  34. if (SOF_SSP_GET_PORT(sof_sdw_quirk))
  35. dev_dbg(dev, "SSP port %ld\n",
  36. SOF_SSP_GET_PORT(sof_sdw_quirk));
  37. if (sof_sdw_quirk & SOC_SDW_NO_AGGREGATION)
  38. dev_err(dev, "quirk SOC_SDW_NO_AGGREGATION enabled but no longer supported\n");
  39. if (sof_sdw_quirk & SOC_SDW_CODEC_SPKR)
  40. dev_dbg(dev, "quirk SOC_SDW_CODEC_SPKR enabled\n");
  41. if (sof_sdw_quirk & SOC_SDW_SIDECAR_AMPS)
  42. dev_dbg(dev, "quirk SOC_SDW_SIDECAR_AMPS enabled\n");
  43. }
  44. static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
  45. {
  46. sof_sdw_quirk = (unsigned long)id->driver_data;
  47. return 1;
  48. }
  49. static const struct dmi_system_id sof_sdw_quirk_table[] = {
  50. /* CometLake devices */
  51. {
  52. .callback = sof_sdw_quirk_cb,
  53. .matches = {
  54. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  55. DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
  56. },
  57. .driver_data = (void *)SOC_SDW_PCH_DMIC,
  58. },
  59. {
  60. .callback = sof_sdw_quirk_cb,
  61. .matches = {
  62. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  63. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
  64. },
  65. .driver_data = (void *)RT711_JD2,
  66. },
  67. {
  68. /* early version of SKU 09C6 */
  69. .callback = sof_sdw_quirk_cb,
  70. .matches = {
  71. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  72. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
  73. },
  74. .driver_data = (void *)RT711_JD2,
  75. },
  76. {
  77. .callback = sof_sdw_quirk_cb,
  78. .matches = {
  79. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  80. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
  81. },
  82. .driver_data = (void *)(RT711_JD2),
  83. },
  84. {
  85. .callback = sof_sdw_quirk_cb,
  86. .matches = {
  87. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  88. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
  89. },
  90. .driver_data = (void *)(RT711_JD2),
  91. },
  92. /* IceLake devices */
  93. {
  94. .callback = sof_sdw_quirk_cb,
  95. .matches = {
  96. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  97. DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
  98. },
  99. .driver_data = (void *)SOC_SDW_PCH_DMIC,
  100. },
  101. /* TigerLake devices */
  102. {
  103. .callback = sof_sdw_quirk_cb,
  104. .matches = {
  105. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  106. DMI_MATCH(DMI_PRODUCT_NAME,
  107. "Tiger Lake Client Platform"),
  108. },
  109. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  110. RT711_JD1 |
  111. SOC_SDW_PCH_DMIC |
  112. SOF_SSP_PORT(SOF_I2S_SSP2)),
  113. },
  114. {
  115. .callback = sof_sdw_quirk_cb,
  116. .matches = {
  117. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  118. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
  119. },
  120. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  121. RT711_JD2),
  122. },
  123. {
  124. /* another SKU of Dell Latitude 9520 */
  125. .callback = sof_sdw_quirk_cb,
  126. .matches = {
  127. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  128. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3F")
  129. },
  130. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  131. RT711_JD2),
  132. },
  133. {
  134. /* Dell XPS 9710 */
  135. .callback = sof_sdw_quirk_cb,
  136. .matches = {
  137. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  138. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D")
  139. },
  140. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  141. RT711_JD2),
  142. },
  143. {
  144. .callback = sof_sdw_quirk_cb,
  145. .matches = {
  146. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  147. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
  148. },
  149. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  150. RT711_JD2),
  151. },
  152. {
  153. .callback = sof_sdw_quirk_cb,
  154. .matches = {
  155. DMI_MATCH(DMI_SYS_VENDOR, "Google"),
  156. DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
  157. },
  158. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  159. SOC_SDW_PCH_DMIC |
  160. SOF_BT_OFFLOAD_SSP(2) |
  161. SOF_SSP_BT_OFFLOAD_PRESENT),
  162. },
  163. {
  164. .callback = sof_sdw_quirk_cb,
  165. .matches = {
  166. DMI_MATCH(DMI_SYS_VENDOR, "Google"),
  167. DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
  168. },
  169. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  170. SOC_SDW_PCH_DMIC),
  171. },
  172. {
  173. /*
  174. * this entry covers multiple HP SKUs. The family name
  175. * does not seem robust enough, so we use a partial
  176. * match that ignores the product name suffix
  177. * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
  178. */
  179. .callback = sof_sdw_quirk_cb,
  180. .matches = {
  181. DMI_MATCH(DMI_SYS_VENDOR, "HP"),
  182. DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"),
  183. },
  184. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  185. SOC_SDW_PCH_DMIC |
  186. RT711_JD1),
  187. },
  188. {
  189. /*
  190. * this entry covers HP Spectre x360 where the DMI information
  191. * changed somehow
  192. */
  193. .callback = sof_sdw_quirk_cb,
  194. .matches = {
  195. DMI_MATCH(DMI_SYS_VENDOR, "HP"),
  196. DMI_MATCH(DMI_BOARD_NAME, "8709"),
  197. },
  198. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  199. SOC_SDW_PCH_DMIC |
  200. RT711_JD1),
  201. },
  202. {
  203. /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
  204. .callback = sof_sdw_quirk_cb,
  205. .matches = {
  206. DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
  207. DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
  208. },
  209. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  210. SOC_SDW_PCH_DMIC |
  211. RT711_JD1),
  212. },
  213. {
  214. /* NUC15 LAPBC710 skews */
  215. .callback = sof_sdw_quirk_cb,
  216. .matches = {
  217. DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
  218. DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"),
  219. },
  220. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  221. SOC_SDW_PCH_DMIC |
  222. RT711_JD1),
  223. },
  224. {
  225. /* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */
  226. .callback = sof_sdw_quirk_cb,
  227. .matches = {
  228. DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
  229. DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"),
  230. },
  231. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  232. SOC_SDW_PCH_DMIC |
  233. RT711_JD2_100K),
  234. },
  235. {
  236. /* NUC15 LAPRC710 skews */
  237. .callback = sof_sdw_quirk_cb,
  238. .matches = {
  239. DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
  240. DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"),
  241. },
  242. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  243. SOC_SDW_PCH_DMIC |
  244. RT711_JD2_100K),
  245. },
  246. /* TigerLake-SDCA devices */
  247. {
  248. .callback = sof_sdw_quirk_cb,
  249. .matches = {
  250. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  251. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
  252. },
  253. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  254. RT711_JD2),
  255. },
  256. {
  257. .callback = sof_sdw_quirk_cb,
  258. .matches = {
  259. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  260. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45")
  261. },
  262. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  263. RT711_JD2),
  264. },
  265. /* AlderLake devices */
  266. {
  267. .callback = sof_sdw_quirk_cb,
  268. .matches = {
  269. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  270. DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
  271. },
  272. .driver_data = (void *)(RT711_JD2_100K |
  273. SOF_SDW_TGL_HDMI |
  274. SOF_BT_OFFLOAD_SSP(2) |
  275. SOF_SSP_BT_OFFLOAD_PRESENT),
  276. },
  277. {
  278. .callback = sof_sdw_quirk_cb,
  279. .matches = {
  280. DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
  281. DMI_MATCH(DMI_PRODUCT_SKU, "0000000000070000"),
  282. },
  283. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  284. RT711_JD2_100K),
  285. },
  286. {
  287. .callback = sof_sdw_quirk_cb,
  288. .matches = {
  289. DMI_MATCH(DMI_SYS_VENDOR, "Google"),
  290. DMI_MATCH(DMI_PRODUCT_NAME, "Brya"),
  291. },
  292. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  293. SOC_SDW_PCH_DMIC |
  294. SOF_BT_OFFLOAD_SSP(2) |
  295. SOF_SSP_BT_OFFLOAD_PRESENT),
  296. },
  297. {
  298. .callback = sof_sdw_quirk_cb,
  299. .matches = {
  300. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  301. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF0")
  302. },
  303. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  304. RT711_JD2),
  305. },
  306. {
  307. .callback = sof_sdw_quirk_cb,
  308. .matches = {
  309. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  310. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF3"),
  311. },
  312. /* No Jack */
  313. .driver_data = (void *)(SOF_SDW_TGL_HDMI),
  314. },
  315. {
  316. .callback = sof_sdw_quirk_cb,
  317. .matches = {
  318. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  319. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE")
  320. },
  321. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  322. RT711_JD2),
  323. },
  324. {
  325. .callback = sof_sdw_quirk_cb,
  326. .matches = {
  327. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  328. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF")
  329. },
  330. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  331. RT711_JD2),
  332. },
  333. {
  334. .callback = sof_sdw_quirk_cb,
  335. .matches = {
  336. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  337. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00")
  338. },
  339. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  340. RT711_JD2),
  341. },
  342. {
  343. .callback = sof_sdw_quirk_cb,
  344. .matches = {
  345. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  346. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01")
  347. },
  348. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  349. RT711_JD2),
  350. },
  351. {
  352. .callback = sof_sdw_quirk_cb,
  353. .matches = {
  354. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  355. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B11")
  356. },
  357. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  358. RT711_JD2),
  359. },
  360. {
  361. .callback = sof_sdw_quirk_cb,
  362. .matches = {
  363. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  364. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B12")
  365. },
  366. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  367. RT711_JD2),
  368. },
  369. {
  370. .callback = sof_sdw_quirk_cb,
  371. .matches = {
  372. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  373. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B13"),
  374. },
  375. /* No Jack */
  376. .driver_data = (void *)SOF_SDW_TGL_HDMI,
  377. },
  378. {
  379. .callback = sof_sdw_quirk_cb,
  380. .matches = {
  381. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  382. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B14"),
  383. },
  384. /* No Jack */
  385. .driver_data = (void *)SOF_SDW_TGL_HDMI,
  386. },
  387. {
  388. .callback = sof_sdw_quirk_cb,
  389. .matches = {
  390. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  391. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B29"),
  392. },
  393. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  394. RT711_JD2),
  395. },
  396. {
  397. .callback = sof_sdw_quirk_cb,
  398. .matches = {
  399. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  400. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B34"),
  401. },
  402. /* No Jack */
  403. .driver_data = (void *)SOF_SDW_TGL_HDMI,
  404. },
  405. {
  406. .callback = sof_sdw_quirk_cb,
  407. .matches = {
  408. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  409. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B8C"),
  410. },
  411. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  412. RT711_JD2),
  413. },
  414. {
  415. .callback = sof_sdw_quirk_cb,
  416. .matches = {
  417. DMI_MATCH(DMI_SYS_VENDOR, "HP"),
  418. DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16"),
  419. },
  420. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  421. RT711_JD2),
  422. },
  423. /* RaptorLake devices */
  424. {
  425. .callback = sof_sdw_quirk_cb,
  426. .matches = {
  427. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  428. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0BDA")
  429. },
  430. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  431. RT711_JD2),
  432. },
  433. {
  434. .callback = sof_sdw_quirk_cb,
  435. .matches = {
  436. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  437. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C0F")
  438. },
  439. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  440. RT711_JD2),
  441. },
  442. {
  443. .callback = sof_sdw_quirk_cb,
  444. .matches = {
  445. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  446. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C10"),
  447. },
  448. /* No Jack */
  449. .driver_data = (void *)(SOF_SDW_TGL_HDMI),
  450. },
  451. {
  452. .callback = sof_sdw_quirk_cb,
  453. .matches = {
  454. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  455. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C11")
  456. },
  457. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  458. RT711_JD2),
  459. },
  460. {
  461. .callback = sof_sdw_quirk_cb,
  462. .matches = {
  463. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  464. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C40")
  465. },
  466. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  467. RT711_JD2),
  468. },
  469. {
  470. .callback = sof_sdw_quirk_cb,
  471. .matches = {
  472. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  473. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C4F")
  474. },
  475. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  476. RT711_JD2),
  477. },
  478. {
  479. .callback = sof_sdw_quirk_cb,
  480. .matches = {
  481. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  482. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF9")
  483. },
  484. .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
  485. },
  486. /* MeteorLake devices */
  487. {
  488. .callback = sof_sdw_quirk_cb,
  489. .matches = {
  490. DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_mtlrvp"),
  491. },
  492. .driver_data = (void *)(RT711_JD1),
  493. },
  494. {
  495. .callback = sof_sdw_quirk_cb,
  496. .matches = {
  497. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  498. DMI_MATCH(DMI_PRODUCT_NAME, "Meteor Lake Client Platform"),
  499. },
  500. .driver_data = (void *)(RT711_JD2_100K),
  501. },
  502. {
  503. .callback = sof_sdw_quirk_cb,
  504. .matches = {
  505. DMI_MATCH(DMI_SYS_VENDOR, "Google"),
  506. DMI_MATCH(DMI_PRODUCT_NAME, "Rex"),
  507. },
  508. .driver_data = (void *)(SOC_SDW_PCH_DMIC |
  509. SOF_BT_OFFLOAD_SSP(1) |
  510. SOF_SSP_BT_OFFLOAD_PRESENT),
  511. },
  512. {
  513. .callback = sof_sdw_quirk_cb,
  514. .matches = {
  515. DMI_MATCH(DMI_SYS_VENDOR, "HP"),
  516. DMI_MATCH(DMI_PRODUCT_NAME, "OMEN Transcend Gaming Laptop"),
  517. },
  518. .driver_data = (void *)(RT711_JD2),
  519. },
  520. /* LunarLake devices */
  521. {
  522. .callback = sof_sdw_quirk_cb,
  523. .matches = {
  524. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  525. DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"),
  526. },
  527. .driver_data = (void *)(RT711_JD2),
  528. },
  529. {
  530. .callback = sof_sdw_quirk_cb,
  531. .matches = {
  532. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  533. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE3")
  534. },
  535. .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
  536. },
  537. {
  538. .callback = sof_sdw_quirk_cb,
  539. .matches = {
  540. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  541. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE4")
  542. },
  543. .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
  544. },
  545. {
  546. .callback = sof_sdw_quirk_cb,
  547. .matches = {
  548. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  549. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDB")
  550. },
  551. .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
  552. },
  553. {
  554. .callback = sof_sdw_quirk_cb,
  555. .matches = {
  556. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  557. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDC")
  558. },
  559. .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
  560. },
  561. {
  562. .callback = sof_sdw_quirk_cb,
  563. .matches = {
  564. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  565. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDD")
  566. },
  567. .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
  568. },
  569. {
  570. .callback = sof_sdw_quirk_cb,
  571. .matches = {
  572. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  573. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF8")
  574. },
  575. .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
  576. },
  577. {
  578. .callback = sof_sdw_quirk_cb,
  579. .matches = {
  580. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  581. DMI_MATCH(DMI_PRODUCT_NAME, "83JX")
  582. },
  583. .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
  584. },
  585. {
  586. .callback = sof_sdw_quirk_cb,
  587. .matches = {
  588. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  589. DMI_MATCH(DMI_PRODUCT_NAME, "83LC")
  590. },
  591. .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
  592. },
  593. {
  594. .callback = sof_sdw_quirk_cb,
  595. .matches = {
  596. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  597. DMI_MATCH(DMI_PRODUCT_NAME, "83MC")
  598. },
  599. .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
  600. }, {
  601. .callback = sof_sdw_quirk_cb,
  602. .matches = {
  603. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  604. DMI_MATCH(DMI_PRODUCT_NAME, "83NM")
  605. },
  606. .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
  607. },
  608. {
  609. .callback = sof_sdw_quirk_cb,
  610. .matches = {
  611. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  612. DMI_MATCH(DMI_PRODUCT_NAME, "83HM")
  613. },
  614. .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS |
  615. SOC_SDW_CODEC_MIC),
  616. },
  617. {
  618. .callback = sof_sdw_quirk_cb,
  619. .matches = {
  620. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  621. DMI_MATCH(DMI_PRODUCT_NAME, "21QB")
  622. },
  623. /* Note this quirk excludes the CODEC mic */
  624. .driver_data = (void *)(SOC_SDW_CODEC_MIC),
  625. },
  626. {
  627. .callback = sof_sdw_quirk_cb,
  628. .matches = {
  629. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  630. DMI_MATCH(DMI_PRODUCT_NAME, "21QA")
  631. },
  632. /* Note this quirk excludes the CODEC mic */
  633. .driver_data = (void *)(SOC_SDW_CODEC_MIC),
  634. },
  635. {
  636. .callback = sof_sdw_quirk_cb,
  637. .matches = {
  638. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  639. DMI_MATCH(DMI_PRODUCT_NAME, "21Q6")
  640. },
  641. .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
  642. },
  643. {
  644. .callback = sof_sdw_quirk_cb,
  645. .matches = {
  646. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  647. DMI_MATCH(DMI_PRODUCT_NAME, "21Q7")
  648. },
  649. .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
  650. },
  651. /* ArrowLake devices */
  652. {
  653. .callback = sof_sdw_quirk_cb,
  654. .matches = {
  655. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  656. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE8")
  657. },
  658. .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
  659. },
  660. {
  661. .callback = sof_sdw_quirk_cb,
  662. .matches = {
  663. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  664. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF1")
  665. },
  666. .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
  667. },
  668. {
  669. .callback = sof_sdw_quirk_cb,
  670. .matches = {
  671. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  672. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF7")
  673. },
  674. .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
  675. },
  676. {}
  677. };
  678. static const struct snd_pci_quirk sof_sdw_ssid_quirk_table[] = {
  679. SND_PCI_QUIRK(0x1043, 0x1e13, "ASUS Zenbook S14", SOC_SDW_CODEC_MIC),
  680. SND_PCI_QUIRK(0x1043, 0x1f43, "ASUS Zenbook S16", SOC_SDW_CODEC_MIC),
  681. {}
  682. };
  683. static void sof_sdw_check_ssid_quirk(const struct snd_soc_acpi_mach *mach)
  684. {
  685. const struct snd_pci_quirk *quirk_entry;
  686. quirk_entry = snd_pci_quirk_lookup_id(mach->mach_params.subsystem_vendor,
  687. mach->mach_params.subsystem_device,
  688. sof_sdw_ssid_quirk_table);
  689. if (quirk_entry)
  690. sof_sdw_quirk = quirk_entry->value;
  691. }
  692. static struct snd_soc_dai_link_component platform_component[] = {
  693. {
  694. /* name might be overridden during probe */
  695. .name = "0000:00:1f.3"
  696. }
  697. };
  698. static const struct snd_soc_ops sdw_ops = {
  699. .startup = asoc_sdw_startup,
  700. .prepare = asoc_sdw_prepare,
  701. .trigger = asoc_sdw_trigger,
  702. .hw_params = asoc_sdw_hw_params,
  703. .hw_free = asoc_sdw_hw_free,
  704. .shutdown = asoc_sdw_shutdown,
  705. };
  706. static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
  707. static int create_sdw_dailink(struct snd_soc_card *card,
  708. struct asoc_sdw_dailink *sof_dai,
  709. struct snd_soc_dai_link **dai_links,
  710. int *be_id, struct snd_soc_codec_conf **codec_conf)
  711. {
  712. struct device *dev = card->dev;
  713. struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
  714. struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
  715. struct asoc_sdw_endpoint *sof_end;
  716. int stream;
  717. int ret;
  718. list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
  719. if (sof_end->name_prefix) {
  720. (*codec_conf)->dlc.name = sof_end->codec_name;
  721. (*codec_conf)->name_prefix = sof_end->name_prefix;
  722. (*codec_conf)++;
  723. }
  724. if (sof_end->include_sidecar && sof_end->codec_info->add_sidecar) {
  725. ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf);
  726. if (ret)
  727. return ret;
  728. }
  729. }
  730. for_each_pcm_streams(stream) {
  731. static const char * const sdw_stream_name[] = {
  732. "SDW%d-Playback",
  733. "SDW%d-Capture",
  734. "SDW%d-Playback-%s",
  735. "SDW%d-Capture-%s",
  736. };
  737. struct snd_soc_dai_link_ch_map *codec_maps;
  738. struct snd_soc_dai_link_component *codecs;
  739. struct snd_soc_dai_link_component *cpus;
  740. int num_cpus = hweight32(sof_dai->link_mask[stream]);
  741. int num_codecs = sof_dai->num_devs[stream];
  742. int playback, capture;
  743. int cur_link = 0;
  744. int i = 0, j = 0;
  745. char *name;
  746. if (!sof_dai->num_devs[stream])
  747. continue;
  748. sof_end = list_first_entry(&sof_dai->endpoints,
  749. struct asoc_sdw_endpoint, list);
  750. *be_id = sof_end->dai_info->dailink[stream];
  751. if (*be_id < 0) {
  752. dev_err(dev, "Invalid dailink id %d\n", *be_id);
  753. return -EINVAL;
  754. }
  755. /* create stream name according to first link id */
  756. if (ctx->append_dai_type)
  757. name = devm_kasprintf(dev, GFP_KERNEL,
  758. sdw_stream_name[stream + 2],
  759. ffs(sof_end->link_mask) - 1,
  760. type_strings[sof_end->dai_info->dai_type]);
  761. else
  762. name = devm_kasprintf(dev, GFP_KERNEL,
  763. sdw_stream_name[stream],
  764. ffs(sof_end->link_mask) - 1);
  765. if (!name)
  766. return -ENOMEM;
  767. cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL);
  768. if (!cpus)
  769. return -ENOMEM;
  770. codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL);
  771. if (!codecs)
  772. return -ENOMEM;
  773. codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL);
  774. if (!codec_maps)
  775. return -ENOMEM;
  776. list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
  777. if (!sof_end->dai_info->direction[stream])
  778. continue;
  779. if (cur_link != sof_end->link_mask) {
  780. int link_num = ffs(sof_end->link_mask) - 1;
  781. int pin_num = intel_ctx->sdw_pin_index[link_num]++;
  782. cur_link = sof_end->link_mask;
  783. cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL,
  784. "SDW%d Pin%d",
  785. link_num, pin_num);
  786. if (!cpus[i].dai_name)
  787. return -ENOMEM;
  788. i++;
  789. }
  790. codec_maps[j].cpu = i - 1;
  791. codec_maps[j].codec = j;
  792. codecs[j].name = sof_end->codec_name;
  793. codecs[j].dai_name = sof_end->dai_info->dai_name;
  794. j++;
  795. }
  796. WARN_ON(i != num_cpus || j != num_codecs);
  797. playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
  798. capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
  799. asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
  800. cpus, num_cpus, platform_component,
  801. ARRAY_SIZE(platform_component), codecs, num_codecs,
  802. asoc_sdw_rtd_init, &sdw_ops);
  803. /*
  804. * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
  805. * based on wait_for_completion(), tag them as 'nonatomic'.
  806. */
  807. (*dai_links)->nonatomic = true;
  808. (*dai_links)->ch_maps = codec_maps;
  809. list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
  810. if (sof_end->dai_info->init)
  811. sof_end->dai_info->init(card, *dai_links,
  812. sof_end->codec_info,
  813. playback);
  814. }
  815. (*dai_links)++;
  816. }
  817. return 0;
  818. }
  819. static int create_sdw_dailinks(struct snd_soc_card *card,
  820. struct snd_soc_dai_link **dai_links, int *be_id,
  821. struct asoc_sdw_dailink *sof_dais,
  822. struct snd_soc_codec_conf **codec_conf)
  823. {
  824. struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
  825. struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
  826. int ret, i;
  827. for (i = 0; i < SDW_INTEL_MAX_LINKS; i++)
  828. intel_ctx->sdw_pin_index[i] = SOC_SDW_INTEL_BIDIR_PDI_BASE;
  829. /* generate DAI links by each sdw link */
  830. while (sof_dais->initialised) {
  831. int current_be_id = 0;
  832. ret = create_sdw_dailink(card, sof_dais, dai_links,
  833. &current_be_id, codec_conf);
  834. if (ret)
  835. return ret;
  836. /* Update the be_id to match the highest ID used for SDW link */
  837. if (*be_id < current_be_id)
  838. *be_id = current_be_id;
  839. sof_dais++;
  840. }
  841. return 0;
  842. }
  843. static int create_ssp_dailinks(struct snd_soc_card *card,
  844. struct snd_soc_dai_link **dai_links, int *be_id,
  845. struct asoc_sdw_codec_info *ssp_info,
  846. unsigned long ssp_mask)
  847. {
  848. struct device *dev = card->dev;
  849. int i, j = 0;
  850. int ret;
  851. for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) {
  852. char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i);
  853. char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
  854. char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
  855. ssp_info->acpi_id, j++);
  856. if (!name || !cpu_dai_name || !codec_name)
  857. return -ENOMEM;
  858. int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK];
  859. int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE];
  860. ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
  861. playback, capture, cpu_dai_name,
  862. platform_component->name,
  863. ARRAY_SIZE(platform_component), codec_name,
  864. ssp_info->dais[0].dai_name, NULL,
  865. ssp_info->ops);
  866. if (ret)
  867. return ret;
  868. ret = ssp_info->dais[0].init(card, *dai_links, ssp_info, 0);
  869. if (ret < 0)
  870. return ret;
  871. (*dai_links)++;
  872. }
  873. return 0;
  874. }
  875. static int create_dmic_dailinks(struct snd_soc_card *card,
  876. struct snd_soc_dai_link **dai_links, int *be_id)
  877. {
  878. struct device *dev = card->dev;
  879. int ret;
  880. ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic01",
  881. 0, 1, // DMIC only supports capture
  882. "DMIC01 Pin", platform_component->name,
  883. ARRAY_SIZE(platform_component),
  884. "dmic-codec", "dmic-hifi",
  885. asoc_sdw_dmic_init, NULL);
  886. if (ret)
  887. return ret;
  888. (*dai_links)++;
  889. ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic16k",
  890. 0, 1, // DMIC only supports capture
  891. "DMIC16k Pin", platform_component->name,
  892. ARRAY_SIZE(platform_component),
  893. "dmic-codec", "dmic-hifi",
  894. /* don't call asoc_sdw_dmic_init() twice */
  895. NULL, NULL);
  896. if (ret)
  897. return ret;
  898. (*dai_links)++;
  899. return 0;
  900. }
  901. static int create_hdmi_dailinks(struct snd_soc_card *card,
  902. struct snd_soc_dai_link **dai_links, int *be_id,
  903. int hdmi_num)
  904. {
  905. struct device *dev = card->dev;
  906. struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
  907. struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
  908. int i, ret;
  909. for (i = 0; i < hdmi_num; i++) {
  910. char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1);
  911. char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1);
  912. if (!name || !cpu_dai_name)
  913. return -ENOMEM;
  914. char *codec_name, *codec_dai_name;
  915. if (intel_ctx->hdmi.idisp_codec) {
  916. codec_name = "ehdaudio0D2";
  917. codec_dai_name = devm_kasprintf(dev, GFP_KERNEL,
  918. "intel-hdmi-hifi%d", i + 1);
  919. } else {
  920. codec_name = "snd-soc-dummy";
  921. codec_dai_name = "snd-soc-dummy-dai";
  922. }
  923. if (!codec_dai_name)
  924. return -ENOMEM;
  925. ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
  926. 1, 0, // HDMI only supports playback
  927. cpu_dai_name, platform_component->name,
  928. ARRAY_SIZE(platform_component),
  929. codec_name, codec_dai_name,
  930. i == 0 ? sof_sdw_hdmi_init : NULL, NULL);
  931. if (ret)
  932. return ret;
  933. (*dai_links)++;
  934. }
  935. return 0;
  936. }
  937. static int create_bt_dailinks(struct snd_soc_card *card,
  938. struct snd_soc_dai_link **dai_links, int *be_id)
  939. {
  940. struct device *dev = card->dev;
  941. int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
  942. SOF_BT_OFFLOAD_SSP_SHIFT;
  943. char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
  944. char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port);
  945. if (!name || !cpu_dai_name)
  946. return -ENOMEM;
  947. int ret;
  948. ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
  949. 1, 1, cpu_dai_name, platform_component->name,
  950. ARRAY_SIZE(platform_component),
  951. snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name,
  952. NULL, NULL);
  953. if (ret)
  954. return ret;
  955. (*dai_links)++;
  956. return 0;
  957. }
  958. static int sof_card_dai_links_create(struct snd_soc_card *card)
  959. {
  960. struct device *dev = card->dev;
  961. struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
  962. int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0;
  963. struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
  964. struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
  965. struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
  966. struct snd_soc_codec_conf *codec_conf;
  967. struct asoc_sdw_codec_info *ssp_info;
  968. struct asoc_sdw_endpoint *sof_ends;
  969. struct asoc_sdw_dailink *sof_dais;
  970. int num_devs = 0;
  971. int num_ends = 0;
  972. struct snd_soc_dai_link *dai_links;
  973. int num_links;
  974. int be_id = 0;
  975. int hdmi_num;
  976. unsigned long ssp_mask;
  977. int ret;
  978. ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends);
  979. if (ret < 0) {
  980. dev_err(dev, "failed to count devices/endpoints: %d\n", ret);
  981. return ret;
  982. }
  983. /*
  984. * One per DAI link, worst case is a DAI link for every endpoint, also
  985. * add one additional to act as a terminator such that code can iterate
  986. * until it hits an uninitialised DAI.
  987. */
  988. sof_dais = kcalloc(num_ends + 1, sizeof(*sof_dais), GFP_KERNEL);
  989. if (!sof_dais)
  990. return -ENOMEM;
  991. /* One per endpoint, ie. each DAI on each codec/amp */
  992. sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL);
  993. if (!sof_ends) {
  994. ret = -ENOMEM;
  995. goto err_dai;
  996. }
  997. ret = asoc_sdw_parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs);
  998. if (ret < 0)
  999. goto err_end;
  1000. sdw_be_num = ret;
  1001. /*
  1002. * on generic tgl platform, I2S or sdw mode is supported
  1003. * based on board rework. A ACPI device is registered in
  1004. * system only when I2S mode is supported, not sdw mode.
  1005. * Here check ACPI ID to confirm I2S is supported.
  1006. */
  1007. ssp_info = asoc_sdw_find_codec_info_acpi(mach->id);
  1008. if (ssp_info) {
  1009. ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
  1010. ssp_num = hweight_long(ssp_mask);
  1011. }
  1012. if (mach_params->codec_mask & IDISP_CODEC_MASK)
  1013. intel_ctx->hdmi.idisp_codec = true;
  1014. if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
  1015. hdmi_num = SOF_TGL_HDMI_COUNT;
  1016. else
  1017. hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
  1018. /* enable dmic01 & dmic16k */
  1019. if (ctx->ignore_internal_dmic) {
  1020. dev_warn(dev, "Ignoring internal DMIC\n");
  1021. mach_params->dmic_num = 0;
  1022. } else if (mach_params->dmic_num) {
  1023. dmic_num = 2;
  1024. } else if (sof_sdw_quirk & SOC_SDW_PCH_DMIC) {
  1025. dmic_num = 2;
  1026. /*
  1027. * mach_params->dmic_num will be used to set the cfg-mics value of
  1028. * card->components string. Set it to the default value.
  1029. */
  1030. mach_params->dmic_num = DMIC_DEFAULT_CHANNELS;
  1031. }
  1032. if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
  1033. bt_num = 1;
  1034. dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n",
  1035. sdw_be_num, ssp_num, dmic_num,
  1036. intel_ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num);
  1037. codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
  1038. if (!codec_conf) {
  1039. ret = -ENOMEM;
  1040. goto err_end;
  1041. }
  1042. /* allocate BE dailinks */
  1043. num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num;
  1044. dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
  1045. if (!dai_links) {
  1046. ret = -ENOMEM;
  1047. goto err_end;
  1048. }
  1049. card->codec_conf = codec_conf;
  1050. card->num_configs = num_devs;
  1051. card->dai_link = dai_links;
  1052. card->num_links = num_links;
  1053. /* SDW */
  1054. if (sdw_be_num) {
  1055. ret = create_sdw_dailinks(card, &dai_links, &be_id,
  1056. sof_dais, &codec_conf);
  1057. if (ret)
  1058. goto err_end;
  1059. }
  1060. /* SSP */
  1061. if (ssp_num) {
  1062. ret = create_ssp_dailinks(card, &dai_links, &be_id,
  1063. ssp_info, ssp_mask);
  1064. if (ret)
  1065. goto err_end;
  1066. }
  1067. /* dmic */
  1068. if (dmic_num) {
  1069. ret = create_dmic_dailinks(card, &dai_links, &be_id);
  1070. if (ret)
  1071. goto err_end;
  1072. }
  1073. /* HDMI */
  1074. ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num);
  1075. if (ret)
  1076. goto err_end;
  1077. /* BT */
  1078. if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
  1079. ret = create_bt_dailinks(card, &dai_links, &be_id);
  1080. if (ret)
  1081. goto err_end;
  1082. }
  1083. WARN_ON(codec_conf != card->codec_conf + card->num_configs);
  1084. WARN_ON(dai_links != card->dai_link + card->num_links);
  1085. err_end:
  1086. kfree(sof_ends);
  1087. err_dai:
  1088. kfree(sof_dais);
  1089. return ret;
  1090. }
  1091. static int sof_sdw_card_late_probe(struct snd_soc_card *card)
  1092. {
  1093. struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
  1094. struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
  1095. int ret = 0;
  1096. ret = asoc_sdw_card_late_probe(card);
  1097. if (ret < 0)
  1098. return ret;
  1099. if (intel_ctx->hdmi.idisp_codec)
  1100. ret = sof_sdw_hdmi_card_late_probe(card);
  1101. return ret;
  1102. }
  1103. static int mc_probe(struct platform_device *pdev)
  1104. {
  1105. struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
  1106. struct snd_soc_card *card;
  1107. struct asoc_sdw_mc_private *ctx;
  1108. struct intel_mc_ctx *intel_ctx;
  1109. int amp_num = 0, i;
  1110. int ret;
  1111. dev_dbg(&pdev->dev, "Entry\n");
  1112. intel_ctx = devm_kzalloc(&pdev->dev, sizeof(*intel_ctx), GFP_KERNEL);
  1113. if (!intel_ctx)
  1114. return -ENOMEM;
  1115. ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
  1116. if (!ctx)
  1117. return -ENOMEM;
  1118. ctx->private = intel_ctx;
  1119. ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count();
  1120. card = &ctx->card;
  1121. card->dev = &pdev->dev;
  1122. card->name = "soundwire";
  1123. card->owner = THIS_MODULE;
  1124. card->late_probe = sof_sdw_card_late_probe;
  1125. snd_soc_card_set_drvdata(card, ctx);
  1126. if (mach->mach_params.subsystem_id_set) {
  1127. snd_soc_card_set_pci_ssid(card,
  1128. mach->mach_params.subsystem_vendor,
  1129. mach->mach_params.subsystem_device);
  1130. sof_sdw_check_ssid_quirk(mach);
  1131. }
  1132. dmi_check_system(sof_sdw_quirk_table);
  1133. if (quirk_override != -1) {
  1134. dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n",
  1135. sof_sdw_quirk, quirk_override);
  1136. sof_sdw_quirk = quirk_override;
  1137. }
  1138. log_quirks(card->dev);
  1139. ctx->mc_quirk = sof_sdw_quirk;
  1140. /* reset amp_num to ensure amp_num++ starts from 0 in each probe */
  1141. for (i = 0; i < ctx->codec_info_list_count; i++)
  1142. codec_info_list[i].amp_num = 0;
  1143. ret = sof_card_dai_links_create(card);
  1144. if (ret < 0)
  1145. return ret;
  1146. /*
  1147. * the default amp_num is zero for each codec and
  1148. * amp_num will only be increased for active amp
  1149. * codecs on used platform
  1150. */
  1151. for (i = 0; i < ctx->codec_info_list_count; i++)
  1152. amp_num += codec_info_list[i].amp_num;
  1153. card->components = devm_kasprintf(card->dev, GFP_KERNEL,
  1154. " cfg-amp:%d", amp_num);
  1155. if (!card->components)
  1156. return -ENOMEM;
  1157. if (mach->mach_params.dmic_num) {
  1158. card->components = devm_kasprintf(card->dev, GFP_KERNEL,
  1159. "%s mic:dmic cfg-mics:%d",
  1160. card->components,
  1161. mach->mach_params.dmic_num);
  1162. if (!card->components)
  1163. return -ENOMEM;
  1164. }
  1165. /* Register the card */
  1166. ret = devm_snd_soc_register_card(card->dev, card);
  1167. if (ret) {
  1168. dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret);
  1169. asoc_sdw_mc_dailink_exit_loop(card);
  1170. return ret;
  1171. }
  1172. platform_set_drvdata(pdev, card);
  1173. return ret;
  1174. }
  1175. static void mc_remove(struct platform_device *pdev)
  1176. {
  1177. struct snd_soc_card *card = platform_get_drvdata(pdev);
  1178. asoc_sdw_mc_dailink_exit_loop(card);
  1179. }
  1180. static const struct platform_device_id mc_id_table[] = {
  1181. { "sof_sdw", },
  1182. {}
  1183. };
  1184. MODULE_DEVICE_TABLE(platform, mc_id_table);
  1185. static struct platform_driver sof_sdw_driver = {
  1186. .driver = {
  1187. .name = "sof_sdw",
  1188. .pm = &snd_soc_pm_ops,
  1189. },
  1190. .probe = mc_probe,
  1191. .remove = mc_remove,
  1192. .id_table = mc_id_table,
  1193. };
  1194. module_platform_driver(sof_sdw_driver);
  1195. MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
  1196. MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
  1197. MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
  1198. MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
  1199. MODULE_LICENSE("GPL v2");
  1200. MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
  1201. MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);