audio-graph-card2.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // ASoC Audio Graph Card2 support
  4. //
  5. // Copyright (C) 2020 Renesas Electronics Corp.
  6. // Copyright (C) 2020 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
  7. //
  8. // based on ${LINUX}/sound/soc/generic/audio-graph-card.c
  9. #include <linux/clk.h>
  10. #include <linux/device.h>
  11. #include <linux/gpio/consumer.h>
  12. #include <linux/module.h>
  13. #include <linux/of.h>
  14. #include <linux/of_graph.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/string.h>
  17. #include <sound/graph_card.h>
  18. /************************************
  19. daifmt
  20. ************************************
  21. ports {
  22. format = "left_j";
  23. port@0 {
  24. bitclock-master;
  25. sample0: endpoint@0 {
  26. frame-master;
  27. };
  28. sample1: endpoint@1 {
  29. format = "i2s";
  30. };
  31. };
  32. ...
  33. };
  34. You can set daifmt at ports/port/endpoint.
  35. It uses *latest* format, and *share* master settings.
  36. In above case,
  37. sample0: left_j, bitclock-master, frame-master
  38. sample1: i2s, bitclock-master
  39. If there was no settings, *Codec* will be
  40. bitclock/frame provider as default.
  41. see
  42. graph_parse_daifmt().
  43. "format" property is no longer needed on DT if both CPU/Codec drivers are
  44. supporting snd_soc_dai_ops :: .auto_selectable_formats.
  45. see
  46. snd_soc_runtime_get_dai_fmt()
  47. sample driver
  48. linux/sound/soc/sh/rcar/core.c
  49. linux/sound/soc/codecs/ak4613.c
  50. linux/sound/soc/codecs/pcm3168a.c
  51. linux/sound/soc/soc-utils.c
  52. linux/sound/soc/generic/test-component.c
  53. ************************************
  54. Normal Audio-Graph
  55. ************************************
  56. CPU <---> Codec
  57. sound {
  58. compatible = "audio-graph-card2";
  59. links = <&cpu>;
  60. };
  61. CPU {
  62. cpu: port {
  63. bitclock-master;
  64. frame-master;
  65. cpu_ep: endpoint { remote-endpoint = <&codec_ep>; }; };
  66. };
  67. Codec {
  68. port { codec_ep: endpoint { remote-endpoint = <&cpu_ep>; }; };
  69. };
  70. ************************************
  71. Multi-CPU/Codec
  72. ************************************
  73. It has link connection part (= X,x) and list part (= A,B,a,b).
  74. "links" is connection part of CPU side (= @).
  75. +----+ +---+
  76. CPU1 --|A X| <-@----> |x a|-- Codec1
  77. CPU2 --|B | | b|-- Codec2
  78. +----+ +---+
  79. sound {
  80. compatible = "audio-graph-card2";
  81. (@) links = <&mcpu>;
  82. multi {
  83. ports@0 {
  84. (@) mcpu: port@0 { mcpu0_ep: endpoint { remote-endpoint = <&mcodec0_ep>; }; }; // (X) to pair
  85. port@1 { mcpu1_ep: endpoint { remote-endpoint = <&cpu1_ep>; }; }; // (A) Multi Element
  86. port@2 { mcpu2_ep: endpoint { remote-endpoint = <&cpu2_ep>; }; }; // (B) Multi Element
  87. };
  88. ports@1 {
  89. port@0 { mcodec0_ep: endpoint { remote-endpoint = <&mcpu0_ep>; }; }; // (x) to pair
  90. port@1 { mcodec1_ep: endpoint { remote-endpoint = <&codec1_ep>; }; }; // (a) Multi Element
  91. port@2 { mcodec2_ep: endpoint { remote-endpoint = <&codec2_ep>; }; }; // (b) Multi Element
  92. };
  93. };
  94. };
  95. CPU {
  96. ports {
  97. bitclock-master;
  98. frame-master;
  99. port@0 { cpu1_ep: endpoint { remote-endpoint = <&mcpu1_ep>; }; };
  100. port@1 { cpu2_ep: endpoint { remote-endpoint = <&mcpu2_ep>; }; };
  101. };
  102. };
  103. Codec {
  104. ports {
  105. port@0 { codec1_ep: endpoint { remote-endpoint = <&mcodec1_ep>; }; };
  106. port@1 { codec2_ep: endpoint { remote-endpoint = <&mcodec2_ep>; }; };
  107. };
  108. };
  109. ************************************
  110. DPCM
  111. ************************************
  112. DSP
  113. ************
  114. PCM0 <--> * fe0 be0 * <--> DAI0: Codec Headset
  115. PCM1 <--> * fe1 be1 * <--> DAI1: Codec Speakers
  116. PCM2 <--> * fe2 be2 * <--> DAI2: MODEM
  117. PCM3 <--> * fe3 be3 * <--> DAI3: BT
  118. * be4 * <--> DAI4: DMIC
  119. * be5 * <--> DAI5: FM
  120. ************
  121. sound {
  122. compatible = "audio-graph-card2";
  123. // indicate routing
  124. routing = "xxx Playback", "xxx Playback",
  125. "xxx Playback", "xxx Playback",
  126. "xxx Playback", "xxx Playback";
  127. // indicate all Front-End, Back-End
  128. links = <&fe0, &fe1, ...,
  129. &be0, &be1, ...>;
  130. dpcm {
  131. // Front-End
  132. ports@0 {
  133. fe0: port@0 { fe0_ep: endpoint { remote-endpoint = <&pcm0_ep>; }; };
  134. fe1: port@1 { fe1_ep: endpoint { remote-endpoint = <&pcm1_ep>; }; };
  135. ...
  136. };
  137. // Back-End
  138. ports@1 {
  139. be0: port@0 { be0_ep: endpoint { remote-endpoint = <&dai0_ep>; }; };
  140. be1: port@1 { be1_ep: endpoint { remote-endpoint = <&dai1_ep>; }; };
  141. ...
  142. };
  143. };
  144. };
  145. CPU {
  146. ports {
  147. bitclock-master;
  148. frame-master;
  149. port@0 { pcm0_ep: endpoint { remote-endpoint = <&fe0_ep>; }; };
  150. port@1 { pcm1_ep: endpoint { remote-endpoint = <&fe1_ep>; }; };
  151. ...
  152. };
  153. };
  154. Codec {
  155. ports {
  156. port@0 { dai0_ep: endpoint { remote-endpoint = <&be0_ep>; }; };
  157. port@1 { dai1_ep: endpoint { remote-endpoint = <&be1_ep>; }; };
  158. ...
  159. };
  160. };
  161. ************************************
  162. Codec to Codec
  163. ************************************
  164. +--+
  165. | |<-- Codec0 <- IN
  166. | |--> Codec1 -> OUT
  167. +--+
  168. sound {
  169. compatible = "audio-graph-card2";
  170. routing = "OUT" ,"DAI1 Playback",
  171. "DAI0 Capture", "IN";
  172. links = <&c2c>;
  173. codec2codec {
  174. ports {
  175. rate = <48000>;
  176. c2c: port@0 { c2cf_ep: endpoint { remote-endpoint = <&codec0_ep>; }; };
  177. port@1 { c2cb_ep: endpoint { remote-endpoint = <&codec1_ep>; }; };
  178. };
  179. };
  180. Codec {
  181. ports {
  182. port@0 {
  183. bitclock-master;
  184. frame-master;
  185. codec0_ep: endpoint { remote-endpoint = <&c2cf_ep>; }; };
  186. port@1 { codec1_ep: endpoint { remote-endpoint = <&c2cb_ep>; }; };
  187. };
  188. };
  189. */
  190. enum graph_type {
  191. GRAPH_NORMAL,
  192. GRAPH_DPCM,
  193. GRAPH_C2C,
  194. GRAPH_MULTI, /* don't use ! Use this only in __graph_get_type() */
  195. };
  196. #define GRAPH_NODENAME_MULTI "multi"
  197. #define GRAPH_NODENAME_DPCM "dpcm"
  198. #define GRAPH_NODENAME_C2C "codec2codec"
  199. #define port_to_endpoint(port) of_get_child_by_name(port, "endpoint")
  200. #define ep_to_port(ep) of_get_parent(ep)
  201. static struct device_node *port_to_ports(struct device_node *port)
  202. {
  203. struct device_node *ports = of_get_parent(port);
  204. if (!of_node_name_eq(ports, "ports")) {
  205. of_node_put(ports);
  206. return NULL;
  207. }
  208. return ports;
  209. }
  210. static enum graph_type __graph_get_type(struct device_node *lnk)
  211. {
  212. struct device_node *np, *parent_np;
  213. enum graph_type ret;
  214. /*
  215. * target {
  216. * ports {
  217. * => lnk: port@0 { ... };
  218. * port@1 { ... };
  219. * };
  220. * };
  221. */
  222. np = of_get_parent(lnk);
  223. if (of_node_name_eq(np, "ports")) {
  224. parent_np = of_get_parent(np);
  225. of_node_put(np);
  226. np = parent_np;
  227. }
  228. if (of_node_name_eq(np, GRAPH_NODENAME_MULTI)) {
  229. ret = GRAPH_MULTI;
  230. fw_devlink_purge_absent_suppliers(&np->fwnode);
  231. goto out_put;
  232. }
  233. if (of_node_name_eq(np, GRAPH_NODENAME_DPCM)) {
  234. ret = GRAPH_DPCM;
  235. fw_devlink_purge_absent_suppliers(&np->fwnode);
  236. goto out_put;
  237. }
  238. if (of_node_name_eq(np, GRAPH_NODENAME_C2C)) {
  239. ret = GRAPH_C2C;
  240. fw_devlink_purge_absent_suppliers(&np->fwnode);
  241. goto out_put;
  242. }
  243. ret = GRAPH_NORMAL;
  244. out_put:
  245. of_node_put(np);
  246. return ret;
  247. }
  248. static enum graph_type graph_get_type(struct simple_util_priv *priv,
  249. struct device_node *lnk)
  250. {
  251. enum graph_type type = __graph_get_type(lnk);
  252. /* GRAPH_MULTI here means GRAPH_NORMAL */
  253. if (type == GRAPH_MULTI)
  254. type = GRAPH_NORMAL;
  255. #ifdef DEBUG
  256. {
  257. struct device *dev = simple_priv_to_dev(priv);
  258. const char *str = "Normal";
  259. switch (type) {
  260. case GRAPH_DPCM:
  261. if (graph_util_is_ports0(lnk))
  262. str = "DPCM Front-End";
  263. else
  264. str = "DPCM Back-End";
  265. break;
  266. case GRAPH_C2C:
  267. str = "Codec2Codec";
  268. break;
  269. default:
  270. break;
  271. }
  272. dev_dbg(dev, "%pOF (%s)", lnk, str);
  273. }
  274. #endif
  275. return type;
  276. }
  277. static int graph_lnk_is_multi(struct device_node *lnk)
  278. {
  279. return __graph_get_type(lnk) == GRAPH_MULTI;
  280. }
  281. static struct device_node *graph_get_next_multi_ep(struct device_node **port)
  282. {
  283. struct device_node *ports = port_to_ports(*port);
  284. struct device_node *ep = NULL;
  285. struct device_node *rep = NULL;
  286. /*
  287. * multi {
  288. * ports {
  289. * => lnk: port@0 { ... }; // to pair
  290. * port@1 { ep { ... = rep0 } }; // Multi Element
  291. * port@2 { ep { ... = rep1 } }; // Multi Element
  292. * ...
  293. * };
  294. * };
  295. *
  296. * xxx {
  297. * port@0 { rep0 };
  298. * port@1 { rep1 };
  299. * };
  300. */
  301. do {
  302. *port = of_get_next_child(ports, *port);
  303. if (!*port)
  304. break;
  305. } while (!of_node_name_eq(*port, "port"));
  306. if (*port) {
  307. ep = port_to_endpoint(*port);
  308. rep = of_graph_get_remote_endpoint(ep);
  309. }
  310. of_node_put(ep);
  311. of_node_put(ports);
  312. return rep;
  313. }
  314. static const struct snd_soc_ops graph_ops = {
  315. .startup = simple_util_startup,
  316. .shutdown = simple_util_shutdown,
  317. .hw_params = simple_util_hw_params,
  318. };
  319. static void graph_parse_convert(struct device_node *ep,
  320. struct simple_dai_props *props)
  321. {
  322. struct device_node *port = ep_to_port(ep);
  323. struct device_node *ports = port_to_ports(port);
  324. struct simple_util_data *adata = &props->adata;
  325. simple_util_parse_convert(ports, NULL, adata);
  326. simple_util_parse_convert(port, NULL, adata);
  327. simple_util_parse_convert(ep, NULL, adata);
  328. of_node_put(port);
  329. of_node_put(ports);
  330. }
  331. static int __graph_parse_node(struct simple_util_priv *priv,
  332. enum graph_type gtype,
  333. struct device_node *ep,
  334. struct link_info *li,
  335. int is_cpu, int idx)
  336. {
  337. struct device *dev = simple_priv_to_dev(priv);
  338. struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
  339. struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
  340. struct snd_soc_dai_link_component *dlc;
  341. struct simple_util_dai *dai;
  342. int ret, is_single_links = 0;
  343. if (is_cpu) {
  344. dlc = snd_soc_link_to_cpu(dai_link, idx);
  345. dai = simple_props_to_dai_cpu(dai_props, idx);
  346. } else {
  347. dlc = snd_soc_link_to_codec(dai_link, idx);
  348. dai = simple_props_to_dai_codec(dai_props, idx);
  349. }
  350. ret = graph_util_parse_dai(dev, ep, dlc, &is_single_links);
  351. if (ret < 0)
  352. return ret;
  353. ret = simple_util_parse_tdm(ep, dai);
  354. if (ret < 0)
  355. return ret;
  356. ret = simple_util_parse_tdm_width_map(dev, ep, dai);
  357. if (ret < 0)
  358. return ret;
  359. ret = simple_util_parse_clk(dev, ep, dai, dlc);
  360. if (ret < 0)
  361. return ret;
  362. /*
  363. * set DAI Name
  364. */
  365. if (!dai_link->name) {
  366. struct snd_soc_dai_link_component *cpus = dlc;
  367. struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, idx);
  368. char *cpu_multi = "";
  369. char *codec_multi = "";
  370. if (dai_link->num_cpus > 1)
  371. cpu_multi = "_multi";
  372. if (dai_link->num_codecs > 1)
  373. codec_multi = "_multi";
  374. switch (gtype) {
  375. case GRAPH_NORMAL:
  376. /* run is_cpu only. see audio_graph2_link_normal() */
  377. if (is_cpu)
  378. simple_util_set_dailink_name(dev, dai_link, "%s%s-%s%s",
  379. cpus->dai_name, cpu_multi,
  380. codecs->dai_name, codec_multi);
  381. break;
  382. case GRAPH_DPCM:
  383. if (is_cpu)
  384. simple_util_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s",
  385. cpus->of_node, cpus->dai_name, cpu_multi);
  386. else
  387. simple_util_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s",
  388. codecs->of_node, codecs->dai_name, codec_multi);
  389. break;
  390. case GRAPH_C2C:
  391. /* run is_cpu only. see audio_graph2_link_c2c() */
  392. if (is_cpu)
  393. simple_util_set_dailink_name(dev, dai_link, "c2c.%s%s-%s%s",
  394. cpus->dai_name, cpu_multi,
  395. codecs->dai_name, codec_multi);
  396. break;
  397. default:
  398. break;
  399. }
  400. }
  401. /*
  402. * Check "prefix" from top node
  403. * if DPCM-BE case
  404. */
  405. if (!is_cpu && gtype == GRAPH_DPCM) {
  406. struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, idx);
  407. struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx);
  408. struct device_node *rport = ep_to_port(ep);
  409. struct device_node *rports = port_to_ports(rport);
  410. snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix");
  411. snd_soc_of_parse_node_prefix(rport, cconf, codecs->of_node, "prefix");
  412. of_node_put(rport);
  413. of_node_put(rports);
  414. }
  415. if (is_cpu) {
  416. struct snd_soc_dai_link_component *cpus = dlc;
  417. struct snd_soc_dai_link_component *platforms = snd_soc_link_to_platform(dai_link, idx);
  418. simple_util_canonicalize_cpu(cpus, is_single_links);
  419. simple_util_canonicalize_platform(platforms, cpus);
  420. }
  421. return 0;
  422. }
  423. static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link,
  424. int *nm_idx, int cpu_idx,
  425. struct device_node *mcpu_port)
  426. {
  427. /*
  428. * +---+ +---+
  429. * | X|<-@------->|x |
  430. * | | | |
  431. * cpu0 <--|A 1|<--------->|4 a|-> codec0
  432. * cpu1 <--|B 2|<-----+--->|5 b|-> codec1
  433. * cpu2 <--|C 3|<----/ +---+
  434. * +---+
  435. *
  436. * multi {
  437. * ports {
  438. * port@0 { mcpu_top_ep {... = mcodec_ep; }; }; // (X) to pair
  439. * <mcpu_port> port@1 { mcpu0_ep { ... = cpu0_ep; }; // (A) Multi Element
  440. * mcpu0_ep_0 { ... = mcodec0_ep_0; }; }; // (1) connected Codec
  441. * port@2 { mcpu1_ep { ... = cpu1_ep; }; // (B) Multi Element
  442. * mcpu1_ep_0 { ... = mcodec1_ep_0; }; }; // (2) connected Codec
  443. * port@3 { mcpu2_ep { ... = cpu2_ep; }; // (C) Multi Element
  444. * mcpu2_ep_0 { ... = mcodec1_ep_1; }; }; // (3) connected Codec
  445. * };
  446. *
  447. * ports {
  448. * port@0 { mcodec_top_ep {... = mcpu_ep; }; }; // (x) to pair
  449. * <mcodec_port>port@1 { mcodec0_ep { ... = codec0_ep; }; // (a) Multi Element
  450. * mcodec0_ep_0 { ... = mcpu0_ep_0; }; }; // (4) connected CPU
  451. * port@2 { mcodec1_ep { ... = codec1_ep; }; // (b) Multi Element
  452. * mcodec1_ep_0 { ... = mcpu1_ep_0; }; // (5) connected CPU
  453. * mcodec1_ep_1 { ... = mcpu2_ep_0; }; }; // (5) connected CPU
  454. * };
  455. * };
  456. */
  457. struct device_node *mcpu_ep = port_to_endpoint(mcpu_port);
  458. struct device_node *mcpu_ep_n = mcpu_ep;
  459. struct device_node *mcpu_port_top = of_get_next_child(port_to_ports(mcpu_port), NULL);
  460. struct device_node *mcpu_ep_top = port_to_endpoint(mcpu_port_top);
  461. struct device_node *mcodec_ep_top = of_graph_get_remote_endpoint(mcpu_ep_top);
  462. struct device_node *mcodec_port_top = ep_to_port(mcodec_ep_top);
  463. struct device_node *mcodec_ports = port_to_ports(mcodec_port_top);
  464. int nm_max = max(dai_link->num_cpus, dai_link->num_codecs);
  465. int ret = -EINVAL;
  466. if (cpu_idx > dai_link->num_cpus)
  467. goto mcpu_err;
  468. while (1) {
  469. struct device_node *mcodec_ep_n;
  470. struct device_node *mcodec_port_i;
  471. struct device_node *mcodec_port;
  472. int codec_idx;
  473. if (*nm_idx > nm_max)
  474. break;
  475. mcpu_ep_n = of_get_next_child(mcpu_port, mcpu_ep_n);
  476. if (!mcpu_ep_n) {
  477. ret = 0;
  478. break;
  479. }
  480. mcodec_ep_n = of_graph_get_remote_endpoint(mcpu_ep_n);
  481. mcodec_port = ep_to_port(mcodec_ep_n);
  482. if (mcodec_ports != port_to_ports(mcodec_port))
  483. goto mcpu_err;
  484. codec_idx = 0;
  485. mcodec_port_i = of_get_next_child(mcodec_ports, NULL);
  486. while (1) {
  487. if (codec_idx > dai_link->num_codecs)
  488. goto mcodec_err;
  489. mcodec_port_i = of_get_next_child(mcodec_ports, mcodec_port_i);
  490. if (!mcodec_port_i)
  491. goto mcodec_err;
  492. if (mcodec_port_i == mcodec_port)
  493. break;
  494. codec_idx++;
  495. }
  496. dai_link->ch_maps[*nm_idx].cpu = cpu_idx;
  497. dai_link->ch_maps[*nm_idx].codec = codec_idx;
  498. (*nm_idx)++;
  499. of_node_put(mcodec_port_i);
  500. mcodec_err:
  501. of_node_put(mcodec_port);
  502. of_node_put(mcpu_ep_n);
  503. of_node_put(mcodec_ep_n);
  504. }
  505. mcpu_err:
  506. of_node_put(mcpu_ep);
  507. of_node_put(mcpu_port_top);
  508. of_node_put(mcpu_ep_top);
  509. of_node_put(mcodec_ep_top);
  510. of_node_put(mcodec_port_top);
  511. of_node_put(mcodec_ports);
  512. return ret;
  513. }
  514. static int graph_parse_node_multi(struct simple_util_priv *priv,
  515. enum graph_type gtype,
  516. struct device_node *port,
  517. struct link_info *li, int is_cpu)
  518. {
  519. struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
  520. struct device *dev = simple_priv_to_dev(priv);
  521. struct device_node *ep;
  522. int ret = -ENOMEM;
  523. int nm_idx = 0;
  524. int nm_max = max(dai_link->num_cpus, dai_link->num_codecs);
  525. /*
  526. * create ch_maps if CPU:Codec = N:M
  527. * DPCM is out of scope
  528. */
  529. if (gtype != GRAPH_DPCM && !dai_link->ch_maps &&
  530. dai_link->num_cpus > 1 && dai_link->num_codecs > 1 &&
  531. dai_link->num_cpus != dai_link->num_codecs) {
  532. dai_link->ch_maps = devm_kcalloc(dev, nm_max,
  533. sizeof(struct snd_soc_dai_link_ch_map), GFP_KERNEL);
  534. if (!dai_link->ch_maps)
  535. goto multi_err;
  536. }
  537. for (int idx = 0;; idx++) {
  538. /*
  539. * multi {
  540. * ports {
  541. * <port> port@0 { ... }; // to pair
  542. * port@1 { mcpu1_ep { ... = cpu1_ep };}; // Multi Element
  543. * port@2 { mcpu2_ep { ... = cpu2_ep };}; // Multi Element
  544. * };
  545. * };
  546. *
  547. * cpu {
  548. * ports {
  549. * <ep> port@0 { cpu1_ep { ... = mcpu1_ep };};
  550. * };
  551. * };
  552. */
  553. ep = graph_get_next_multi_ep(&port);
  554. if (!ep)
  555. break;
  556. ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, idx);
  557. of_node_put(ep);
  558. if (ret < 0)
  559. goto multi_err;
  560. /* CPU:Codec = N:M */
  561. if (is_cpu && dai_link->ch_maps) {
  562. ret = graph_parse_node_multi_nm(dai_link, &nm_idx, idx, port);
  563. if (ret < 0)
  564. goto multi_err;
  565. }
  566. }
  567. if (is_cpu && dai_link->ch_maps && (nm_idx != nm_max))
  568. ret = -EINVAL;
  569. multi_err:
  570. return ret;
  571. }
  572. static int graph_parse_node_single(struct simple_util_priv *priv,
  573. enum graph_type gtype,
  574. struct device_node *port,
  575. struct link_info *li, int is_cpu)
  576. {
  577. struct device_node *ep = port_to_endpoint(port);
  578. int ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, 0);
  579. of_node_put(ep);
  580. return ret;
  581. }
  582. static int graph_parse_node(struct simple_util_priv *priv,
  583. enum graph_type gtype,
  584. struct device_node *port,
  585. struct link_info *li, int is_cpu)
  586. {
  587. if (graph_lnk_is_multi(port))
  588. return graph_parse_node_multi(priv, gtype, port, li, is_cpu);
  589. else
  590. return graph_parse_node_single(priv, gtype, port, li, is_cpu);
  591. }
  592. static void graph_parse_daifmt(struct device_node *node,
  593. unsigned int *daifmt, unsigned int *bit_frame)
  594. {
  595. unsigned int fmt;
  596. if (!node)
  597. return;
  598. /*
  599. * see also above "daifmt" explanation
  600. * and samples.
  601. */
  602. /*
  603. * ports {
  604. * (A)
  605. * port {
  606. * (B)
  607. * endpoint {
  608. * (C)
  609. * };
  610. * };
  611. * };
  612. * };
  613. */
  614. /*
  615. * clock_provider:
  616. *
  617. * It can be judged it is provider
  618. * if (A) or (B) or (C) has bitclock-master / frame-master flag.
  619. *
  620. * use "or"
  621. */
  622. *bit_frame |= snd_soc_daifmt_parse_clock_provider_as_bitmap(node, NULL);
  623. #define update_daifmt(name) \
  624. if (!(*daifmt & SND_SOC_DAIFMT_##name##_MASK) && \
  625. (fmt & SND_SOC_DAIFMT_##name##_MASK)) \
  626. *daifmt |= fmt & SND_SOC_DAIFMT_##name##_MASK
  627. /*
  628. * format
  629. *
  630. * This function is called by (C) -> (B) -> (A) order.
  631. * Set if applicable part was not yet set.
  632. */
  633. fmt = snd_soc_daifmt_parse_format(node, NULL);
  634. update_daifmt(FORMAT);
  635. update_daifmt(CLOCK);
  636. update_daifmt(INV);
  637. }
  638. static void graph_link_init(struct simple_util_priv *priv,
  639. struct device_node *lnk,
  640. struct device_node *port_cpu,
  641. struct device_node *port_codec,
  642. struct link_info *li,
  643. int is_cpu_node)
  644. {
  645. struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
  646. struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
  647. struct device_node *ep_cpu, *ep_codec;
  648. struct device_node *ports_cpu, *ports_codec;
  649. unsigned int daifmt = 0, daiclk = 0;
  650. bool playback_only = 0, capture_only = 0;
  651. enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT;
  652. enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT;
  653. unsigned int bit_frame = 0;
  654. of_node_get(port_cpu);
  655. if (graph_lnk_is_multi(port_cpu)) {
  656. ep_cpu = graph_get_next_multi_ep(&port_cpu);
  657. of_node_put(port_cpu);
  658. port_cpu = ep_to_port(ep_cpu);
  659. } else {
  660. ep_cpu = port_to_endpoint(port_cpu);
  661. }
  662. ports_cpu = port_to_ports(port_cpu);
  663. of_node_get(port_codec);
  664. if (graph_lnk_is_multi(port_codec)) {
  665. ep_codec = graph_get_next_multi_ep(&port_codec);
  666. of_node_put(port_codec);
  667. port_codec = ep_to_port(ep_codec);
  668. } else {
  669. ep_codec = port_to_endpoint(port_codec);
  670. }
  671. ports_codec = port_to_ports(port_codec);
  672. graph_parse_daifmt(ep_cpu, &daifmt, &bit_frame);
  673. graph_parse_daifmt(ep_codec, &daifmt, &bit_frame);
  674. graph_parse_daifmt(port_cpu, &daifmt, &bit_frame);
  675. graph_parse_daifmt(port_codec, &daifmt, &bit_frame);
  676. graph_parse_daifmt(ports_cpu, &daifmt, &bit_frame);
  677. graph_parse_daifmt(ports_codec, &daifmt, &bit_frame);
  678. graph_parse_daifmt(lnk, &daifmt, &bit_frame);
  679. graph_util_parse_link_direction(lnk, &playback_only, &capture_only);
  680. graph_util_parse_link_direction(ports_cpu, &playback_only, &capture_only);
  681. graph_util_parse_link_direction(ports_codec, &playback_only, &capture_only);
  682. graph_util_parse_link_direction(port_cpu, &playback_only, &capture_only);
  683. graph_util_parse_link_direction(port_codec, &playback_only, &capture_only);
  684. graph_util_parse_link_direction(ep_cpu, &playback_only, &capture_only);
  685. graph_util_parse_link_direction(ep_codec, &playback_only, &capture_only);
  686. of_property_read_u32(lnk, "mclk-fs", &dai_props->mclk_fs);
  687. of_property_read_u32(ports_cpu, "mclk-fs", &dai_props->mclk_fs);
  688. of_property_read_u32(ports_codec, "mclk-fs", &dai_props->mclk_fs);
  689. of_property_read_u32(port_cpu, "mclk-fs", &dai_props->mclk_fs);
  690. of_property_read_u32(port_codec, "mclk-fs", &dai_props->mclk_fs);
  691. of_property_read_u32(ep_cpu, "mclk-fs", &dai_props->mclk_fs);
  692. of_property_read_u32(ep_codec, "mclk-fs", &dai_props->mclk_fs);
  693. graph_util_parse_trigger_order(priv, lnk, &trigger_start, &trigger_stop);
  694. graph_util_parse_trigger_order(priv, ports_cpu, &trigger_start, &trigger_stop);
  695. graph_util_parse_trigger_order(priv, ports_codec, &trigger_start, &trigger_stop);
  696. graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop);
  697. graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop);
  698. graph_util_parse_trigger_order(priv, ep_cpu, &trigger_start, &trigger_stop);
  699. graph_util_parse_trigger_order(priv, ep_codec, &trigger_start, &trigger_stop);
  700. /*
  701. * convert bit_frame
  702. * We need to flip clock_provider if it was CPU node,
  703. * because it is Codec base.
  704. */
  705. daiclk = snd_soc_daifmt_clock_provider_from_bitmap(bit_frame);
  706. if (is_cpu_node)
  707. daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk);
  708. dai_link->playback_only = playback_only;
  709. dai_link->capture_only = capture_only;
  710. dai_link->trigger_start = trigger_start;
  711. dai_link->trigger_stop = trigger_stop;
  712. dai_link->dai_fmt = daifmt | daiclk;
  713. dai_link->init = simple_util_dai_init;
  714. dai_link->ops = &graph_ops;
  715. if (priv->ops)
  716. dai_link->ops = priv->ops;
  717. of_node_put(ports_cpu);
  718. of_node_put(ports_codec);
  719. of_node_put(port_cpu);
  720. of_node_put(port_codec);
  721. of_node_put(ep_cpu);
  722. of_node_put(ep_codec);
  723. }
  724. int audio_graph2_link_normal(struct simple_util_priv *priv,
  725. struct device_node *lnk,
  726. struct link_info *li)
  727. {
  728. struct device_node *cpu_port = lnk;
  729. struct device_node *cpu_ep = port_to_endpoint(cpu_port);
  730. struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
  731. int ret;
  732. /*
  733. * call Codec first.
  734. * see
  735. * __graph_parse_node() :: DAI Naming
  736. */
  737. ret = graph_parse_node(priv, GRAPH_NORMAL, codec_port, li, 0);
  738. if (ret < 0)
  739. goto err;
  740. /*
  741. * call CPU, and set DAI Name
  742. */
  743. ret = graph_parse_node(priv, GRAPH_NORMAL, cpu_port, li, 1);
  744. if (ret < 0)
  745. goto err;
  746. graph_link_init(priv, lnk, cpu_port, codec_port, li, 1);
  747. err:
  748. of_node_put(codec_port);
  749. of_node_put(cpu_ep);
  750. return ret;
  751. }
  752. EXPORT_SYMBOL_GPL(audio_graph2_link_normal);
  753. int audio_graph2_link_dpcm(struct simple_util_priv *priv,
  754. struct device_node *lnk,
  755. struct link_info *li)
  756. {
  757. struct device_node *ep = port_to_endpoint(lnk);
  758. struct device_node *rep = of_graph_get_remote_endpoint(ep);
  759. struct device_node *cpu_port = NULL;
  760. struct device_node *codec_port = NULL;
  761. struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
  762. struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
  763. int is_cpu = graph_util_is_ports0(lnk);
  764. int ret;
  765. if (is_cpu) {
  766. cpu_port = of_graph_get_remote_port(ep); /* rport */
  767. /*
  768. * dpcm {
  769. * // Front-End
  770. * ports@0 {
  771. * => lnk: port@0 { ep: { ... = rep }; };
  772. * ...
  773. * };
  774. * // Back-End
  775. * ports@0 {
  776. * ...
  777. * };
  778. * };
  779. *
  780. * CPU {
  781. * rports: ports {
  782. * rport: port@0 { rep: { ... = ep } };
  783. * }
  784. * }
  785. */
  786. /*
  787. * setup CPU here, Codec is already set as dummy.
  788. * see
  789. * simple_util_init_priv()
  790. */
  791. dai_link->dynamic = 1;
  792. dai_link->dpcm_merged_format = 1;
  793. ret = graph_parse_node(priv, GRAPH_DPCM, cpu_port, li, 1);
  794. if (ret)
  795. goto err;
  796. } else {
  797. codec_port = of_graph_get_remote_port(ep); /* rport */
  798. /*
  799. * dpcm {
  800. * // Front-End
  801. * ports@0 {
  802. * ...
  803. * };
  804. * // Back-End
  805. * ports@0 {
  806. * => lnk: port@0 { ep: { ... = rep; }; };
  807. * ...
  808. * };
  809. * };
  810. *
  811. * Codec {
  812. * rports: ports {
  813. * rport: port@0 { rep: { ... = ep; }; };
  814. * }
  815. * }
  816. */
  817. /*
  818. * setup Codec here, CPU is already set as dummy.
  819. * see
  820. * simple_util_init_priv()
  821. */
  822. /* BE settings */
  823. dai_link->no_pcm = 1;
  824. dai_link->be_hw_params_fixup = simple_util_be_hw_params_fixup;
  825. ret = graph_parse_node(priv, GRAPH_DPCM, codec_port, li, 0);
  826. if (ret < 0)
  827. goto err;
  828. }
  829. graph_parse_convert(ep, dai_props); /* at node of <dpcm> */
  830. graph_parse_convert(rep, dai_props); /* at node of <CPU/Codec> */
  831. graph_link_init(priv, lnk, cpu_port, codec_port, li, is_cpu);
  832. err:
  833. of_node_put(ep);
  834. of_node_put(rep);
  835. of_node_put(cpu_port);
  836. of_node_put(codec_port);
  837. return ret;
  838. }
  839. EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm);
  840. int audio_graph2_link_c2c(struct simple_util_priv *priv,
  841. struct device_node *lnk,
  842. struct link_info *li)
  843. {
  844. struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
  845. struct device_node *port0, *port1, *ports;
  846. struct device_node *codec0_port, *codec1_port;
  847. struct device_node *ep0, *ep1;
  848. u32 val = 0;
  849. int ret = -EINVAL;
  850. /*
  851. * codec2codec {
  852. * ports {
  853. * rate = <48000>;
  854. * => lnk: port@0 { c2c0_ep: { ... = codec0_ep; }; };
  855. * port@1 { c2c1_ep: { ... = codec1_ep; }; };
  856. * };
  857. * };
  858. *
  859. * Codec {
  860. * ports {
  861. * port@0 { codec0_ep: ... }; };
  862. * port@1 { codec1_ep: ... }; };
  863. * };
  864. * };
  865. */
  866. of_node_get(lnk);
  867. port0 = lnk;
  868. ports = port_to_ports(port0);
  869. port1 = of_get_next_child(ports, lnk);
  870. /*
  871. * Card2 can use original Codec2Codec settings if DT has.
  872. * It will use default settings if no settings on DT.
  873. * see
  874. * simple_util_init_for_codec2codec()
  875. *
  876. * Add more settings here if needed
  877. */
  878. of_property_read_u32(ports, "rate", &val);
  879. if (val) {
  880. struct device *dev = simple_priv_to_dev(priv);
  881. struct snd_soc_pcm_stream *c2c_conf;
  882. c2c_conf = devm_kzalloc(dev, sizeof(*c2c_conf), GFP_KERNEL);
  883. if (!c2c_conf)
  884. goto err1;
  885. c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */
  886. c2c_conf->rates = SNDRV_PCM_RATE_8000_384000;
  887. c2c_conf->rate_min =
  888. c2c_conf->rate_max = val;
  889. c2c_conf->channels_min =
  890. c2c_conf->channels_max = 2; /* update ME */
  891. dai_link->c2c_params = c2c_conf;
  892. dai_link->num_c2c_params = 1;
  893. }
  894. ep0 = port_to_endpoint(port0);
  895. ep1 = port_to_endpoint(port1);
  896. codec0_port = of_graph_get_remote_port(ep0);
  897. codec1_port = of_graph_get_remote_port(ep1);
  898. /*
  899. * call Codec first.
  900. * see
  901. * __graph_parse_node() :: DAI Naming
  902. */
  903. ret = graph_parse_node(priv, GRAPH_C2C, codec1_port, li, 0);
  904. if (ret < 0)
  905. goto err2;
  906. /*
  907. * call CPU, and set DAI Name
  908. */
  909. ret = graph_parse_node(priv, GRAPH_C2C, codec0_port, li, 1);
  910. if (ret < 0)
  911. goto err2;
  912. graph_link_init(priv, lnk, codec0_port, codec1_port, li, 1);
  913. err2:
  914. of_node_put(ep0);
  915. of_node_put(ep1);
  916. of_node_put(codec0_port);
  917. of_node_put(codec1_port);
  918. err1:
  919. of_node_put(ports);
  920. of_node_put(port0);
  921. of_node_put(port1);
  922. return ret;
  923. }
  924. EXPORT_SYMBOL_GPL(audio_graph2_link_c2c);
  925. static int graph_link(struct simple_util_priv *priv,
  926. struct graph2_custom_hooks *hooks,
  927. enum graph_type gtype,
  928. struct device_node *lnk,
  929. struct link_info *li)
  930. {
  931. struct device *dev = simple_priv_to_dev(priv);
  932. GRAPH2_CUSTOM func = NULL;
  933. int ret = -EINVAL;
  934. switch (gtype) {
  935. case GRAPH_NORMAL:
  936. if (hooks && hooks->custom_normal)
  937. func = hooks->custom_normal;
  938. else
  939. func = audio_graph2_link_normal;
  940. break;
  941. case GRAPH_DPCM:
  942. if (hooks && hooks->custom_dpcm)
  943. func = hooks->custom_dpcm;
  944. else
  945. func = audio_graph2_link_dpcm;
  946. break;
  947. case GRAPH_C2C:
  948. if (hooks && hooks->custom_c2c)
  949. func = hooks->custom_c2c;
  950. else
  951. func = audio_graph2_link_c2c;
  952. break;
  953. default:
  954. break;
  955. }
  956. if (!func) {
  957. dev_err(dev, "non supported gtype (%d)\n", gtype);
  958. goto err;
  959. }
  960. ret = func(priv, lnk, li);
  961. if (ret < 0)
  962. goto err;
  963. li->link++;
  964. err:
  965. return ret;
  966. }
  967. static int graph_counter(struct device_node *lnk)
  968. {
  969. /*
  970. * Multi CPU / Codec
  971. *
  972. * multi {
  973. * ports {
  974. * => lnk: port@0 { ... }; // to pair
  975. * port@1 { ... }; // Multi Element
  976. * port@2 { ... }; // Multi Element
  977. * ...
  978. * };
  979. * };
  980. *
  981. * ignore first lnk part
  982. */
  983. if (graph_lnk_is_multi(lnk)) {
  984. struct device_node *ports = port_to_ports(lnk);
  985. /*
  986. * CPU/Codec = N:M case has many endpoints.
  987. * We can't use of_graph_get_endpoint_count() here
  988. */
  989. return of_get_child_count(ports) - 1;
  990. }
  991. /*
  992. * Single CPU / Codec
  993. */
  994. else
  995. return 1;
  996. }
  997. static int graph_count_normal(struct simple_util_priv *priv,
  998. struct device_node *lnk,
  999. struct link_info *li)
  1000. {
  1001. struct device_node *cpu_port = lnk;
  1002. struct device_node *cpu_ep = port_to_endpoint(cpu_port);
  1003. struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
  1004. /*
  1005. * CPU {
  1006. * => lnk: port { endpoint { .. }; };
  1007. * };
  1008. */
  1009. /*
  1010. * DON'T REMOVE platforms
  1011. * see
  1012. * simple-card.c :: simple_count_noml()
  1013. */
  1014. li->num[li->link].cpus =
  1015. li->num[li->link].platforms = graph_counter(cpu_port);
  1016. li->num[li->link].codecs = graph_counter(codec_port);
  1017. of_node_put(cpu_ep);
  1018. of_node_put(codec_port);
  1019. return 0;
  1020. }
  1021. static int graph_count_dpcm(struct simple_util_priv *priv,
  1022. struct device_node *lnk,
  1023. struct link_info *li)
  1024. {
  1025. struct device_node *ep = port_to_endpoint(lnk);
  1026. struct device_node *rport = of_graph_get_remote_port(ep);
  1027. /*
  1028. * dpcm {
  1029. * // Front-End
  1030. * ports@0 {
  1031. * => lnk: port@0 { endpoint { ... }; };
  1032. * ...
  1033. * };
  1034. * // Back-End
  1035. * ports@1 {
  1036. * => lnk: port@0 { endpoint { ... }; };
  1037. * ...
  1038. * };
  1039. * };
  1040. */
  1041. if (graph_util_is_ports0(lnk)) {
  1042. /*
  1043. * DON'T REMOVE platforms
  1044. * see
  1045. * simple-card.c :: simple_count_noml()
  1046. */
  1047. li->num[li->link].cpus = graph_counter(rport); /* FE */
  1048. li->num[li->link].platforms = graph_counter(rport);
  1049. } else {
  1050. li->num[li->link].codecs = graph_counter(rport); /* BE */
  1051. }
  1052. of_node_put(ep);
  1053. of_node_put(rport);
  1054. return 0;
  1055. }
  1056. static int graph_count_c2c(struct simple_util_priv *priv,
  1057. struct device_node *lnk,
  1058. struct link_info *li)
  1059. {
  1060. struct device_node *ports = port_to_ports(lnk);
  1061. struct device_node *port0 = lnk;
  1062. struct device_node *port1 = of_get_next_child(ports, of_node_get(lnk));
  1063. struct device_node *ep0 = port_to_endpoint(port0);
  1064. struct device_node *ep1 = port_to_endpoint(port1);
  1065. struct device_node *codec0 = of_graph_get_remote_port(ep0);
  1066. struct device_node *codec1 = of_graph_get_remote_port(ep1);
  1067. /*
  1068. * codec2codec {
  1069. * ports {
  1070. * => lnk: port@0 { endpoint { ... }; };
  1071. * port@1 { endpoint { ... }; };
  1072. * };
  1073. * };
  1074. */
  1075. /*
  1076. * DON'T REMOVE platforms
  1077. * see
  1078. * simple-card.c :: simple_count_noml()
  1079. */
  1080. li->num[li->link].cpus =
  1081. li->num[li->link].platforms = graph_counter(codec0);
  1082. li->num[li->link].codecs = graph_counter(codec1);
  1083. of_node_put(ports);
  1084. of_node_put(port1);
  1085. of_node_put(ep0);
  1086. of_node_put(ep1);
  1087. of_node_put(codec0);
  1088. of_node_put(codec1);
  1089. return 0;
  1090. }
  1091. static int graph_count(struct simple_util_priv *priv,
  1092. struct graph2_custom_hooks *hooks,
  1093. enum graph_type gtype,
  1094. struct device_node *lnk,
  1095. struct link_info *li)
  1096. {
  1097. struct device *dev = simple_priv_to_dev(priv);
  1098. GRAPH2_CUSTOM func = NULL;
  1099. int ret = -EINVAL;
  1100. if (li->link >= SNDRV_MAX_LINKS) {
  1101. dev_err(dev, "too many links\n");
  1102. return ret;
  1103. }
  1104. switch (gtype) {
  1105. case GRAPH_NORMAL:
  1106. func = graph_count_normal;
  1107. break;
  1108. case GRAPH_DPCM:
  1109. func = graph_count_dpcm;
  1110. break;
  1111. case GRAPH_C2C:
  1112. func = graph_count_c2c;
  1113. break;
  1114. default:
  1115. break;
  1116. }
  1117. if (!func) {
  1118. dev_err(dev, "non supported gtype (%d)\n", gtype);
  1119. goto err;
  1120. }
  1121. ret = func(priv, lnk, li);
  1122. if (ret < 0)
  1123. goto err;
  1124. li->link++;
  1125. err:
  1126. return ret;
  1127. }
  1128. static int graph_for_each_link(struct simple_util_priv *priv,
  1129. struct graph2_custom_hooks *hooks,
  1130. struct link_info *li,
  1131. int (*func)(struct simple_util_priv *priv,
  1132. struct graph2_custom_hooks *hooks,
  1133. enum graph_type gtype,
  1134. struct device_node *lnk,
  1135. struct link_info *li))
  1136. {
  1137. struct of_phandle_iterator it;
  1138. struct device *dev = simple_priv_to_dev(priv);
  1139. struct device_node *node = dev->of_node;
  1140. struct device_node *lnk;
  1141. enum graph_type gtype;
  1142. int rc, ret;
  1143. /* loop for all listed CPU port */
  1144. of_for_each_phandle(&it, rc, node, "links", NULL, 0) {
  1145. lnk = it.node;
  1146. gtype = graph_get_type(priv, lnk);
  1147. ret = func(priv, hooks, gtype, lnk, li);
  1148. if (ret < 0)
  1149. return ret;
  1150. }
  1151. return 0;
  1152. }
  1153. int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev,
  1154. struct graph2_custom_hooks *hooks)
  1155. {
  1156. struct snd_soc_card *card = simple_priv_to_card(priv);
  1157. int ret;
  1158. struct link_info *li __free(kfree) = kzalloc(sizeof(*li), GFP_KERNEL);
  1159. if (!li)
  1160. return -ENOMEM;
  1161. card->probe = graph_util_card_probe;
  1162. card->owner = THIS_MODULE;
  1163. card->dev = dev;
  1164. if ((hooks) && (hooks)->hook_pre) {
  1165. ret = (hooks)->hook_pre(priv);
  1166. if (ret < 0)
  1167. goto err;
  1168. }
  1169. ret = graph_for_each_link(priv, hooks, li, graph_count);
  1170. if (!li->link)
  1171. ret = -EINVAL;
  1172. if (ret < 0)
  1173. goto err;
  1174. ret = simple_util_init_priv(priv, li);
  1175. if (ret < 0)
  1176. goto err;
  1177. priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW);
  1178. if (IS_ERR(priv->pa_gpio)) {
  1179. ret = PTR_ERR(priv->pa_gpio);
  1180. dev_err(dev, "failed to get amplifier gpio: %d\n", ret);
  1181. goto err;
  1182. }
  1183. ret = simple_util_parse_widgets(card, NULL);
  1184. if (ret < 0)
  1185. goto err;
  1186. ret = simple_util_parse_routing(card, NULL);
  1187. if (ret < 0)
  1188. goto err;
  1189. memset(li, 0, sizeof(*li));
  1190. ret = graph_for_each_link(priv, hooks, li, graph_link);
  1191. if (ret < 0)
  1192. goto err;
  1193. ret = simple_util_parse_card_name(card, NULL);
  1194. if (ret < 0)
  1195. goto err;
  1196. snd_soc_card_set_drvdata(card, priv);
  1197. if ((hooks) && (hooks)->hook_post) {
  1198. ret = (hooks)->hook_post(priv);
  1199. if (ret < 0)
  1200. goto err;
  1201. }
  1202. simple_util_debug_info(priv);
  1203. ret = snd_soc_of_parse_aux_devs(card, "aux-devs");
  1204. if (ret < 0)
  1205. goto err;
  1206. ret = devm_snd_soc_register_card(dev, card);
  1207. err:
  1208. if (ret < 0)
  1209. dev_err_probe(dev, ret, "parse error\n");
  1210. return ret;
  1211. }
  1212. EXPORT_SYMBOL_GPL(audio_graph2_parse_of);
  1213. static int graph_probe(struct platform_device *pdev)
  1214. {
  1215. struct simple_util_priv *priv;
  1216. struct device *dev = &pdev->dev;
  1217. /* Allocate the private data and the DAI link array */
  1218. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  1219. if (!priv)
  1220. return -ENOMEM;
  1221. return audio_graph2_parse_of(priv, dev, NULL);
  1222. }
  1223. static const struct of_device_id graph_of_match[] = {
  1224. { .compatible = "audio-graph-card2", },
  1225. {},
  1226. };
  1227. MODULE_DEVICE_TABLE(of, graph_of_match);
  1228. static struct platform_driver graph_card = {
  1229. .driver = {
  1230. .name = "asoc-audio-graph-card2",
  1231. .pm = &snd_soc_pm_ops,
  1232. .of_match_table = graph_of_match,
  1233. },
  1234. .probe = graph_probe,
  1235. .remove = simple_util_remove,
  1236. };
  1237. module_platform_driver(graph_card);
  1238. MODULE_ALIAS("platform:asoc-audio-graph-card2");
  1239. MODULE_LICENSE("GPL v2");
  1240. MODULE_DESCRIPTION("ASoC Audio Graph Card2");
  1241. MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");