sof_sdw.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630
  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/device.h>
  7. #include <linux/dmi.h>
  8. #include <linux/module.h>
  9. #include <linux/soundwire/sdw.h>
  10. #include <linux/soundwire/sdw_type.h>
  11. #include <sound/soc.h>
  12. #include <sound/soc-acpi.h>
  13. #include "sof_sdw_common.h"
  14. #include "../../codecs/rt711.h"
  15. unsigned long sof_sdw_quirk = RT711_JD1;
  16. static int quirk_override = -1;
  17. module_param_named(quirk, quirk_override, int, 0444);
  18. MODULE_PARM_DESC(quirk, "Board-specific quirk override");
  19. #define INC_ID(BE, CPU, LINK) do { (BE)++; (CPU)++; (LINK)++; } while (0)
  20. static void log_quirks(struct device *dev)
  21. {
  22. if (SOF_RT711_JDSRC(sof_sdw_quirk))
  23. dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
  24. SOF_RT711_JDSRC(sof_sdw_quirk));
  25. if (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
  26. dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n");
  27. if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
  28. dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n");
  29. if (sof_sdw_quirk & SOF_SDW_PCH_DMIC)
  30. dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n");
  31. if (SOF_SSP_GET_PORT(sof_sdw_quirk))
  32. dev_dbg(dev, "SSP port %ld\n",
  33. SOF_SSP_GET_PORT(sof_sdw_quirk));
  34. if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION)
  35. dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n");
  36. }
  37. static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
  38. {
  39. sof_sdw_quirk = (unsigned long)id->driver_data;
  40. return 1;
  41. }
  42. static const struct dmi_system_id sof_sdw_quirk_table[] = {
  43. /* CometLake devices */
  44. {
  45. .callback = sof_sdw_quirk_cb,
  46. .matches = {
  47. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  48. DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
  49. },
  50. .driver_data = (void *)SOF_SDW_PCH_DMIC,
  51. },
  52. {
  53. .callback = sof_sdw_quirk_cb,
  54. .matches = {
  55. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  56. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
  57. },
  58. .driver_data = (void *)RT711_JD2,
  59. },
  60. {
  61. /* early version of SKU 09C6 */
  62. .callback = sof_sdw_quirk_cb,
  63. .matches = {
  64. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  65. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
  66. },
  67. .driver_data = (void *)RT711_JD2,
  68. },
  69. {
  70. .callback = sof_sdw_quirk_cb,
  71. .matches = {
  72. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  73. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
  74. },
  75. .driver_data = (void *)(RT711_JD2 |
  76. SOF_SDW_FOUR_SPK),
  77. },
  78. {
  79. .callback = sof_sdw_quirk_cb,
  80. .matches = {
  81. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  82. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
  83. },
  84. .driver_data = (void *)(RT711_JD2 |
  85. SOF_SDW_FOUR_SPK),
  86. },
  87. /* IceLake devices */
  88. {
  89. .callback = sof_sdw_quirk_cb,
  90. .matches = {
  91. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  92. DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
  93. },
  94. .driver_data = (void *)SOF_SDW_PCH_DMIC,
  95. },
  96. /* TigerLake devices */
  97. {
  98. .callback = sof_sdw_quirk_cb,
  99. .matches = {
  100. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  101. DMI_MATCH(DMI_PRODUCT_NAME,
  102. "Tiger Lake Client Platform"),
  103. },
  104. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  105. RT711_JD1 |
  106. SOF_SDW_PCH_DMIC |
  107. SOF_SSP_PORT(SOF_I2S_SSP2)),
  108. },
  109. {
  110. .callback = sof_sdw_quirk_cb,
  111. .matches = {
  112. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  113. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
  114. },
  115. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  116. RT711_JD2),
  117. },
  118. {
  119. /* another SKU of Dell Latitude 9520 */
  120. .callback = sof_sdw_quirk_cb,
  121. .matches = {
  122. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  123. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3F")
  124. },
  125. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  126. RT711_JD2),
  127. },
  128. {
  129. /* Dell XPS 9710 */
  130. .callback = sof_sdw_quirk_cb,
  131. .matches = {
  132. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  133. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D")
  134. },
  135. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  136. RT711_JD2 |
  137. SOF_SDW_FOUR_SPK),
  138. },
  139. {
  140. .callback = sof_sdw_quirk_cb,
  141. .matches = {
  142. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  143. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
  144. },
  145. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  146. RT711_JD2 |
  147. SOF_SDW_FOUR_SPK),
  148. },
  149. {
  150. .callback = sof_sdw_quirk_cb,
  151. .matches = {
  152. DMI_MATCH(DMI_SYS_VENDOR, "Google"),
  153. DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
  154. },
  155. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  156. SOF_SDW_PCH_DMIC |
  157. SOF_SDW_FOUR_SPK |
  158. SOF_BT_OFFLOAD_SSP(2) |
  159. SOF_SSP_BT_OFFLOAD_PRESENT),
  160. },
  161. {
  162. .callback = sof_sdw_quirk_cb,
  163. .matches = {
  164. DMI_MATCH(DMI_SYS_VENDOR, "Google"),
  165. DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
  166. },
  167. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  168. SOF_SDW_PCH_DMIC |
  169. SOF_SDW_FOUR_SPK),
  170. },
  171. {
  172. /*
  173. * this entry covers multiple HP SKUs. The family name
  174. * does not seem robust enough, so we use a partial
  175. * match that ignores the product name suffix
  176. * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
  177. */
  178. .callback = sof_sdw_quirk_cb,
  179. .matches = {
  180. DMI_MATCH(DMI_SYS_VENDOR, "HP"),
  181. DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"),
  182. },
  183. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  184. SOF_SDW_PCH_DMIC |
  185. RT711_JD1),
  186. },
  187. {
  188. /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
  189. .callback = sof_sdw_quirk_cb,
  190. .matches = {
  191. DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
  192. DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
  193. },
  194. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  195. SOF_SDW_PCH_DMIC |
  196. RT711_JD1),
  197. },
  198. {
  199. /* NUC15 LAPBC710 skews */
  200. .callback = sof_sdw_quirk_cb,
  201. .matches = {
  202. DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
  203. DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"),
  204. },
  205. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  206. SOF_SDW_PCH_DMIC |
  207. RT711_JD1),
  208. },
  209. {
  210. /* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */
  211. .callback = sof_sdw_quirk_cb,
  212. .matches = {
  213. DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
  214. DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"),
  215. },
  216. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  217. SOF_SDW_PCH_DMIC |
  218. RT711_JD2_100K),
  219. },
  220. /* TigerLake-SDCA devices */
  221. {
  222. .callback = sof_sdw_quirk_cb,
  223. .matches = {
  224. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  225. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
  226. },
  227. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  228. RT711_JD2 |
  229. SOF_SDW_FOUR_SPK),
  230. },
  231. {
  232. .callback = sof_sdw_quirk_cb,
  233. .matches = {
  234. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  235. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45")
  236. },
  237. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  238. RT711_JD2),
  239. },
  240. /* AlderLake devices */
  241. {
  242. .callback = sof_sdw_quirk_cb,
  243. .matches = {
  244. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  245. DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
  246. },
  247. .driver_data = (void *)(RT711_JD2_100K |
  248. SOF_SDW_TGL_HDMI |
  249. SOF_BT_OFFLOAD_SSP(2) |
  250. SOF_SSP_BT_OFFLOAD_PRESENT),
  251. },
  252. {
  253. .callback = sof_sdw_quirk_cb,
  254. .matches = {
  255. DMI_MATCH(DMI_SYS_VENDOR, "Google"),
  256. DMI_MATCH(DMI_PRODUCT_NAME, "Brya"),
  257. },
  258. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  259. SOF_SDW_PCH_DMIC |
  260. SOF_SDW_FOUR_SPK |
  261. SOF_BT_OFFLOAD_SSP(2) |
  262. SOF_SSP_BT_OFFLOAD_PRESENT),
  263. },
  264. {
  265. .callback = sof_sdw_quirk_cb,
  266. .matches = {
  267. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  268. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF0")
  269. },
  270. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  271. RT711_JD2 |
  272. SOF_SDW_FOUR_SPK),
  273. },
  274. {
  275. .callback = sof_sdw_quirk_cb,
  276. .matches = {
  277. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  278. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF3"),
  279. },
  280. /* No Jack */
  281. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  282. SOF_SDW_FOUR_SPK),
  283. },
  284. {
  285. .callback = sof_sdw_quirk_cb,
  286. .matches = {
  287. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  288. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF")
  289. },
  290. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  291. RT711_JD2 |
  292. SOF_SDW_FOUR_SPK),
  293. },
  294. {
  295. .callback = sof_sdw_quirk_cb,
  296. .matches = {
  297. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  298. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00")
  299. },
  300. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  301. RT711_JD2 |
  302. SOF_SDW_FOUR_SPK),
  303. },
  304. {
  305. .callback = sof_sdw_quirk_cb,
  306. .matches = {
  307. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  308. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01")
  309. },
  310. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  311. RT711_JD2 |
  312. SOF_SDW_FOUR_SPK),
  313. },
  314. {
  315. .callback = sof_sdw_quirk_cb,
  316. .matches = {
  317. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  318. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B11")
  319. },
  320. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  321. RT711_JD2 |
  322. SOF_SDW_FOUR_SPK),
  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, "0B12")
  329. },
  330. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  331. RT711_JD2 |
  332. SOF_SDW_FOUR_SPK),
  333. },
  334. {
  335. .callback = sof_sdw_quirk_cb,
  336. .matches = {
  337. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  338. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B13"),
  339. },
  340. /* No Jack */
  341. .driver_data = (void *)SOF_SDW_TGL_HDMI,
  342. },
  343. {
  344. .callback = sof_sdw_quirk_cb,
  345. .matches = {
  346. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  347. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B14"),
  348. },
  349. /* No Jack */
  350. .driver_data = (void *)SOF_SDW_TGL_HDMI,
  351. },
  352. {
  353. .callback = sof_sdw_quirk_cb,
  354. .matches = {
  355. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  356. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B29"),
  357. },
  358. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  359. RT711_JD2 |
  360. SOF_SDW_FOUR_SPK),
  361. },
  362. {
  363. .callback = sof_sdw_quirk_cb,
  364. .matches = {
  365. DMI_MATCH(DMI_SYS_VENDOR, "HP"),
  366. DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16-k0xxx"),
  367. },
  368. .driver_data = (void *)(SOF_SDW_TGL_HDMI |
  369. RT711_JD2),
  370. },
  371. /* MeteorLake devices */
  372. {
  373. .callback = sof_sdw_quirk_cb,
  374. .matches = {
  375. DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_mtlrvp"),
  376. },
  377. .driver_data = (void *)(RT711_JD1),
  378. },
  379. {
  380. .callback = sof_sdw_quirk_cb,
  381. .matches = {
  382. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  383. DMI_MATCH(DMI_PRODUCT_NAME, "Meteor Lake Client Platform"),
  384. },
  385. .driver_data = (void *)(RT711_JD2_100K),
  386. },
  387. {
  388. .callback = sof_sdw_quirk_cb,
  389. .matches = {
  390. DMI_MATCH(DMI_SYS_VENDOR, "Google"),
  391. DMI_MATCH(DMI_PRODUCT_NAME, "Rex"),
  392. },
  393. .driver_data = (void *)(SOF_SDW_PCH_DMIC |
  394. SOF_BT_OFFLOAD_SSP(1) |
  395. SOF_SSP_BT_OFFLOAD_PRESENT),
  396. },
  397. /* LunarLake devices */
  398. {
  399. .callback = sof_sdw_quirk_cb,
  400. .matches = {
  401. DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  402. DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"),
  403. },
  404. .driver_data = (void *)(RT711_JD2_100K),
  405. },
  406. {}
  407. };
  408. static struct snd_soc_dai_link_component dmic_component[] = {
  409. {
  410. .name = "dmic-codec",
  411. .dai_name = "dmic-hifi",
  412. }
  413. };
  414. static struct snd_soc_dai_link_component platform_component[] = {
  415. {
  416. /* name might be overridden during probe */
  417. .name = "0000:00:1f.3"
  418. }
  419. };
  420. /* these wrappers are only needed to avoid typecast compilation errors */
  421. int sdw_startup(struct snd_pcm_substream *substream)
  422. {
  423. return sdw_startup_stream(substream);
  424. }
  425. int sdw_prepare(struct snd_pcm_substream *substream)
  426. {
  427. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  428. struct sdw_stream_runtime *sdw_stream;
  429. struct snd_soc_dai *dai;
  430. /* Find stream from first CPU DAI */
  431. dai = asoc_rtd_to_cpu(rtd, 0);
  432. sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
  433. if (IS_ERR(sdw_stream)) {
  434. dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
  435. return PTR_ERR(sdw_stream);
  436. }
  437. return sdw_prepare_stream(sdw_stream);
  438. }
  439. int sdw_trigger(struct snd_pcm_substream *substream, int cmd)
  440. {
  441. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  442. struct sdw_stream_runtime *sdw_stream;
  443. struct snd_soc_dai *dai;
  444. int ret;
  445. /* Find stream from first CPU DAI */
  446. dai = asoc_rtd_to_cpu(rtd, 0);
  447. sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
  448. if (IS_ERR(sdw_stream)) {
  449. dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
  450. return PTR_ERR(sdw_stream);
  451. }
  452. switch (cmd) {
  453. case SNDRV_PCM_TRIGGER_START:
  454. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  455. case SNDRV_PCM_TRIGGER_RESUME:
  456. ret = sdw_enable_stream(sdw_stream);
  457. break;
  458. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  459. case SNDRV_PCM_TRIGGER_SUSPEND:
  460. case SNDRV_PCM_TRIGGER_STOP:
  461. ret = sdw_disable_stream(sdw_stream);
  462. break;
  463. default:
  464. ret = -EINVAL;
  465. break;
  466. }
  467. if (ret)
  468. dev_err(rtd->dev, "%s trigger %d failed: %d", __func__, cmd, ret);
  469. return ret;
  470. }
  471. int sdw_hw_free(struct snd_pcm_substream *substream)
  472. {
  473. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  474. struct sdw_stream_runtime *sdw_stream;
  475. struct snd_soc_dai *dai;
  476. /* Find stream from first CPU DAI */
  477. dai = asoc_rtd_to_cpu(rtd, 0);
  478. sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
  479. if (IS_ERR(sdw_stream)) {
  480. dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
  481. return PTR_ERR(sdw_stream);
  482. }
  483. return sdw_deprepare_stream(sdw_stream);
  484. }
  485. void sdw_shutdown(struct snd_pcm_substream *substream)
  486. {
  487. sdw_shutdown_stream(substream);
  488. }
  489. static const struct snd_soc_ops sdw_ops = {
  490. .startup = sdw_startup,
  491. .prepare = sdw_prepare,
  492. .trigger = sdw_trigger,
  493. .hw_free = sdw_hw_free,
  494. .shutdown = sdw_shutdown,
  495. };
  496. static struct sof_sdw_codec_info codec_info_list[] = {
  497. {
  498. .part_id = 0x700,
  499. .direction = {true, true},
  500. .dai_name = "rt700-aif1",
  501. .init = sof_sdw_rt700_init,
  502. .codec_type = SOF_SDW_CODEC_TYPE_JACK,
  503. },
  504. {
  505. .part_id = 0x711,
  506. .version_id = 3,
  507. .direction = {true, true},
  508. .dai_name = "rt711-sdca-aif1",
  509. .init = sof_sdw_rt711_sdca_init,
  510. .exit = sof_sdw_rt711_sdca_exit,
  511. .codec_type = SOF_SDW_CODEC_TYPE_JACK,
  512. },
  513. {
  514. .part_id = 0x711,
  515. .version_id = 2,
  516. .direction = {true, true},
  517. .dai_name = "rt711-aif1",
  518. .init = sof_sdw_rt711_init,
  519. .exit = sof_sdw_rt711_exit,
  520. .codec_type = SOF_SDW_CODEC_TYPE_JACK,
  521. },
  522. {
  523. .part_id = 0x1308,
  524. .acpi_id = "10EC1308",
  525. .direction = {true, false},
  526. .dai_name = "rt1308-aif",
  527. .ops = &sof_sdw_rt1308_i2s_ops,
  528. .init = sof_sdw_rt1308_init,
  529. .codec_type = SOF_SDW_CODEC_TYPE_AMP,
  530. },
  531. {
  532. .part_id = 0x1316,
  533. .direction = {true, true},
  534. .dai_name = "rt1316-aif",
  535. .init = sof_sdw_rt1316_init,
  536. .codec_type = SOF_SDW_CODEC_TYPE_AMP,
  537. },
  538. {
  539. .part_id = 0x714,
  540. .version_id = 3,
  541. .direction = {false, true},
  542. .ignore_pch_dmic = true,
  543. .dai_name = "rt715-aif2",
  544. .init = sof_sdw_rt715_sdca_init,
  545. .codec_type = SOF_SDW_CODEC_TYPE_MIC,
  546. },
  547. {
  548. .part_id = 0x715,
  549. .version_id = 3,
  550. .direction = {false, true},
  551. .ignore_pch_dmic = true,
  552. .dai_name = "rt715-aif2",
  553. .init = sof_sdw_rt715_sdca_init,
  554. .codec_type = SOF_SDW_CODEC_TYPE_MIC,
  555. },
  556. {
  557. .part_id = 0x714,
  558. .version_id = 2,
  559. .direction = {false, true},
  560. .ignore_pch_dmic = true,
  561. .dai_name = "rt715-aif2",
  562. .init = sof_sdw_rt715_init,
  563. .codec_type = SOF_SDW_CODEC_TYPE_MIC,
  564. },
  565. {
  566. .part_id = 0x715,
  567. .version_id = 2,
  568. .direction = {false, true},
  569. .ignore_pch_dmic = true,
  570. .dai_name = "rt715-aif2",
  571. .init = sof_sdw_rt715_init,
  572. .codec_type = SOF_SDW_CODEC_TYPE_MIC,
  573. },
  574. {
  575. .part_id = 0x8373,
  576. .direction = {true, true},
  577. .dai_name = "max98373-aif1",
  578. .init = sof_sdw_mx8373_init,
  579. .codec_card_late_probe = sof_sdw_mx8373_late_probe,
  580. .codec_type = SOF_SDW_CODEC_TYPE_AMP,
  581. },
  582. {
  583. .part_id = 0x5682,
  584. .direction = {true, true},
  585. .dai_name = "rt5682-sdw",
  586. .init = sof_sdw_rt5682_init,
  587. .codec_type = SOF_SDW_CODEC_TYPE_JACK,
  588. },
  589. {
  590. .part_id = 0xaaaa, /* generic codec mockup */
  591. .version_id = 0,
  592. .direction = {true, true},
  593. .dai_name = "sdw-mockup-aif1",
  594. .init = NULL,
  595. .codec_type = SOF_SDW_CODEC_TYPE_JACK,
  596. },
  597. {
  598. .part_id = 0xaa55, /* headset codec mockup */
  599. .version_id = 0,
  600. .direction = {true, true},
  601. .dai_name = "sdw-mockup-aif1",
  602. .init = NULL,
  603. .codec_type = SOF_SDW_CODEC_TYPE_JACK,
  604. },
  605. {
  606. .part_id = 0x55aa, /* amplifier mockup */
  607. .version_id = 0,
  608. .direction = {true, false},
  609. .dai_name = "sdw-mockup-aif1",
  610. .init = NULL,
  611. .codec_type = SOF_SDW_CODEC_TYPE_AMP,
  612. },
  613. {
  614. .part_id = 0x5555,
  615. .version_id = 0,
  616. .direction = {false, true},
  617. .dai_name = "sdw-mockup-aif1",
  618. .codec_type = SOF_SDW_CODEC_TYPE_MIC,
  619. },
  620. };
  621. static inline int find_codec_info_part(u64 adr)
  622. {
  623. unsigned int part_id, sdw_version;
  624. int i;
  625. part_id = SDW_PART_ID(adr);
  626. sdw_version = SDW_VERSION(adr);
  627. for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
  628. /*
  629. * A codec info is for all sdw version with the part id if
  630. * version_id is not specified in the codec info.
  631. */
  632. if (part_id == codec_info_list[i].part_id &&
  633. (!codec_info_list[i].version_id ||
  634. sdw_version == codec_info_list[i].version_id))
  635. return i;
  636. return -EINVAL;
  637. }
  638. static inline int find_codec_info_acpi(const u8 *acpi_id)
  639. {
  640. int i;
  641. if (!acpi_id[0])
  642. return -EINVAL;
  643. for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
  644. if (!memcmp(codec_info_list[i].acpi_id, acpi_id,
  645. ACPI_ID_LEN))
  646. break;
  647. if (i == ARRAY_SIZE(codec_info_list))
  648. return -EINVAL;
  649. return i;
  650. }
  651. /*
  652. * get BE dailink number and CPU DAI number based on sdw link adr.
  653. * Since some sdw slaves may be aggregated, the CPU DAI number
  654. * may be larger than the number of BE dailinks.
  655. */
  656. static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_link_adr *links,
  657. int *sdw_be_num, int *sdw_cpu_dai_num)
  658. {
  659. const struct snd_soc_acpi_link_adr *link;
  660. int _codec_type = SOF_SDW_CODEC_TYPE_JACK;
  661. bool group_visited[SDW_MAX_GROUPS];
  662. bool no_aggregation;
  663. int i;
  664. no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
  665. *sdw_cpu_dai_num = 0;
  666. *sdw_be_num = 0;
  667. if (!links)
  668. return -EINVAL;
  669. for (i = 0; i < SDW_MAX_GROUPS; i++)
  670. group_visited[i] = false;
  671. for (link = links; link->num_adr; link++) {
  672. const struct snd_soc_acpi_endpoint *endpoint;
  673. int codec_index;
  674. int stream;
  675. u64 adr;
  676. adr = link->adr_d->adr;
  677. codec_index = find_codec_info_part(adr);
  678. if (codec_index < 0)
  679. return codec_index;
  680. if (codec_info_list[codec_index].codec_type < _codec_type)
  681. dev_warn(dev,
  682. "Unexpected address table ordering. Expected order: jack -> amp -> mic\n");
  683. _codec_type = codec_info_list[codec_index].codec_type;
  684. endpoint = link->adr_d->endpoints;
  685. /* count DAI number for playback and capture */
  686. for_each_pcm_streams(stream) {
  687. if (!codec_info_list[codec_index].direction[stream])
  688. continue;
  689. (*sdw_cpu_dai_num)++;
  690. /* count BE for each non-aggregated slave or group */
  691. if (!endpoint->aggregated || no_aggregation ||
  692. !group_visited[endpoint->group_id])
  693. (*sdw_be_num)++;
  694. }
  695. if (endpoint->aggregated)
  696. group_visited[endpoint->group_id] = true;
  697. }
  698. return 0;
  699. }
  700. static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
  701. int be_id, char *name, int playback, int capture,
  702. struct snd_soc_dai_link_component *cpus, int cpus_num,
  703. struct snd_soc_dai_link_component *codecs, int codecs_num,
  704. int (*init)(struct snd_soc_pcm_runtime *rtd),
  705. const struct snd_soc_ops *ops)
  706. {
  707. dev_dbg(dev, "create dai link %s, id %d\n", name, be_id);
  708. dai_links->id = be_id;
  709. dai_links->name = name;
  710. dai_links->platforms = platform_component;
  711. dai_links->num_platforms = ARRAY_SIZE(platform_component);
  712. dai_links->no_pcm = 1;
  713. dai_links->cpus = cpus;
  714. dai_links->num_cpus = cpus_num;
  715. dai_links->codecs = codecs;
  716. dai_links->num_codecs = codecs_num;
  717. dai_links->dpcm_playback = playback;
  718. dai_links->dpcm_capture = capture;
  719. dai_links->init = init;
  720. dai_links->ops = ops;
  721. }
  722. static bool is_unique_device(const struct snd_soc_acpi_link_adr *link,
  723. unsigned int sdw_version,
  724. unsigned int mfg_id,
  725. unsigned int part_id,
  726. unsigned int class_id,
  727. int index_in_link
  728. )
  729. {
  730. int i;
  731. for (i = 0; i < link->num_adr; i++) {
  732. unsigned int sdw1_version, mfg1_id, part1_id, class1_id;
  733. u64 adr;
  734. /* skip itself */
  735. if (i == index_in_link)
  736. continue;
  737. adr = link->adr_d[i].adr;
  738. sdw1_version = SDW_VERSION(adr);
  739. mfg1_id = SDW_MFG_ID(adr);
  740. part1_id = SDW_PART_ID(adr);
  741. class1_id = SDW_CLASS_ID(adr);
  742. if (sdw_version == sdw1_version &&
  743. mfg_id == mfg1_id &&
  744. part_id == part1_id &&
  745. class_id == class1_id)
  746. return false;
  747. }
  748. return true;
  749. }
  750. static int create_codec_dai_name(struct device *dev,
  751. const struct snd_soc_acpi_link_adr *link,
  752. struct snd_soc_dai_link_component *codec,
  753. int offset,
  754. struct snd_soc_codec_conf *codec_conf,
  755. int codec_count,
  756. int *codec_conf_index)
  757. {
  758. int i;
  759. /* sanity check */
  760. if (*codec_conf_index + link->num_adr > codec_count) {
  761. dev_err(dev, "codec_conf: out-of-bounds access requested\n");
  762. return -EINVAL;
  763. }
  764. for (i = 0; i < link->num_adr; i++) {
  765. unsigned int sdw_version, unique_id, mfg_id;
  766. unsigned int link_id, part_id, class_id;
  767. int codec_index, comp_index;
  768. char *codec_str;
  769. u64 adr;
  770. adr = link->adr_d[i].adr;
  771. sdw_version = SDW_VERSION(adr);
  772. link_id = SDW_DISCO_LINK_ID(adr);
  773. unique_id = SDW_UNIQUE_ID(adr);
  774. mfg_id = SDW_MFG_ID(adr);
  775. part_id = SDW_PART_ID(adr);
  776. class_id = SDW_CLASS_ID(adr);
  777. comp_index = i + offset;
  778. if (is_unique_device(link, sdw_version, mfg_id, part_id,
  779. class_id, i)) {
  780. codec_str = "sdw:%01x:%04x:%04x:%02x";
  781. codec[comp_index].name =
  782. devm_kasprintf(dev, GFP_KERNEL, codec_str,
  783. link_id, mfg_id, part_id,
  784. class_id);
  785. } else {
  786. codec_str = "sdw:%01x:%04x:%04x:%02x:%01x";
  787. codec[comp_index].name =
  788. devm_kasprintf(dev, GFP_KERNEL, codec_str,
  789. link_id, mfg_id, part_id,
  790. class_id, unique_id);
  791. }
  792. if (!codec[comp_index].name)
  793. return -ENOMEM;
  794. codec_index = find_codec_info_part(adr);
  795. if (codec_index < 0)
  796. return codec_index;
  797. codec[comp_index].dai_name =
  798. codec_info_list[codec_index].dai_name;
  799. codec_conf[*codec_conf_index].dlc = codec[comp_index];
  800. codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix;
  801. ++*codec_conf_index;
  802. }
  803. return 0;
  804. }
  805. static int set_codec_init_func(struct snd_soc_card *card,
  806. const struct snd_soc_acpi_link_adr *link,
  807. struct snd_soc_dai_link *dai_links,
  808. bool playback, int group_id)
  809. {
  810. int i;
  811. do {
  812. /*
  813. * Initialize the codec. If codec is part of an aggregated
  814. * group (group_id>0), initialize all codecs belonging to
  815. * same group.
  816. */
  817. for (i = 0; i < link->num_adr; i++) {
  818. int codec_index;
  819. codec_index = find_codec_info_part(link->adr_d[i].adr);
  820. if (codec_index < 0)
  821. return codec_index;
  822. /* The group_id is > 0 iff the codec is aggregated */
  823. if (link->adr_d[i].endpoints->group_id != group_id)
  824. continue;
  825. if (codec_info_list[codec_index].init)
  826. codec_info_list[codec_index].init(card,
  827. link,
  828. dai_links,
  829. &codec_info_list[codec_index],
  830. playback);
  831. }
  832. link++;
  833. } while (link->mask && group_id);
  834. return 0;
  835. }
  836. /*
  837. * check endpoint status in slaves and gather link ID for all slaves in
  838. * the same group to generate different CPU DAI. Now only support
  839. * one sdw link with all slaves set with only single group id.
  840. *
  841. * one slave on one sdw link with aggregated = 0
  842. * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI
  843. *
  844. * two or more slaves on one sdw link with aggregated = 0
  845. * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs
  846. *
  847. * multiple links with multiple slaves with aggregated = 1
  848. * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs
  849. */
  850. static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
  851. struct device *dev, int *cpu_dai_id, int *cpu_dai_num,
  852. int *codec_num, unsigned int *group_id,
  853. bool *group_generated)
  854. {
  855. const struct snd_soc_acpi_adr_device *adr_d;
  856. const struct snd_soc_acpi_link_adr *adr_next;
  857. bool no_aggregation;
  858. int index = 0;
  859. no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
  860. *codec_num = adr_link->num_adr;
  861. adr_d = adr_link->adr_d;
  862. /* make sure the link mask has a single bit set */
  863. if (!is_power_of_2(adr_link->mask))
  864. return -EINVAL;
  865. cpu_dai_id[index++] = ffs(adr_link->mask) - 1;
  866. if (!adr_d->endpoints->aggregated || no_aggregation) {
  867. *cpu_dai_num = 1;
  868. *group_id = 0;
  869. return 0;
  870. }
  871. *group_id = adr_d->endpoints->group_id;
  872. /* gather other link ID of slaves in the same group */
  873. for (adr_next = adr_link + 1; adr_next && adr_next->num_adr;
  874. adr_next++) {
  875. const struct snd_soc_acpi_endpoint *endpoint;
  876. endpoint = adr_next->adr_d->endpoints;
  877. if (!endpoint->aggregated ||
  878. endpoint->group_id != *group_id)
  879. continue;
  880. /* make sure the link mask has a single bit set */
  881. if (!is_power_of_2(adr_next->mask))
  882. return -EINVAL;
  883. if (index >= SDW_MAX_CPU_DAIS) {
  884. dev_err(dev, " cpu_dai_id array overflows");
  885. return -EINVAL;
  886. }
  887. cpu_dai_id[index++] = ffs(adr_next->mask) - 1;
  888. *codec_num += adr_next->num_adr;
  889. }
  890. /*
  891. * indicate CPU DAIs for this group have been generated
  892. * to avoid generating CPU DAIs for this group again.
  893. */
  894. group_generated[*group_id] = true;
  895. *cpu_dai_num = index;
  896. return 0;
  897. }
  898. static int create_sdw_dailink(struct snd_soc_card *card,
  899. struct device *dev, int *link_index,
  900. struct snd_soc_dai_link *dai_links,
  901. int sdw_be_num, int sdw_cpu_dai_num,
  902. struct snd_soc_dai_link_component *cpus,
  903. const struct snd_soc_acpi_link_adr *link,
  904. int *cpu_id, bool *group_generated,
  905. struct snd_soc_codec_conf *codec_conf,
  906. int codec_count, int *link_id,
  907. int *codec_conf_index,
  908. bool *ignore_pch_dmic)
  909. {
  910. const struct snd_soc_acpi_link_adr *link_next;
  911. struct snd_soc_dai_link_component *codecs;
  912. int cpu_dai_id[SDW_MAX_CPU_DAIS];
  913. int cpu_dai_num, cpu_dai_index;
  914. unsigned int group_id;
  915. int codec_idx = 0;
  916. int i = 0, j = 0;
  917. int codec_index;
  918. int codec_num;
  919. int stream;
  920. int ret;
  921. int k;
  922. ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num,
  923. &group_id, group_generated);
  924. if (ret)
  925. return ret;
  926. codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL);
  927. if (!codecs)
  928. return -ENOMEM;
  929. /* generate codec name on different links in the same group */
  930. for (link_next = link; link_next && link_next->num_adr &&
  931. i < cpu_dai_num; link_next++) {
  932. const struct snd_soc_acpi_endpoint *endpoints;
  933. endpoints = link_next->adr_d->endpoints;
  934. if (group_id && (!endpoints->aggregated ||
  935. endpoints->group_id != group_id))
  936. continue;
  937. /* skip the link excluded by this processed group */
  938. if (cpu_dai_id[i] != ffs(link_next->mask) - 1)
  939. continue;
  940. ret = create_codec_dai_name(dev, link_next, codecs, codec_idx,
  941. codec_conf, codec_count, codec_conf_index);
  942. if (ret < 0)
  943. return ret;
  944. /* check next link to create codec dai in the processed group */
  945. i++;
  946. codec_idx += link_next->num_adr;
  947. }
  948. /* find codec info to create BE DAI */
  949. codec_index = find_codec_info_part(link->adr_d[0].adr);
  950. if (codec_index < 0)
  951. return codec_index;
  952. if (codec_info_list[codec_index].ignore_pch_dmic)
  953. *ignore_pch_dmic = true;
  954. /* Shift the first amplifier's *link_id to SDW_AMP_DAI_ID */
  955. if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_AMP &&
  956. *link_id < SDW_AMP_DAI_ID)
  957. *link_id = SDW_AMP_DAI_ID;
  958. /*
  959. * DAI ID is fixed at SDW_DMIC_DAI_ID for MICs to
  960. * keep sdw DMIC and HDMI setting static in UCM
  961. */
  962. if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_MIC &&
  963. *link_id < SDW_DMIC_DAI_ID)
  964. *link_id = SDW_DMIC_DAI_ID;
  965. cpu_dai_index = *cpu_id;
  966. for_each_pcm_streams(stream) {
  967. char *name, *cpu_name;
  968. int playback, capture;
  969. static const char * const sdw_stream_name[] = {
  970. "SDW%d-Playback",
  971. "SDW%d-Capture",
  972. };
  973. if (!codec_info_list[codec_index].direction[stream])
  974. continue;
  975. /* create stream name according to first link id */
  976. name = devm_kasprintf(dev, GFP_KERNEL,
  977. sdw_stream_name[stream], cpu_dai_id[0]);
  978. if (!name)
  979. return -ENOMEM;
  980. /*
  981. * generate CPU DAI name base on the sdw link ID and
  982. * PIN ID with offset of 2 according to sdw dai driver.
  983. */
  984. for (k = 0; k < cpu_dai_num; k++) {
  985. cpu_name = devm_kasprintf(dev, GFP_KERNEL,
  986. "SDW%d Pin%d", cpu_dai_id[k],
  987. j + SDW_INTEL_BIDIR_PDI_BASE);
  988. if (!cpu_name)
  989. return -ENOMEM;
  990. if (cpu_dai_index >= sdw_cpu_dai_num) {
  991. dev_err(dev, "invalid cpu dai index %d",
  992. cpu_dai_index);
  993. return -EINVAL;
  994. }
  995. cpus[cpu_dai_index++].dai_name = cpu_name;
  996. }
  997. /*
  998. * We create sdw dai links at first stage, so link index should
  999. * not be larger than sdw_be_num
  1000. */
  1001. if (*link_index >= sdw_be_num) {
  1002. dev_err(dev, "invalid dai link index %d", *link_index);
  1003. return -EINVAL;
  1004. }
  1005. if (*cpu_id >= sdw_cpu_dai_num) {
  1006. dev_err(dev, " invalid cpu dai index %d", *cpu_id);
  1007. return -EINVAL;
  1008. }
  1009. playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
  1010. capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
  1011. init_dai_link(dev, dai_links + *link_index, (*link_id)++, name,
  1012. playback, capture,
  1013. cpus + *cpu_id, cpu_dai_num,
  1014. codecs, codec_num,
  1015. NULL, &sdw_ops);
  1016. /*
  1017. * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
  1018. * based on wait_for_completion(), tag them as 'nonatomic'.
  1019. */
  1020. dai_links[*link_index].nonatomic = true;
  1021. ret = set_codec_init_func(card, link, dai_links + (*link_index)++,
  1022. playback, group_id);
  1023. if (ret < 0) {
  1024. dev_err(dev, "failed to init codec %d", codec_index);
  1025. return ret;
  1026. }
  1027. *cpu_id += cpu_dai_num;
  1028. j++;
  1029. }
  1030. return 0;
  1031. }
  1032. #define IDISP_CODEC_MASK 0x4
  1033. static int sof_card_codec_conf_alloc(struct device *dev,
  1034. struct snd_soc_acpi_mach_params *mach_params,
  1035. struct snd_soc_codec_conf **codec_conf,
  1036. int *codec_conf_count)
  1037. {
  1038. const struct snd_soc_acpi_link_adr *adr_link;
  1039. struct snd_soc_codec_conf *c_conf;
  1040. int num_codecs = 0;
  1041. int i;
  1042. adr_link = mach_params->links;
  1043. if (!adr_link)
  1044. return -EINVAL;
  1045. /* generate DAI links by each sdw link */
  1046. for (; adr_link->num_adr; adr_link++) {
  1047. for (i = 0; i < adr_link->num_adr; i++) {
  1048. if (!adr_link->adr_d[i].name_prefix) {
  1049. dev_err(dev, "codec 0x%llx does not have a name prefix\n",
  1050. adr_link->adr_d[i].adr);
  1051. return -EINVAL;
  1052. }
  1053. }
  1054. num_codecs += adr_link->num_adr;
  1055. }
  1056. c_conf = devm_kzalloc(dev, num_codecs * sizeof(*c_conf), GFP_KERNEL);
  1057. if (!c_conf)
  1058. return -ENOMEM;
  1059. *codec_conf = c_conf;
  1060. *codec_conf_count = num_codecs;
  1061. return 0;
  1062. }
  1063. static int sof_card_dai_links_create(struct device *dev,
  1064. struct snd_soc_acpi_mach *mach,
  1065. struct snd_soc_card *card)
  1066. {
  1067. int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num;
  1068. struct mc_private *ctx = snd_soc_card_get_drvdata(card);
  1069. struct snd_soc_dai_link_component *idisp_components;
  1070. struct snd_soc_dai_link_component *ssp_components;
  1071. struct snd_soc_acpi_mach_params *mach_params;
  1072. const struct snd_soc_acpi_link_adr *adr_link;
  1073. struct snd_soc_dai_link_component *cpus;
  1074. struct snd_soc_codec_conf *codec_conf;
  1075. bool ignore_pch_dmic = false;
  1076. int codec_conf_count;
  1077. int codec_conf_index = 0;
  1078. bool group_generated[SDW_MAX_GROUPS];
  1079. int ssp_codec_index, ssp_mask;
  1080. struct snd_soc_dai_link *links;
  1081. int num_links, link_index = 0;
  1082. char *name, *cpu_name;
  1083. int total_cpu_dai_num;
  1084. int sdw_cpu_dai_num;
  1085. int i, j, be_id = 0;
  1086. int cpu_id = 0;
  1087. int comp_num;
  1088. int ret;
  1089. mach_params = &mach->mach_params;
  1090. /* allocate codec conf, will be populated when dailinks are created */
  1091. ret = sof_card_codec_conf_alloc(dev, mach_params, &codec_conf, &codec_conf_count);
  1092. if (ret < 0)
  1093. return ret;
  1094. /* reset amp_num to ensure amp_num++ starts from 0 in each probe */
  1095. for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
  1096. codec_info_list[i].amp_num = 0;
  1097. if (mach_params->codec_mask & IDISP_CODEC_MASK) {
  1098. ctx->idisp_codec = true;
  1099. if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
  1100. hdmi_num = SOF_TGL_HDMI_COUNT;
  1101. else
  1102. hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
  1103. }
  1104. ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
  1105. /*
  1106. * on generic tgl platform, I2S or sdw mode is supported
  1107. * based on board rework. A ACPI device is registered in
  1108. * system only when I2S mode is supported, not sdw mode.
  1109. * Here check ACPI ID to confirm I2S is supported.
  1110. */
  1111. ssp_codec_index = find_codec_info_acpi(mach->id);
  1112. ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0;
  1113. comp_num = hdmi_num + ssp_num;
  1114. ret = get_sdw_dailink_info(dev, mach_params->links,
  1115. &sdw_be_num, &sdw_cpu_dai_num);
  1116. if (ret < 0) {
  1117. dev_err(dev, "failed to get sdw link info %d", ret);
  1118. return ret;
  1119. }
  1120. /* enable dmic01 & dmic16k */
  1121. dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0;
  1122. comp_num += dmic_num;
  1123. if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
  1124. comp_num++;
  1125. dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num,
  1126. dmic_num, ctx->idisp_codec ? hdmi_num : 0);
  1127. /* allocate BE dailinks */
  1128. num_links = comp_num + sdw_be_num;
  1129. links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL);
  1130. /* allocated CPU DAIs */
  1131. total_cpu_dai_num = comp_num + sdw_cpu_dai_num;
  1132. cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus),
  1133. GFP_KERNEL);
  1134. if (!links || !cpus)
  1135. return -ENOMEM;
  1136. /* SDW */
  1137. if (!sdw_be_num)
  1138. goto SSP;
  1139. adr_link = mach_params->links;
  1140. if (!adr_link)
  1141. return -EINVAL;
  1142. /*
  1143. * SoundWire Slaves aggregated in the same group may be
  1144. * located on different hardware links. Clear array to indicate
  1145. * CPU DAIs for this group have not been generated.
  1146. */
  1147. for (i = 0; i < SDW_MAX_GROUPS; i++)
  1148. group_generated[i] = false;
  1149. /* generate DAI links by each sdw link */
  1150. for (; adr_link->num_adr; adr_link++) {
  1151. const struct snd_soc_acpi_endpoint *endpoint;
  1152. endpoint = adr_link->adr_d->endpoints;
  1153. if (endpoint->aggregated && !endpoint->group_id) {
  1154. dev_err(dev, "invalid group id on link %x",
  1155. adr_link->mask);
  1156. continue;
  1157. }
  1158. /* this group has been generated */
  1159. if (endpoint->aggregated &&
  1160. group_generated[endpoint->group_id])
  1161. continue;
  1162. ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num,
  1163. sdw_cpu_dai_num, cpus, adr_link,
  1164. &cpu_id, group_generated,
  1165. codec_conf, codec_conf_count,
  1166. &be_id, &codec_conf_index,
  1167. &ignore_pch_dmic);
  1168. if (ret < 0) {
  1169. dev_err(dev, "failed to create dai link %d", link_index);
  1170. return ret;
  1171. }
  1172. }
  1173. SSP:
  1174. /* SSP */
  1175. if (!ssp_num)
  1176. goto DMIC;
  1177. for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) {
  1178. struct sof_sdw_codec_info *info;
  1179. int playback, capture;
  1180. char *codec_name;
  1181. if (!(ssp_mask & 0x1))
  1182. continue;
  1183. name = devm_kasprintf(dev, GFP_KERNEL,
  1184. "SSP%d-Codec", i);
  1185. if (!name)
  1186. return -ENOMEM;
  1187. cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
  1188. if (!cpu_name)
  1189. return -ENOMEM;
  1190. ssp_components = devm_kzalloc(dev, sizeof(*ssp_components),
  1191. GFP_KERNEL);
  1192. if (!ssp_components)
  1193. return -ENOMEM;
  1194. info = &codec_info_list[ssp_codec_index];
  1195. codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
  1196. info->acpi_id, j++);
  1197. if (!codec_name)
  1198. return -ENOMEM;
  1199. ssp_components->name = codec_name;
  1200. ssp_components->dai_name = info->dai_name;
  1201. cpus[cpu_id].dai_name = cpu_name;
  1202. playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
  1203. capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
  1204. init_dai_link(dev, links + link_index, be_id, name,
  1205. playback, capture,
  1206. cpus + cpu_id, 1,
  1207. ssp_components, 1,
  1208. NULL, info->ops);
  1209. ret = info->init(card, NULL, links + link_index, info, 0);
  1210. if (ret < 0)
  1211. return ret;
  1212. INC_ID(be_id, cpu_id, link_index);
  1213. }
  1214. DMIC:
  1215. /* dmic */
  1216. if (dmic_num > 0) {
  1217. if (ignore_pch_dmic) {
  1218. dev_warn(dev, "Ignoring PCH DMIC\n");
  1219. goto HDMI;
  1220. }
  1221. cpus[cpu_id].dai_name = "DMIC01 Pin";
  1222. init_dai_link(dev, links + link_index, be_id, "dmic01",
  1223. 0, 1, // DMIC only supports capture
  1224. cpus + cpu_id, 1,
  1225. dmic_component, 1,
  1226. sof_sdw_dmic_init, NULL);
  1227. INC_ID(be_id, cpu_id, link_index);
  1228. cpus[cpu_id].dai_name = "DMIC16k Pin";
  1229. init_dai_link(dev, links + link_index, be_id, "dmic16k",
  1230. 0, 1, // DMIC only supports capture
  1231. cpus + cpu_id, 1,
  1232. dmic_component, 1,
  1233. /* don't call sof_sdw_dmic_init() twice */
  1234. NULL, NULL);
  1235. INC_ID(be_id, cpu_id, link_index);
  1236. }
  1237. HDMI:
  1238. /* HDMI */
  1239. if (hdmi_num > 0) {
  1240. idisp_components = devm_kcalloc(dev, hdmi_num,
  1241. sizeof(*idisp_components),
  1242. GFP_KERNEL);
  1243. if (!idisp_components)
  1244. return -ENOMEM;
  1245. }
  1246. for (i = 0; i < hdmi_num; i++) {
  1247. name = devm_kasprintf(dev, GFP_KERNEL,
  1248. "iDisp%d", i + 1);
  1249. if (!name)
  1250. return -ENOMEM;
  1251. if (ctx->idisp_codec) {
  1252. idisp_components[i].name = "ehdaudio0D2";
  1253. idisp_components[i].dai_name = devm_kasprintf(dev,
  1254. GFP_KERNEL,
  1255. "intel-hdmi-hifi%d",
  1256. i + 1);
  1257. if (!idisp_components[i].dai_name)
  1258. return -ENOMEM;
  1259. } else {
  1260. idisp_components[i].name = "snd-soc-dummy";
  1261. idisp_components[i].dai_name = "snd-soc-dummy-dai";
  1262. }
  1263. cpu_name = devm_kasprintf(dev, GFP_KERNEL,
  1264. "iDisp%d Pin", i + 1);
  1265. if (!cpu_name)
  1266. return -ENOMEM;
  1267. cpus[cpu_id].dai_name = cpu_name;
  1268. init_dai_link(dev, links + link_index, be_id, name,
  1269. 1, 0, // HDMI only supports playback
  1270. cpus + cpu_id, 1,
  1271. idisp_components + i, 1,
  1272. sof_sdw_hdmi_init, NULL);
  1273. INC_ID(be_id, cpu_id, link_index);
  1274. }
  1275. if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
  1276. int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
  1277. SOF_BT_OFFLOAD_SSP_SHIFT;
  1278. name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
  1279. if (!name)
  1280. return -ENOMEM;
  1281. ssp_components = devm_kzalloc(dev, sizeof(*ssp_components),
  1282. GFP_KERNEL);
  1283. if (!ssp_components)
  1284. return -ENOMEM;
  1285. ssp_components->name = "snd-soc-dummy";
  1286. ssp_components->dai_name = "snd-soc-dummy-dai";
  1287. cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port);
  1288. if (!cpu_name)
  1289. return -ENOMEM;
  1290. cpus[cpu_id].dai_name = cpu_name;
  1291. init_dai_link(dev, links + link_index, be_id, name, 1, 1,
  1292. cpus + cpu_id, 1, ssp_components, 1, NULL, NULL);
  1293. }
  1294. card->dai_link = links;
  1295. card->num_links = num_links;
  1296. card->codec_conf = codec_conf;
  1297. card->num_configs = codec_conf_count;
  1298. return 0;
  1299. }
  1300. static int sof_sdw_card_late_probe(struct snd_soc_card *card)
  1301. {
  1302. struct mc_private *ctx = snd_soc_card_get_drvdata(card);
  1303. int ret = 0;
  1304. int i;
  1305. for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
  1306. if (!codec_info_list[i].late_probe)
  1307. continue;
  1308. ret = codec_info_list[i].codec_card_late_probe(card);
  1309. if (ret < 0)
  1310. return ret;
  1311. }
  1312. if (ctx->idisp_codec)
  1313. ret = sof_sdw_hdmi_card_late_probe(card);
  1314. return ret;
  1315. }
  1316. /* SoC card */
  1317. static const char sdw_card_long_name[] = "Intel Soundwire SOF";
  1318. static struct snd_soc_card card_sof_sdw = {
  1319. .name = "soundwire",
  1320. .owner = THIS_MODULE,
  1321. .late_probe = sof_sdw_card_late_probe,
  1322. };
  1323. static void mc_dailink_exit_loop(struct snd_soc_card *card)
  1324. {
  1325. struct snd_soc_dai_link *link;
  1326. int ret;
  1327. int i, j;
  1328. for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
  1329. if (!codec_info_list[i].exit)
  1330. continue;
  1331. /*
  1332. * We don't need to call .exit function if there is no matched
  1333. * dai link found.
  1334. */
  1335. for_each_card_prelinks(card, j, link) {
  1336. if (!strcmp(link->codecs[0].dai_name,
  1337. codec_info_list[i].dai_name)) {
  1338. ret = codec_info_list[i].exit(card, link);
  1339. if (ret)
  1340. dev_warn(card->dev,
  1341. "codec exit failed %d\n",
  1342. ret);
  1343. break;
  1344. }
  1345. }
  1346. }
  1347. }
  1348. static int mc_probe(struct platform_device *pdev)
  1349. {
  1350. struct snd_soc_card *card = &card_sof_sdw;
  1351. struct snd_soc_acpi_mach *mach;
  1352. struct mc_private *ctx;
  1353. int amp_num = 0, i;
  1354. int ret;
  1355. dev_dbg(&pdev->dev, "Entry\n");
  1356. ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
  1357. if (!ctx)
  1358. return -ENOMEM;
  1359. dmi_check_system(sof_sdw_quirk_table);
  1360. if (quirk_override != -1) {
  1361. dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n",
  1362. sof_sdw_quirk, quirk_override);
  1363. sof_sdw_quirk = quirk_override;
  1364. }
  1365. log_quirks(&pdev->dev);
  1366. INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
  1367. card->dev = &pdev->dev;
  1368. snd_soc_card_set_drvdata(card, ctx);
  1369. mach = pdev->dev.platform_data;
  1370. ret = sof_card_dai_links_create(&pdev->dev, mach,
  1371. card);
  1372. if (ret < 0)
  1373. return ret;
  1374. /*
  1375. * the default amp_num is zero for each codec and
  1376. * amp_num will only be increased for active amp
  1377. * codecs on used platform
  1378. */
  1379. for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
  1380. amp_num += codec_info_list[i].amp_num;
  1381. card->components = devm_kasprintf(card->dev, GFP_KERNEL,
  1382. "cfg-spk:%d cfg-amp:%d",
  1383. (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
  1384. ? 4 : 2, amp_num);
  1385. if (!card->components)
  1386. return -ENOMEM;
  1387. if (mach->mach_params.dmic_num) {
  1388. card->components = devm_kasprintf(card->dev, GFP_KERNEL,
  1389. "%s mic:dmic cfg-mics:%d",
  1390. card->components,
  1391. mach->mach_params.dmic_num);
  1392. if (!card->components)
  1393. return -ENOMEM;
  1394. }
  1395. card->long_name = sdw_card_long_name;
  1396. /* Register the card */
  1397. ret = devm_snd_soc_register_card(&pdev->dev, card);
  1398. if (ret) {
  1399. dev_err(card->dev, "snd_soc_register_card failed %d\n", ret);
  1400. mc_dailink_exit_loop(card);
  1401. return ret;
  1402. }
  1403. platform_set_drvdata(pdev, card);
  1404. return ret;
  1405. }
  1406. static int mc_remove(struct platform_device *pdev)
  1407. {
  1408. struct snd_soc_card *card = platform_get_drvdata(pdev);
  1409. mc_dailink_exit_loop(card);
  1410. return 0;
  1411. }
  1412. static struct platform_driver sof_sdw_driver = {
  1413. .driver = {
  1414. .name = "sof_sdw",
  1415. .pm = &snd_soc_pm_ops,
  1416. },
  1417. .probe = mc_probe,
  1418. .remove = mc_remove,
  1419. };
  1420. module_platform_driver(sof_sdw_driver);
  1421. MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
  1422. MODULE_AUTHOR("Bard Liao <[email protected]>");
  1423. MODULE_AUTHOR("Rander Wang <[email protected]>");
  1424. MODULE_AUTHOR("Pierre-Louis Bossart <[email protected]>");
  1425. MODULE_LICENSE("GPL v2");
  1426. MODULE_ALIAS("platform:sof_sdw");
  1427. MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
  1428. MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);