topology.c 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // Copyright(c) 2021 Intel Corporation. All rights reserved.
  4. //
  5. // Authors: Cezary Rojewski <[email protected]>
  6. // Amadeusz Slawinski <[email protected]>
  7. //
  8. #include <linux/firmware.h>
  9. #include <linux/uuid.h>
  10. #include <sound/soc.h>
  11. #include <sound/soc-acpi.h>
  12. #include <sound/soc-topology.h>
  13. #include <uapi/sound/intel/avs/tokens.h>
  14. #include "avs.h"
  15. #include "topology.h"
  16. /* Get pointer to vendor array at the specified offset. */
  17. #define avs_tplg_vendor_array_at(array, offset) \
  18. ((struct snd_soc_tplg_vendor_array *)((u8 *)array + offset))
  19. /* Get pointer to vendor array that is next in line. */
  20. #define avs_tplg_vendor_array_next(array) \
  21. (avs_tplg_vendor_array_at(array, le32_to_cpu((array)->size)))
  22. /*
  23. * Scan provided block of tuples for the specified token. If found,
  24. * @offset is updated with position at which first matching token is
  25. * located.
  26. *
  27. * Returns 0 on success, -ENOENT if not found and error code otherwise.
  28. */
  29. static int
  30. avs_tplg_vendor_array_lookup(struct snd_soc_tplg_vendor_array *tuples,
  31. u32 block_size, u32 token, u32 *offset)
  32. {
  33. u32 pos = 0;
  34. while (block_size > 0) {
  35. struct snd_soc_tplg_vendor_value_elem *tuple;
  36. u32 tuples_size = le32_to_cpu(tuples->size);
  37. if (tuples_size > block_size)
  38. return -EINVAL;
  39. tuple = tuples->value;
  40. if (le32_to_cpu(tuple->token) == token) {
  41. *offset = pos;
  42. return 0;
  43. }
  44. block_size -= tuples_size;
  45. pos += tuples_size;
  46. tuples = avs_tplg_vendor_array_next(tuples);
  47. }
  48. return -ENOENT;
  49. }
  50. /*
  51. * See avs_tplg_vendor_array_lookup() for description.
  52. *
  53. * Behaves exactly like avs_tplg_vendor_lookup() but starts from the
  54. * next vendor array in line. Useful when searching for the finish line
  55. * of an arbitrary entry in a list of entries where each is composed of
  56. * several vendor tuples and a specific token marks the beginning of
  57. * a new entry block.
  58. */
  59. static int
  60. avs_tplg_vendor_array_lookup_next(struct snd_soc_tplg_vendor_array *tuples,
  61. u32 block_size, u32 token, u32 *offset)
  62. {
  63. u32 tuples_size = le32_to_cpu(tuples->size);
  64. int ret;
  65. if (tuples_size > block_size)
  66. return -EINVAL;
  67. tuples = avs_tplg_vendor_array_next(tuples);
  68. block_size -= tuples_size;
  69. ret = avs_tplg_vendor_array_lookup(tuples, block_size, token, offset);
  70. if (!ret)
  71. *offset += tuples_size;
  72. return ret;
  73. }
  74. /*
  75. * Scan provided block of tuples for the specified token which marks
  76. * the border of an entry block. Behavior is similar to
  77. * avs_tplg_vendor_array_lookup() except 0 is also returned if no
  78. * matching token has been found. In such case, returned @size is
  79. * assigned to @block_size as the entire block belongs to the current
  80. * entry.
  81. *
  82. * Returns 0 on success, error code otherwise.
  83. */
  84. static int
  85. avs_tplg_vendor_entry_size(struct snd_soc_tplg_vendor_array *tuples,
  86. u32 block_size, u32 entry_id_token, u32 *size)
  87. {
  88. int ret;
  89. ret = avs_tplg_vendor_array_lookup_next(tuples, block_size, entry_id_token, size);
  90. if (ret == -ENOENT) {
  91. *size = block_size;
  92. ret = 0;
  93. }
  94. return ret;
  95. }
  96. /*
  97. * Vendor tuple parsing descriptor.
  98. *
  99. * @token: vendor specific token that identifies tuple
  100. * @type: tuple type, one of SND_SOC_TPLG_TUPLE_TYPE_XXX
  101. * @offset: offset of a struct's field to initialize
  102. * @parse: parsing function, extracts and assigns value to object's field
  103. */
  104. struct avs_tplg_token_parser {
  105. enum avs_tplg_token token;
  106. u32 type;
  107. u32 offset;
  108. int (*parse)(struct snd_soc_component *comp, void *elem, void *object, u32 offset);
  109. };
  110. static int
  111. avs_parse_uuid_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
  112. {
  113. struct snd_soc_tplg_vendor_uuid_elem *tuple = elem;
  114. guid_t *val = (guid_t *)((u8 *)object + offset);
  115. guid_copy((guid_t *)val, (const guid_t *)&tuple->uuid);
  116. return 0;
  117. }
  118. static int
  119. avs_parse_bool_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
  120. {
  121. struct snd_soc_tplg_vendor_value_elem *tuple = elem;
  122. bool *val = (bool *)((u8 *)object + offset);
  123. *val = le32_to_cpu(tuple->value);
  124. return 0;
  125. }
  126. static int
  127. avs_parse_byte_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
  128. {
  129. struct snd_soc_tplg_vendor_value_elem *tuple = elem;
  130. u8 *val = ((u8 *)object + offset);
  131. *val = le32_to_cpu(tuple->value);
  132. return 0;
  133. }
  134. static int
  135. avs_parse_short_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
  136. {
  137. struct snd_soc_tplg_vendor_value_elem *tuple = elem;
  138. u16 *val = (u16 *)((u8 *)object + offset);
  139. *val = le32_to_cpu(tuple->value);
  140. return 0;
  141. }
  142. static int
  143. avs_parse_word_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
  144. {
  145. struct snd_soc_tplg_vendor_value_elem *tuple = elem;
  146. u32 *val = (u32 *)((u8 *)object + offset);
  147. *val = le32_to_cpu(tuple->value);
  148. return 0;
  149. }
  150. static int
  151. avs_parse_string_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
  152. {
  153. struct snd_soc_tplg_vendor_string_elem *tuple = elem;
  154. char *val = (char *)((u8 *)object + offset);
  155. snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s", tuple->string);
  156. return 0;
  157. }
  158. static int avs_parse_uuid_tokens(struct snd_soc_component *comp, void *object,
  159. const struct avs_tplg_token_parser *parsers, int count,
  160. struct snd_soc_tplg_vendor_array *tuples)
  161. {
  162. struct snd_soc_tplg_vendor_uuid_elem *tuple;
  163. int ret, i, j;
  164. /* Parse element by element. */
  165. for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
  166. tuple = &tuples->uuid[i];
  167. for (j = 0; j < count; j++) {
  168. /* Ignore non-UUID tokens. */
  169. if (parsers[j].type != SND_SOC_TPLG_TUPLE_TYPE_UUID ||
  170. parsers[j].token != le32_to_cpu(tuple->token))
  171. continue;
  172. ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
  173. if (ret)
  174. return ret;
  175. }
  176. }
  177. return 0;
  178. }
  179. static int avs_parse_string_tokens(struct snd_soc_component *comp, void *object,
  180. const struct avs_tplg_token_parser *parsers, int count,
  181. struct snd_soc_tplg_vendor_array *tuples)
  182. {
  183. struct snd_soc_tplg_vendor_string_elem *tuple;
  184. int ret, i, j;
  185. /* Parse element by element. */
  186. for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
  187. tuple = &tuples->string[i];
  188. for (j = 0; j < count; j++) {
  189. /* Ignore non-string tokens. */
  190. if (parsers[j].type != SND_SOC_TPLG_TUPLE_TYPE_STRING ||
  191. parsers[j].token != le32_to_cpu(tuple->token))
  192. continue;
  193. ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
  194. if (ret)
  195. return ret;
  196. }
  197. }
  198. return 0;
  199. }
  200. static int avs_parse_word_tokens(struct snd_soc_component *comp, void *object,
  201. const struct avs_tplg_token_parser *parsers, int count,
  202. struct snd_soc_tplg_vendor_array *tuples)
  203. {
  204. struct snd_soc_tplg_vendor_value_elem *tuple;
  205. int ret, i, j;
  206. /* Parse element by element. */
  207. for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
  208. tuple = &tuples->value[i];
  209. for (j = 0; j < count; j++) {
  210. /* Ignore non-integer tokens. */
  211. if (!(parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_WORD ||
  212. parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT ||
  213. parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_BYTE ||
  214. parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_BOOL))
  215. continue;
  216. if (parsers[j].token != le32_to_cpu(tuple->token))
  217. continue;
  218. ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
  219. if (ret)
  220. return ret;
  221. }
  222. }
  223. return 0;
  224. }
  225. static int avs_parse_tokens(struct snd_soc_component *comp, void *object,
  226. const struct avs_tplg_token_parser *parsers, size_t count,
  227. struct snd_soc_tplg_vendor_array *tuples, int priv_size)
  228. {
  229. int array_size, ret;
  230. while (priv_size > 0) {
  231. array_size = le32_to_cpu(tuples->size);
  232. if (array_size <= 0) {
  233. dev_err(comp->dev, "invalid array size 0x%x\n", array_size);
  234. return -EINVAL;
  235. }
  236. /* Make sure there is enough data before parsing. */
  237. priv_size -= array_size;
  238. if (priv_size < 0) {
  239. dev_err(comp->dev, "invalid array size 0x%x\n", array_size);
  240. return -EINVAL;
  241. }
  242. switch (le32_to_cpu(tuples->type)) {
  243. case SND_SOC_TPLG_TUPLE_TYPE_UUID:
  244. ret = avs_parse_uuid_tokens(comp, object, parsers, count, tuples);
  245. break;
  246. case SND_SOC_TPLG_TUPLE_TYPE_STRING:
  247. ret = avs_parse_string_tokens(comp, object, parsers, count, tuples);
  248. break;
  249. case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
  250. case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
  251. case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
  252. case SND_SOC_TPLG_TUPLE_TYPE_WORD:
  253. ret = avs_parse_word_tokens(comp, object, parsers, count, tuples);
  254. break;
  255. default:
  256. dev_err(comp->dev, "unknown token type %d\n", tuples->type);
  257. ret = -EINVAL;
  258. }
  259. if (ret) {
  260. dev_err(comp->dev, "parsing %zu tokens of %d type failed: %d\n",
  261. count, tuples->type, ret);
  262. return ret;
  263. }
  264. tuples = avs_tplg_vendor_array_next(tuples);
  265. }
  266. return 0;
  267. }
  268. #define AVS_DEFINE_PTR_PARSER(name, type, member) \
  269. static int \
  270. avs_parse_##name##_ptr(struct snd_soc_component *comp, void *elem, void *object, u32 offset) \
  271. { \
  272. struct snd_soc_tplg_vendor_value_elem *tuple = elem; \
  273. struct avs_soc_component *acomp = to_avs_soc_component(comp); \
  274. type **val = (type **)(object + offset); \
  275. u32 idx; \
  276. \
  277. idx = le32_to_cpu(tuple->value); \
  278. if (idx >= acomp->tplg->num_##member) \
  279. return -EINVAL; \
  280. \
  281. *val = &acomp->tplg->member[idx]; \
  282. \
  283. return 0; \
  284. }
  285. AVS_DEFINE_PTR_PARSER(audio_format, struct avs_audio_format, fmts);
  286. AVS_DEFINE_PTR_PARSER(modcfg_base, struct avs_tplg_modcfg_base, modcfgs_base);
  287. AVS_DEFINE_PTR_PARSER(modcfg_ext, struct avs_tplg_modcfg_ext, modcfgs_ext);
  288. AVS_DEFINE_PTR_PARSER(pplcfg, struct avs_tplg_pplcfg, pplcfgs);
  289. AVS_DEFINE_PTR_PARSER(binding, struct avs_tplg_binding, bindings);
  290. static int
  291. parse_audio_format_bitfield(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
  292. {
  293. struct snd_soc_tplg_vendor_value_elem *velem = elem;
  294. struct avs_audio_format *audio_format = object;
  295. switch (offset) {
  296. case AVS_TKN_AFMT_NUM_CHANNELS_U32:
  297. audio_format->num_channels = le32_to_cpu(velem->value);
  298. break;
  299. case AVS_TKN_AFMT_VALID_BIT_DEPTH_U32:
  300. audio_format->valid_bit_depth = le32_to_cpu(velem->value);
  301. break;
  302. case AVS_TKN_AFMT_SAMPLE_TYPE_U32:
  303. audio_format->sample_type = le32_to_cpu(velem->value);
  304. break;
  305. }
  306. return 0;
  307. }
  308. static int parse_link_formatted_string(struct snd_soc_component *comp, void *elem,
  309. void *object, u32 offset)
  310. {
  311. struct snd_soc_tplg_vendor_string_elem *tuple = elem;
  312. struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
  313. char *val = (char *)((u8 *)object + offset);
  314. /*
  315. * Dynamic naming - string formats, e.g.: ssp%d - supported only for
  316. * topologies describing single device e.g.: an I2S codec on SSP0.
  317. */
  318. if (hweight_long(mach->mach_params.i2s_link_mask) != 1)
  319. return avs_parse_string_token(comp, elem, object, offset);
  320. snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, tuple->string,
  321. __ffs(mach->mach_params.i2s_link_mask));
  322. return 0;
  323. }
  324. static int
  325. parse_dictionary_header(struct snd_soc_component *comp,
  326. struct snd_soc_tplg_vendor_array *tuples,
  327. void **dict, u32 *num_entries, size_t entry_size,
  328. u32 num_entries_token)
  329. {
  330. struct snd_soc_tplg_vendor_value_elem *tuple;
  331. /* Dictionary header consists of single tuple - entry count. */
  332. tuple = tuples->value;
  333. if (le32_to_cpu(tuple->token) != num_entries_token) {
  334. dev_err(comp->dev, "invalid dictionary header, expected: %d\n",
  335. num_entries_token);
  336. return -EINVAL;
  337. }
  338. *num_entries = le32_to_cpu(tuple->value);
  339. *dict = devm_kcalloc(comp->card->dev, *num_entries, entry_size, GFP_KERNEL);
  340. if (!*dict)
  341. return -ENOMEM;
  342. return 0;
  343. }
  344. static int
  345. parse_dictionary_entries(struct snd_soc_component *comp,
  346. struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
  347. void *dict, u32 num_entries, size_t entry_size,
  348. u32 entry_id_token,
  349. const struct avs_tplg_token_parser *parsers, size_t num_parsers)
  350. {
  351. void *pos = dict;
  352. int i;
  353. for (i = 0; i < num_entries; i++) {
  354. u32 esize;
  355. int ret;
  356. ret = avs_tplg_vendor_entry_size(tuples, block_size,
  357. entry_id_token, &esize);
  358. if (ret)
  359. return ret;
  360. ret = avs_parse_tokens(comp, pos, parsers, num_parsers, tuples, esize);
  361. if (ret < 0) {
  362. dev_err(comp->dev, "parse entry: %d of type: %d failed: %d\n",
  363. i, entry_id_token, ret);
  364. return ret;
  365. }
  366. pos += entry_size;
  367. block_size -= esize;
  368. tuples = avs_tplg_vendor_array_at(tuples, esize);
  369. }
  370. return 0;
  371. }
  372. static int parse_dictionary(struct snd_soc_component *comp,
  373. struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
  374. void **dict, u32 *num_entries, size_t entry_size,
  375. u32 num_entries_token, u32 entry_id_token,
  376. const struct avs_tplg_token_parser *parsers, size_t num_parsers)
  377. {
  378. int ret;
  379. ret = parse_dictionary_header(comp, tuples, dict, num_entries,
  380. entry_size, num_entries_token);
  381. if (ret)
  382. return ret;
  383. block_size -= le32_to_cpu(tuples->size);
  384. /* With header parsed, move on to parsing entries. */
  385. tuples = avs_tplg_vendor_array_next(tuples);
  386. return parse_dictionary_entries(comp, tuples, block_size, *dict,
  387. *num_entries, entry_size,
  388. entry_id_token, parsers, num_parsers);
  389. }
  390. static const struct avs_tplg_token_parser library_parsers[] = {
  391. {
  392. .token = AVS_TKN_LIBRARY_NAME_STRING,
  393. .type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
  394. .offset = offsetof(struct avs_tplg_library, name),
  395. .parse = avs_parse_string_token,
  396. },
  397. };
  398. static int avs_tplg_parse_libraries(struct snd_soc_component *comp,
  399. struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
  400. {
  401. struct avs_soc_component *acomp = to_avs_soc_component(comp);
  402. struct avs_tplg *tplg = acomp->tplg;
  403. return parse_dictionary(comp, tuples, block_size, (void **)&tplg->libs,
  404. &tplg->num_libs, sizeof(*tplg->libs),
  405. AVS_TKN_MANIFEST_NUM_LIBRARIES_U32,
  406. AVS_TKN_LIBRARY_ID_U32,
  407. library_parsers, ARRAY_SIZE(library_parsers));
  408. }
  409. static const struct avs_tplg_token_parser audio_format_parsers[] = {
  410. {
  411. .token = AVS_TKN_AFMT_SAMPLE_RATE_U32,
  412. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  413. .offset = offsetof(struct avs_audio_format, sampling_freq),
  414. .parse = avs_parse_word_token,
  415. },
  416. {
  417. .token = AVS_TKN_AFMT_BIT_DEPTH_U32,
  418. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  419. .offset = offsetof(struct avs_audio_format, bit_depth),
  420. .parse = avs_parse_word_token,
  421. },
  422. {
  423. .token = AVS_TKN_AFMT_CHANNEL_MAP_U32,
  424. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  425. .offset = offsetof(struct avs_audio_format, channel_map),
  426. .parse = avs_parse_word_token,
  427. },
  428. {
  429. .token = AVS_TKN_AFMT_CHANNEL_CFG_U32,
  430. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  431. .offset = offsetof(struct avs_audio_format, channel_config),
  432. .parse = avs_parse_word_token,
  433. },
  434. {
  435. .token = AVS_TKN_AFMT_INTERLEAVING_U32,
  436. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  437. .offset = offsetof(struct avs_audio_format, interleaving),
  438. .parse = avs_parse_word_token,
  439. },
  440. {
  441. .token = AVS_TKN_AFMT_NUM_CHANNELS_U32,
  442. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  443. .offset = AVS_TKN_AFMT_NUM_CHANNELS_U32,
  444. .parse = parse_audio_format_bitfield,
  445. },
  446. {
  447. .token = AVS_TKN_AFMT_VALID_BIT_DEPTH_U32,
  448. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  449. .offset = AVS_TKN_AFMT_VALID_BIT_DEPTH_U32,
  450. .parse = parse_audio_format_bitfield,
  451. },
  452. {
  453. .token = AVS_TKN_AFMT_SAMPLE_TYPE_U32,
  454. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  455. .offset = AVS_TKN_AFMT_SAMPLE_TYPE_U32,
  456. .parse = parse_audio_format_bitfield,
  457. },
  458. };
  459. static int avs_tplg_parse_audio_formats(struct snd_soc_component *comp,
  460. struct snd_soc_tplg_vendor_array *tuples,
  461. u32 block_size)
  462. {
  463. struct avs_soc_component *acomp = to_avs_soc_component(comp);
  464. struct avs_tplg *tplg = acomp->tplg;
  465. return parse_dictionary(comp, tuples, block_size, (void **)&tplg->fmts,
  466. &tplg->num_fmts, sizeof(*tplg->fmts),
  467. AVS_TKN_MANIFEST_NUM_AFMTS_U32,
  468. AVS_TKN_AFMT_ID_U32,
  469. audio_format_parsers, ARRAY_SIZE(audio_format_parsers));
  470. }
  471. static const struct avs_tplg_token_parser modcfg_base_parsers[] = {
  472. {
  473. .token = AVS_TKN_MODCFG_BASE_CPC_U32,
  474. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  475. .offset = offsetof(struct avs_tplg_modcfg_base, cpc),
  476. .parse = avs_parse_word_token,
  477. },
  478. {
  479. .token = AVS_TKN_MODCFG_BASE_IBS_U32,
  480. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  481. .offset = offsetof(struct avs_tplg_modcfg_base, ibs),
  482. .parse = avs_parse_word_token,
  483. },
  484. {
  485. .token = AVS_TKN_MODCFG_BASE_OBS_U32,
  486. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  487. .offset = offsetof(struct avs_tplg_modcfg_base, obs),
  488. .parse = avs_parse_word_token,
  489. },
  490. {
  491. .token = AVS_TKN_MODCFG_BASE_PAGES_U32,
  492. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  493. .offset = offsetof(struct avs_tplg_modcfg_base, is_pages),
  494. .parse = avs_parse_word_token,
  495. },
  496. };
  497. static int avs_tplg_parse_modcfgs_base(struct snd_soc_component *comp,
  498. struct snd_soc_tplg_vendor_array *tuples,
  499. u32 block_size)
  500. {
  501. struct avs_soc_component *acomp = to_avs_soc_component(comp);
  502. struct avs_tplg *tplg = acomp->tplg;
  503. return parse_dictionary(comp, tuples, block_size, (void **)&tplg->modcfgs_base,
  504. &tplg->num_modcfgs_base, sizeof(*tplg->modcfgs_base),
  505. AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32,
  506. AVS_TKN_MODCFG_BASE_ID_U32,
  507. modcfg_base_parsers, ARRAY_SIZE(modcfg_base_parsers));
  508. }
  509. static const struct avs_tplg_token_parser modcfg_ext_parsers[] = {
  510. {
  511. .token = AVS_TKN_MODCFG_EXT_TYPE_UUID,
  512. .type = SND_SOC_TPLG_TUPLE_TYPE_UUID,
  513. .offset = offsetof(struct avs_tplg_modcfg_ext, type),
  514. .parse = avs_parse_uuid_token,
  515. },
  516. {
  517. .token = AVS_TKN_MODCFG_CPR_OUT_AFMT_ID_U32,
  518. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  519. .offset = offsetof(struct avs_tplg_modcfg_ext, copier.out_fmt),
  520. .parse = avs_parse_audio_format_ptr,
  521. },
  522. {
  523. .token = AVS_TKN_MODCFG_CPR_FEATURE_MASK_U32,
  524. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  525. .offset = offsetof(struct avs_tplg_modcfg_ext, copier.feature_mask),
  526. .parse = avs_parse_word_token,
  527. },
  528. {
  529. .token = AVS_TKN_MODCFG_CPR_VINDEX_U8,
  530. .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
  531. .offset = offsetof(struct avs_tplg_modcfg_ext, copier.vindex),
  532. .parse = avs_parse_byte_token,
  533. },
  534. {
  535. .token = AVS_TKN_MODCFG_CPR_DMA_TYPE_U32,
  536. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  537. .offset = offsetof(struct avs_tplg_modcfg_ext, copier.dma_type),
  538. .parse = avs_parse_word_token,
  539. },
  540. {
  541. .token = AVS_TKN_MODCFG_CPR_DMABUFF_SIZE_U32,
  542. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  543. .offset = offsetof(struct avs_tplg_modcfg_ext, copier.dma_buffer_size),
  544. .parse = avs_parse_word_token,
  545. },
  546. {
  547. .token = AVS_TKN_MODCFG_CPR_BLOB_FMT_ID_U32,
  548. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  549. .offset = offsetof(struct avs_tplg_modcfg_ext, copier.blob_fmt),
  550. .parse = avs_parse_audio_format_ptr,
  551. },
  552. {
  553. .token = AVS_TKN_MODCFG_MICSEL_OUT_AFMT_ID_U32,
  554. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  555. .offset = offsetof(struct avs_tplg_modcfg_ext, micsel.out_fmt),
  556. .parse = avs_parse_audio_format_ptr,
  557. },
  558. {
  559. .token = AVS_TKN_MODCFG_INTELWOV_CPC_LP_MODE_U32,
  560. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  561. .offset = offsetof(struct avs_tplg_modcfg_ext, wov.cpc_lp_mode),
  562. .parse = avs_parse_word_token,
  563. },
  564. {
  565. .token = AVS_TKN_MODCFG_SRC_OUT_FREQ_U32,
  566. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  567. .offset = offsetof(struct avs_tplg_modcfg_ext, src.out_freq),
  568. .parse = avs_parse_word_token,
  569. },
  570. {
  571. .token = AVS_TKN_MODCFG_MUX_REF_AFMT_ID_U32,
  572. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  573. .offset = offsetof(struct avs_tplg_modcfg_ext, mux.ref_fmt),
  574. .parse = avs_parse_audio_format_ptr,
  575. },
  576. {
  577. .token = AVS_TKN_MODCFG_MUX_OUT_AFMT_ID_U32,
  578. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  579. .offset = offsetof(struct avs_tplg_modcfg_ext, mux.out_fmt),
  580. .parse = avs_parse_audio_format_ptr,
  581. },
  582. {
  583. .token = AVS_TKN_MODCFG_AEC_REF_AFMT_ID_U32,
  584. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  585. .offset = offsetof(struct avs_tplg_modcfg_ext, aec.ref_fmt),
  586. .parse = avs_parse_audio_format_ptr,
  587. },
  588. {
  589. .token = AVS_TKN_MODCFG_AEC_OUT_AFMT_ID_U32,
  590. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  591. .offset = offsetof(struct avs_tplg_modcfg_ext, aec.out_fmt),
  592. .parse = avs_parse_audio_format_ptr,
  593. },
  594. {
  595. .token = AVS_TKN_MODCFG_AEC_CPC_LP_MODE_U32,
  596. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  597. .offset = offsetof(struct avs_tplg_modcfg_ext, aec.cpc_lp_mode),
  598. .parse = avs_parse_word_token,
  599. },
  600. {
  601. .token = AVS_TKN_MODCFG_ASRC_OUT_FREQ_U32,
  602. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  603. .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.out_freq),
  604. .parse = avs_parse_word_token,
  605. },
  606. {
  607. .token = AVS_TKN_MODCFG_ASRC_MODE_U8,
  608. .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
  609. .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.mode),
  610. .parse = avs_parse_byte_token,
  611. },
  612. {
  613. .token = AVS_TKN_MODCFG_ASRC_DISABLE_JITTER_U8,
  614. .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
  615. .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.disable_jitter_buffer),
  616. .parse = avs_parse_byte_token,
  617. },
  618. {
  619. .token = AVS_TKN_MODCFG_UPDOWN_MIX_OUT_CHAN_CFG_U32,
  620. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  621. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.out_channel_config),
  622. .parse = avs_parse_word_token,
  623. },
  624. {
  625. .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_SELECT_U32,
  626. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  627. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients_select),
  628. .parse = avs_parse_word_token,
  629. },
  630. {
  631. .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_0_S32,
  632. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  633. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[0]),
  634. .parse = avs_parse_word_token,
  635. },
  636. {
  637. .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_1_S32,
  638. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  639. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[1]),
  640. .parse = avs_parse_word_token,
  641. },
  642. {
  643. .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_2_S32,
  644. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  645. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[2]),
  646. .parse = avs_parse_word_token,
  647. },
  648. {
  649. .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_3_S32,
  650. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  651. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[3]),
  652. .parse = avs_parse_word_token,
  653. },
  654. {
  655. .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_4_S32,
  656. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  657. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[4]),
  658. .parse = avs_parse_word_token,
  659. },
  660. {
  661. .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_5_S32,
  662. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  663. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[5]),
  664. .parse = avs_parse_word_token,
  665. },
  666. {
  667. .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_6_S32,
  668. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  669. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[6]),
  670. .parse = avs_parse_word_token,
  671. },
  672. {
  673. .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_7_S32,
  674. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  675. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[7]),
  676. .parse = avs_parse_word_token,
  677. },
  678. {
  679. .token = AVS_TKN_MODCFG_UPDOWN_MIX_CHAN_MAP_U32,
  680. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  681. .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.channel_map),
  682. .parse = avs_parse_word_token,
  683. },
  684. {
  685. .token = AVS_TKN_MODCFG_EXT_NUM_INPUT_PINS_U16,
  686. .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
  687. .offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_input_pins),
  688. .parse = avs_parse_short_token,
  689. },
  690. {
  691. .token = AVS_TKN_MODCFG_EXT_NUM_OUTPUT_PINS_U16,
  692. .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
  693. .offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_output_pins),
  694. .parse = avs_parse_short_token,
  695. },
  696. };
  697. static const struct avs_tplg_token_parser pin_format_parsers[] = {
  698. {
  699. .token = AVS_TKN_PIN_FMT_INDEX_U32,
  700. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  701. .offset = offsetof(struct avs_tplg_pin_format, pin_index),
  702. .parse = avs_parse_word_token,
  703. },
  704. {
  705. .token = AVS_TKN_PIN_FMT_IOBS_U32,
  706. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  707. .offset = offsetof(struct avs_tplg_pin_format, iobs),
  708. .parse = avs_parse_word_token,
  709. },
  710. {
  711. .token = AVS_TKN_PIN_FMT_AFMT_ID_U32,
  712. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  713. .offset = offsetof(struct avs_tplg_pin_format, fmt),
  714. .parse = avs_parse_audio_format_ptr,
  715. },
  716. };
  717. static void
  718. assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcfg_ext *cfg)
  719. {
  720. struct snd_soc_acpi_mach *mach;
  721. if (!guid_equal(&cfg->type, &AVS_COPIER_MOD_UUID))
  722. return;
  723. /* Only I2S boards assign port instance in ->i2s_link_mask. */
  724. switch (cfg->copier.dma_type) {
  725. case AVS_DMA_I2S_LINK_OUTPUT:
  726. case AVS_DMA_I2S_LINK_INPUT:
  727. break;
  728. default:
  729. return;
  730. }
  731. mach = dev_get_platdata(comp->card->dev);
  732. /* Automatic assignment only when board describes single SSP. */
  733. if (hweight_long(mach->mach_params.i2s_link_mask) == 1 && !cfg->copier.vindex.i2s.instance)
  734. cfg->copier.vindex.i2s.instance = __ffs(mach->mach_params.i2s_link_mask);
  735. }
  736. static int avs_tplg_parse_modcfg_ext(struct snd_soc_component *comp,
  737. struct avs_tplg_modcfg_ext *cfg,
  738. struct snd_soc_tplg_vendor_array *tuples,
  739. u32 block_size)
  740. {
  741. u32 esize;
  742. int ret;
  743. /* See where pin block starts. */
  744. ret = avs_tplg_vendor_entry_size(tuples, block_size,
  745. AVS_TKN_PIN_FMT_INDEX_U32, &esize);
  746. if (ret)
  747. return ret;
  748. ret = avs_parse_tokens(comp, cfg, modcfg_ext_parsers,
  749. ARRAY_SIZE(modcfg_ext_parsers), tuples, esize);
  750. if (ret)
  751. return ret;
  752. /* Update copier gateway based on board's i2s_link_mask. */
  753. assign_copier_gtw_instance(comp, cfg);
  754. block_size -= esize;
  755. /* Parse trailing in/out pin formats if any. */
  756. if (block_size) {
  757. struct avs_tplg_pin_format *pins;
  758. u32 num_pins;
  759. num_pins = cfg->generic.num_input_pins + cfg->generic.num_output_pins;
  760. if (!num_pins)
  761. return -EINVAL;
  762. pins = devm_kcalloc(comp->card->dev, num_pins, sizeof(*pins), GFP_KERNEL);
  763. if (!pins)
  764. return -ENOMEM;
  765. tuples = avs_tplg_vendor_array_at(tuples, esize);
  766. ret = parse_dictionary_entries(comp, tuples, block_size,
  767. pins, num_pins, sizeof(*pins),
  768. AVS_TKN_PIN_FMT_INDEX_U32,
  769. pin_format_parsers,
  770. ARRAY_SIZE(pin_format_parsers));
  771. if (ret)
  772. return ret;
  773. cfg->generic.pin_fmts = pins;
  774. }
  775. return 0;
  776. }
  777. static int avs_tplg_parse_modcfgs_ext(struct snd_soc_component *comp,
  778. struct snd_soc_tplg_vendor_array *tuples,
  779. u32 block_size)
  780. {
  781. struct avs_soc_component *acomp = to_avs_soc_component(comp);
  782. struct avs_tplg *tplg = acomp->tplg;
  783. int ret, i;
  784. ret = parse_dictionary_header(comp, tuples, (void **)&tplg->modcfgs_ext,
  785. &tplg->num_modcfgs_ext,
  786. sizeof(*tplg->modcfgs_ext),
  787. AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32);
  788. if (ret)
  789. return ret;
  790. block_size -= le32_to_cpu(tuples->size);
  791. /* With header parsed, move on to parsing entries. */
  792. tuples = avs_tplg_vendor_array_next(tuples);
  793. for (i = 0; i < tplg->num_modcfgs_ext; i++) {
  794. struct avs_tplg_modcfg_ext *cfg = &tplg->modcfgs_ext[i];
  795. u32 esize;
  796. ret = avs_tplg_vendor_entry_size(tuples, block_size,
  797. AVS_TKN_MODCFG_EXT_ID_U32, &esize);
  798. if (ret)
  799. return ret;
  800. ret = avs_tplg_parse_modcfg_ext(comp, cfg, tuples, esize);
  801. if (ret)
  802. return ret;
  803. block_size -= esize;
  804. tuples = avs_tplg_vendor_array_at(tuples, esize);
  805. }
  806. return 0;
  807. }
  808. static const struct avs_tplg_token_parser pplcfg_parsers[] = {
  809. {
  810. .token = AVS_TKN_PPLCFG_REQ_SIZE_U16,
  811. .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
  812. .offset = offsetof(struct avs_tplg_pplcfg, req_size),
  813. .parse = avs_parse_short_token,
  814. },
  815. {
  816. .token = AVS_TKN_PPLCFG_PRIORITY_U8,
  817. .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
  818. .offset = offsetof(struct avs_tplg_pplcfg, priority),
  819. .parse = avs_parse_byte_token,
  820. },
  821. {
  822. .token = AVS_TKN_PPLCFG_LOW_POWER_BOOL,
  823. .type = SND_SOC_TPLG_TUPLE_TYPE_BOOL,
  824. .offset = offsetof(struct avs_tplg_pplcfg, lp),
  825. .parse = avs_parse_bool_token,
  826. },
  827. {
  828. .token = AVS_TKN_PPLCFG_ATTRIBUTES_U16,
  829. .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
  830. .offset = offsetof(struct avs_tplg_pplcfg, attributes),
  831. .parse = avs_parse_short_token,
  832. },
  833. {
  834. .token = AVS_TKN_PPLCFG_TRIGGER_U32,
  835. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  836. .offset = offsetof(struct avs_tplg_pplcfg, trigger),
  837. .parse = avs_parse_word_token,
  838. },
  839. };
  840. static int avs_tplg_parse_pplcfgs(struct snd_soc_component *comp,
  841. struct snd_soc_tplg_vendor_array *tuples,
  842. u32 block_size)
  843. {
  844. struct avs_soc_component *acomp = to_avs_soc_component(comp);
  845. struct avs_tplg *tplg = acomp->tplg;
  846. return parse_dictionary(comp, tuples, block_size, (void **)&tplg->pplcfgs,
  847. &tplg->num_pplcfgs, sizeof(*tplg->pplcfgs),
  848. AVS_TKN_MANIFEST_NUM_PPLCFGS_U32,
  849. AVS_TKN_PPLCFG_ID_U32,
  850. pplcfg_parsers, ARRAY_SIZE(pplcfg_parsers));
  851. }
  852. static const struct avs_tplg_token_parser binding_parsers[] = {
  853. {
  854. .token = AVS_TKN_BINDING_TARGET_TPLG_NAME_STRING,
  855. .type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
  856. .offset = offsetof(struct avs_tplg_binding, target_tplg_name),
  857. .parse = parse_link_formatted_string,
  858. },
  859. {
  860. .token = AVS_TKN_BINDING_TARGET_PATH_TMPL_ID_U32,
  861. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  862. .offset = offsetof(struct avs_tplg_binding, target_path_tmpl_id),
  863. .parse = avs_parse_word_token,
  864. },
  865. {
  866. .token = AVS_TKN_BINDING_TARGET_PPL_ID_U32,
  867. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  868. .offset = offsetof(struct avs_tplg_binding, target_ppl_id),
  869. .parse = avs_parse_word_token,
  870. },
  871. {
  872. .token = AVS_TKN_BINDING_TARGET_MOD_ID_U32,
  873. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  874. .offset = offsetof(struct avs_tplg_binding, target_mod_id),
  875. .parse = avs_parse_word_token,
  876. },
  877. {
  878. .token = AVS_TKN_BINDING_TARGET_MOD_PIN_U8,
  879. .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
  880. .offset = offsetof(struct avs_tplg_binding, target_mod_pin),
  881. .parse = avs_parse_byte_token,
  882. },
  883. {
  884. .token = AVS_TKN_BINDING_MOD_ID_U32,
  885. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  886. .offset = offsetof(struct avs_tplg_binding, mod_id),
  887. .parse = avs_parse_word_token,
  888. },
  889. {
  890. .token = AVS_TKN_BINDING_MOD_PIN_U8,
  891. .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
  892. .offset = offsetof(struct avs_tplg_binding, mod_pin),
  893. .parse = avs_parse_byte_token,
  894. },
  895. {
  896. .token = AVS_TKN_BINDING_IS_SINK_U8,
  897. .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
  898. .offset = offsetof(struct avs_tplg_binding, is_sink),
  899. .parse = avs_parse_byte_token,
  900. },
  901. };
  902. static int avs_tplg_parse_bindings(struct snd_soc_component *comp,
  903. struct snd_soc_tplg_vendor_array *tuples,
  904. u32 block_size)
  905. {
  906. struct avs_soc_component *acomp = to_avs_soc_component(comp);
  907. struct avs_tplg *tplg = acomp->tplg;
  908. return parse_dictionary(comp, tuples, block_size, (void **)&tplg->bindings,
  909. &tplg->num_bindings, sizeof(*tplg->bindings),
  910. AVS_TKN_MANIFEST_NUM_BINDINGS_U32,
  911. AVS_TKN_BINDING_ID_U32,
  912. binding_parsers, ARRAY_SIZE(binding_parsers));
  913. }
  914. static const struct avs_tplg_token_parser module_parsers[] = {
  915. {
  916. .token = AVS_TKN_MOD_ID_U32,
  917. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  918. .offset = offsetof(struct avs_tplg_module, id),
  919. .parse = avs_parse_word_token,
  920. },
  921. {
  922. .token = AVS_TKN_MOD_MODCFG_BASE_ID_U32,
  923. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  924. .offset = offsetof(struct avs_tplg_module, cfg_base),
  925. .parse = avs_parse_modcfg_base_ptr,
  926. },
  927. {
  928. .token = AVS_TKN_MOD_IN_AFMT_ID_U32,
  929. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  930. .offset = offsetof(struct avs_tplg_module, in_fmt),
  931. .parse = avs_parse_audio_format_ptr,
  932. },
  933. {
  934. .token = AVS_TKN_MOD_CORE_ID_U8,
  935. .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
  936. .offset = offsetof(struct avs_tplg_module, core_id),
  937. .parse = avs_parse_byte_token,
  938. },
  939. {
  940. .token = AVS_TKN_MOD_PROC_DOMAIN_U8,
  941. .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
  942. .offset = offsetof(struct avs_tplg_module, domain),
  943. .parse = avs_parse_byte_token,
  944. },
  945. {
  946. .token = AVS_TKN_MOD_MODCFG_EXT_ID_U32,
  947. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  948. .offset = offsetof(struct avs_tplg_module, cfg_ext),
  949. .parse = avs_parse_modcfg_ext_ptr,
  950. },
  951. };
  952. static struct avs_tplg_module *
  953. avs_tplg_module_create(struct snd_soc_component *comp, struct avs_tplg_pipeline *owner,
  954. struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
  955. {
  956. struct avs_tplg_module *module;
  957. int ret;
  958. module = devm_kzalloc(comp->card->dev, sizeof(*module), GFP_KERNEL);
  959. if (!module)
  960. return ERR_PTR(-ENOMEM);
  961. ret = avs_parse_tokens(comp, module, module_parsers,
  962. ARRAY_SIZE(module_parsers), tuples, block_size);
  963. if (ret < 0)
  964. return ERR_PTR(ret);
  965. module->owner = owner;
  966. INIT_LIST_HEAD(&module->node);
  967. return module;
  968. }
  969. static const struct avs_tplg_token_parser pipeline_parsers[] = {
  970. {
  971. .token = AVS_TKN_PPL_ID_U32,
  972. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  973. .offset = offsetof(struct avs_tplg_pipeline, id),
  974. .parse = avs_parse_word_token,
  975. },
  976. {
  977. .token = AVS_TKN_PPL_PPLCFG_ID_U32,
  978. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  979. .offset = offsetof(struct avs_tplg_pipeline, cfg),
  980. .parse = avs_parse_pplcfg_ptr,
  981. },
  982. {
  983. .token = AVS_TKN_PPL_NUM_BINDING_IDS_U32,
  984. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  985. .offset = offsetof(struct avs_tplg_pipeline, num_bindings),
  986. .parse = avs_parse_word_token,
  987. },
  988. };
  989. static const struct avs_tplg_token_parser bindings_parsers[] = {
  990. {
  991. .token = AVS_TKN_PPL_BINDING_ID_U32,
  992. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  993. .offset = 0, /* to treat pipeline->bindings as dictionary */
  994. .parse = avs_parse_binding_ptr,
  995. },
  996. };
  997. static struct avs_tplg_pipeline *
  998. avs_tplg_pipeline_create(struct snd_soc_component *comp, struct avs_tplg_path *owner,
  999. struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
  1000. {
  1001. struct avs_tplg_pipeline *pipeline;
  1002. u32 modblk_size, offset;
  1003. int ret;
  1004. pipeline = devm_kzalloc(comp->card->dev, sizeof(*pipeline), GFP_KERNEL);
  1005. if (!pipeline)
  1006. return ERR_PTR(-ENOMEM);
  1007. pipeline->owner = owner;
  1008. INIT_LIST_HEAD(&pipeline->mod_list);
  1009. /* Pipeline header MUST be followed by at least one module. */
  1010. ret = avs_tplg_vendor_array_lookup(tuples, block_size,
  1011. AVS_TKN_MOD_ID_U32, &offset);
  1012. if (!ret && !offset)
  1013. ret = -EINVAL;
  1014. if (ret)
  1015. return ERR_PTR(ret);
  1016. /* Process header which precedes module sections. */
  1017. ret = avs_parse_tokens(comp, pipeline, pipeline_parsers,
  1018. ARRAY_SIZE(pipeline_parsers), tuples, offset);
  1019. if (ret < 0)
  1020. return ERR_PTR(ret);
  1021. block_size -= offset;
  1022. tuples = avs_tplg_vendor_array_at(tuples, offset);
  1023. /* Optionally, binding sections follow module ones. */
  1024. ret = avs_tplg_vendor_array_lookup_next(tuples, block_size,
  1025. AVS_TKN_PPL_BINDING_ID_U32, &offset);
  1026. if (ret) {
  1027. if (ret != -ENOENT)
  1028. return ERR_PTR(ret);
  1029. /* Does header information match actual block layout? */
  1030. if (pipeline->num_bindings)
  1031. return ERR_PTR(-EINVAL);
  1032. modblk_size = block_size;
  1033. } else {
  1034. pipeline->bindings = devm_kcalloc(comp->card->dev, pipeline->num_bindings,
  1035. sizeof(*pipeline->bindings), GFP_KERNEL);
  1036. if (!pipeline->bindings)
  1037. return ERR_PTR(-ENOMEM);
  1038. modblk_size = offset;
  1039. }
  1040. block_size -= modblk_size;
  1041. do {
  1042. struct avs_tplg_module *module;
  1043. u32 esize;
  1044. ret = avs_tplg_vendor_entry_size(tuples, modblk_size,
  1045. AVS_TKN_MOD_ID_U32, &esize);
  1046. if (ret)
  1047. return ERR_PTR(ret);
  1048. module = avs_tplg_module_create(comp, pipeline, tuples, esize);
  1049. if (IS_ERR(module)) {
  1050. dev_err(comp->dev, "parse module failed: %ld\n",
  1051. PTR_ERR(module));
  1052. return ERR_CAST(module);
  1053. }
  1054. list_add_tail(&module->node, &pipeline->mod_list);
  1055. modblk_size -= esize;
  1056. tuples = avs_tplg_vendor_array_at(tuples, esize);
  1057. } while (modblk_size > 0);
  1058. /* What's left is optional range of bindings. */
  1059. ret = parse_dictionary_entries(comp, tuples, block_size, pipeline->bindings,
  1060. pipeline->num_bindings, sizeof(*pipeline->bindings),
  1061. AVS_TKN_PPL_BINDING_ID_U32,
  1062. bindings_parsers, ARRAY_SIZE(bindings_parsers));
  1063. if (ret)
  1064. return ERR_PTR(ret);
  1065. return pipeline;
  1066. }
  1067. static const struct avs_tplg_token_parser path_parsers[] = {
  1068. {
  1069. .token = AVS_TKN_PATH_ID_U32,
  1070. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  1071. .offset = offsetof(struct avs_tplg_path, id),
  1072. .parse = avs_parse_word_token,
  1073. },
  1074. {
  1075. .token = AVS_TKN_PATH_FE_FMT_ID_U32,
  1076. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  1077. .offset = offsetof(struct avs_tplg_path, fe_fmt),
  1078. .parse = avs_parse_audio_format_ptr,
  1079. },
  1080. {
  1081. .token = AVS_TKN_PATH_BE_FMT_ID_U32,
  1082. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  1083. .offset = offsetof(struct avs_tplg_path, be_fmt),
  1084. .parse = avs_parse_audio_format_ptr,
  1085. },
  1086. };
  1087. static struct avs_tplg_path *
  1088. avs_tplg_path_create(struct snd_soc_component *comp, struct avs_tplg_path_template *owner,
  1089. struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
  1090. const struct avs_tplg_token_parser *parsers, u32 num_parsers)
  1091. {
  1092. struct avs_tplg_pipeline *pipeline;
  1093. struct avs_tplg_path *path;
  1094. u32 offset;
  1095. int ret;
  1096. path = devm_kzalloc(comp->card->dev, sizeof(*path), GFP_KERNEL);
  1097. if (!path)
  1098. return ERR_PTR(-ENOMEM);
  1099. path->owner = owner;
  1100. INIT_LIST_HEAD(&path->ppl_list);
  1101. INIT_LIST_HEAD(&path->node);
  1102. /* Path header MAY be followed by one or more pipelines. */
  1103. ret = avs_tplg_vendor_array_lookup(tuples, block_size,
  1104. AVS_TKN_PPL_ID_U32, &offset);
  1105. if (ret == -ENOENT)
  1106. offset = block_size;
  1107. else if (ret)
  1108. return ERR_PTR(ret);
  1109. else if (!offset)
  1110. return ERR_PTR(-EINVAL);
  1111. /* Process header which precedes pipeline sections. */
  1112. ret = avs_parse_tokens(comp, path, parsers, num_parsers, tuples, offset);
  1113. if (ret < 0)
  1114. return ERR_PTR(ret);
  1115. block_size -= offset;
  1116. tuples = avs_tplg_vendor_array_at(tuples, offset);
  1117. while (block_size > 0) {
  1118. u32 esize;
  1119. ret = avs_tplg_vendor_entry_size(tuples, block_size,
  1120. AVS_TKN_PPL_ID_U32, &esize);
  1121. if (ret)
  1122. return ERR_PTR(ret);
  1123. pipeline = avs_tplg_pipeline_create(comp, path, tuples, esize);
  1124. if (IS_ERR(pipeline)) {
  1125. dev_err(comp->dev, "parse pipeline failed: %ld\n",
  1126. PTR_ERR(pipeline));
  1127. return ERR_CAST(pipeline);
  1128. }
  1129. list_add_tail(&pipeline->node, &path->ppl_list);
  1130. block_size -= esize;
  1131. tuples = avs_tplg_vendor_array_at(tuples, esize);
  1132. }
  1133. return path;
  1134. }
  1135. static const struct avs_tplg_token_parser path_tmpl_parsers[] = {
  1136. {
  1137. .token = AVS_TKN_PATH_TMPL_ID_U32,
  1138. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  1139. .offset = offsetof(struct avs_tplg_path_template, id),
  1140. .parse = avs_parse_word_token,
  1141. },
  1142. };
  1143. static int parse_path_template(struct snd_soc_component *comp,
  1144. struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
  1145. struct avs_tplg_path_template *template,
  1146. const struct avs_tplg_token_parser *tmpl_tokens, u32 num_tmpl_tokens,
  1147. const struct avs_tplg_token_parser *path_tokens, u32 num_path_tokens)
  1148. {
  1149. struct avs_tplg_path *path;
  1150. u32 offset;
  1151. int ret;
  1152. /* Path template header MUST be followed by at least one path variant. */
  1153. ret = avs_tplg_vendor_array_lookup(tuples, block_size,
  1154. AVS_TKN_PATH_ID_U32, &offset);
  1155. if (ret)
  1156. return ret;
  1157. /* Process header which precedes path variants sections. */
  1158. ret = avs_parse_tokens(comp, template, tmpl_tokens, num_tmpl_tokens, tuples, offset);
  1159. if (ret < 0)
  1160. return ret;
  1161. block_size -= offset;
  1162. tuples = avs_tplg_vendor_array_at(tuples, offset);
  1163. do {
  1164. u32 esize;
  1165. ret = avs_tplg_vendor_entry_size(tuples, block_size,
  1166. AVS_TKN_PATH_ID_U32, &esize);
  1167. if (ret)
  1168. return ret;
  1169. path = avs_tplg_path_create(comp, template, tuples, esize, path_tokens,
  1170. num_path_tokens);
  1171. if (IS_ERR(path)) {
  1172. dev_err(comp->dev, "parse path failed: %ld\n", PTR_ERR(path));
  1173. return PTR_ERR(path);
  1174. }
  1175. list_add_tail(&path->node, &template->path_list);
  1176. block_size -= esize;
  1177. tuples = avs_tplg_vendor_array_at(tuples, esize);
  1178. } while (block_size > 0);
  1179. return 0;
  1180. }
  1181. static struct avs_tplg_path_template *
  1182. avs_tplg_path_template_create(struct snd_soc_component *comp, struct avs_tplg *owner,
  1183. struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
  1184. {
  1185. struct avs_tplg_path_template *template;
  1186. int ret;
  1187. template = devm_kzalloc(comp->card->dev, sizeof(*template), GFP_KERNEL);
  1188. if (!template)
  1189. return ERR_PTR(-ENOMEM);
  1190. template->owner = owner; /* Used to access component tplg is assigned to. */
  1191. INIT_LIST_HEAD(&template->path_list);
  1192. INIT_LIST_HEAD(&template->node);
  1193. ret = parse_path_template(comp, tuples, block_size, template, path_tmpl_parsers,
  1194. ARRAY_SIZE(path_tmpl_parsers), path_parsers,
  1195. ARRAY_SIZE(path_parsers));
  1196. if (ret)
  1197. return ERR_PTR(ret);
  1198. return template;
  1199. }
  1200. static int avs_route_load(struct snd_soc_component *comp, int index,
  1201. struct snd_soc_dapm_route *route)
  1202. {
  1203. struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
  1204. size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
  1205. char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
  1206. u32 port;
  1207. /* See parse_link_formatted_string() for dynamic naming when(s). */
  1208. if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
  1209. port = __ffs(mach->mach_params.i2s_link_mask);
  1210. snprintf(buf, len, route->source, port);
  1211. strncpy((char *)route->source, buf, len);
  1212. snprintf(buf, len, route->sink, port);
  1213. strncpy((char *)route->sink, buf, len);
  1214. if (route->control) {
  1215. snprintf(buf, len, route->control, port);
  1216. strncpy((char *)route->control, buf, len);
  1217. }
  1218. }
  1219. return 0;
  1220. }
  1221. static int avs_widget_load(struct snd_soc_component *comp, int index,
  1222. struct snd_soc_dapm_widget *w,
  1223. struct snd_soc_tplg_dapm_widget *dw)
  1224. {
  1225. struct snd_soc_acpi_mach *mach;
  1226. struct avs_tplg_path_template *template;
  1227. struct avs_soc_component *acomp = to_avs_soc_component(comp);
  1228. struct avs_tplg *tplg;
  1229. if (!le32_to_cpu(dw->priv.size))
  1230. return 0;
  1231. tplg = acomp->tplg;
  1232. mach = dev_get_platdata(comp->card->dev);
  1233. /* See parse_link_formatted_string() for dynamic naming when(s). */
  1234. if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
  1235. kfree(w->name);
  1236. /* w->name is freed later by soc_tplg_dapm_widget_create() */
  1237. w->name = kasprintf(GFP_KERNEL, dw->name, __ffs(mach->mach_params.i2s_link_mask));
  1238. if (!w->name)
  1239. return -ENOMEM;
  1240. }
  1241. template = avs_tplg_path_template_create(comp, tplg, dw->priv.array,
  1242. le32_to_cpu(dw->priv.size));
  1243. if (IS_ERR(template)) {
  1244. dev_err(comp->dev, "widget %s load failed: %ld\n", dw->name,
  1245. PTR_ERR(template));
  1246. return PTR_ERR(template);
  1247. }
  1248. w->priv = template; /* link path information to widget */
  1249. list_add_tail(&template->node, &tplg->path_tmpl_list);
  1250. return 0;
  1251. }
  1252. static int avs_dai_load(struct snd_soc_component *comp, int index,
  1253. struct snd_soc_dai_driver *dai_drv, struct snd_soc_tplg_pcm *pcm,
  1254. struct snd_soc_dai *dai)
  1255. {
  1256. if (pcm)
  1257. dai_drv->ops = &avs_dai_fe_ops;
  1258. return 0;
  1259. }
  1260. static int avs_link_load(struct snd_soc_component *comp, int index, struct snd_soc_dai_link *link,
  1261. struct snd_soc_tplg_link_config *cfg)
  1262. {
  1263. if (!link->no_pcm) {
  1264. /* Stream control handled by IPCs. */
  1265. link->nonatomic = true;
  1266. /* Open LINK (BE) pipes last and close them first to prevent xruns. */
  1267. link->trigger[0] = SND_SOC_DPCM_TRIGGER_PRE;
  1268. link->trigger[1] = SND_SOC_DPCM_TRIGGER_PRE;
  1269. }
  1270. return 0;
  1271. }
  1272. static const struct avs_tplg_token_parser manifest_parsers[] = {
  1273. {
  1274. .token = AVS_TKN_MANIFEST_NAME_STRING,
  1275. .type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
  1276. .offset = offsetof(struct avs_tplg, name),
  1277. .parse = parse_link_formatted_string,
  1278. },
  1279. {
  1280. .token = AVS_TKN_MANIFEST_VERSION_U32,
  1281. .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
  1282. .offset = offsetof(struct avs_tplg, version),
  1283. .parse = avs_parse_word_token,
  1284. },
  1285. };
  1286. static int avs_manifest(struct snd_soc_component *comp, int index,
  1287. struct snd_soc_tplg_manifest *manifest)
  1288. {
  1289. struct snd_soc_tplg_vendor_array *tuples = manifest->priv.array;
  1290. struct avs_soc_component *acomp = to_avs_soc_component(comp);
  1291. size_t remaining = le32_to_cpu(manifest->priv.size);
  1292. u32 offset;
  1293. int ret;
  1294. ret = avs_tplg_vendor_array_lookup(tuples, remaining,
  1295. AVS_TKN_MANIFEST_NUM_LIBRARIES_U32, &offset);
  1296. /* Manifest MUST begin with a header. */
  1297. if (!ret && !offset)
  1298. ret = -EINVAL;
  1299. if (ret) {
  1300. dev_err(comp->dev, "incorrect manifest format: %d\n", ret);
  1301. return ret;
  1302. }
  1303. /* Process header which precedes any of the dictionaries. */
  1304. ret = avs_parse_tokens(comp, acomp->tplg, manifest_parsers,
  1305. ARRAY_SIZE(manifest_parsers), tuples, offset);
  1306. if (ret < 0)
  1307. return ret;
  1308. remaining -= offset;
  1309. tuples = avs_tplg_vendor_array_at(tuples, offset);
  1310. ret = avs_tplg_vendor_array_lookup(tuples, remaining,
  1311. AVS_TKN_MANIFEST_NUM_AFMTS_U32, &offset);
  1312. if (ret) {
  1313. dev_err(comp->dev, "audio formats lookup failed: %d\n", ret);
  1314. return ret;
  1315. }
  1316. /* Libraries dictionary. */
  1317. ret = avs_tplg_parse_libraries(comp, tuples, offset);
  1318. if (ret < 0)
  1319. return ret;
  1320. remaining -= offset;
  1321. tuples = avs_tplg_vendor_array_at(tuples, offset);
  1322. ret = avs_tplg_vendor_array_lookup(tuples, remaining,
  1323. AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32, &offset);
  1324. if (ret) {
  1325. dev_err(comp->dev, "modcfgs_base lookup failed: %d\n", ret);
  1326. return ret;
  1327. }
  1328. /* Audio formats dictionary. */
  1329. ret = avs_tplg_parse_audio_formats(comp, tuples, offset);
  1330. if (ret < 0)
  1331. return ret;
  1332. remaining -= offset;
  1333. tuples = avs_tplg_vendor_array_at(tuples, offset);
  1334. ret = avs_tplg_vendor_array_lookup(tuples, remaining,
  1335. AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32, &offset);
  1336. if (ret) {
  1337. dev_err(comp->dev, "modcfgs_ext lookup failed: %d\n", ret);
  1338. return ret;
  1339. }
  1340. /* Module configs-base dictionary. */
  1341. ret = avs_tplg_parse_modcfgs_base(comp, tuples, offset);
  1342. if (ret < 0)
  1343. return ret;
  1344. remaining -= offset;
  1345. tuples = avs_tplg_vendor_array_at(tuples, offset);
  1346. ret = avs_tplg_vendor_array_lookup(tuples, remaining,
  1347. AVS_TKN_MANIFEST_NUM_PPLCFGS_U32, &offset);
  1348. if (ret) {
  1349. dev_err(comp->dev, "pplcfgs lookup failed: %d\n", ret);
  1350. return ret;
  1351. }
  1352. /* Module configs-ext dictionary. */
  1353. ret = avs_tplg_parse_modcfgs_ext(comp, tuples, offset);
  1354. if (ret < 0)
  1355. return ret;
  1356. remaining -= offset;
  1357. tuples = avs_tplg_vendor_array_at(tuples, offset);
  1358. ret = avs_tplg_vendor_array_lookup(tuples, remaining,
  1359. AVS_TKN_MANIFEST_NUM_BINDINGS_U32, &offset);
  1360. if (ret) {
  1361. dev_err(comp->dev, "bindings lookup failed: %d\n", ret);
  1362. return ret;
  1363. }
  1364. /* Pipeline configs dictionary. */
  1365. ret = avs_tplg_parse_pplcfgs(comp, tuples, offset);
  1366. if (ret < 0)
  1367. return ret;
  1368. remaining -= offset;
  1369. tuples = avs_tplg_vendor_array_at(tuples, offset);
  1370. /* Bindings dictionary. */
  1371. return avs_tplg_parse_bindings(comp, tuples, remaining);
  1372. }
  1373. static struct snd_soc_tplg_ops avs_tplg_ops = {
  1374. .dapm_route_load = avs_route_load,
  1375. .widget_load = avs_widget_load,
  1376. .dai_load = avs_dai_load,
  1377. .link_load = avs_link_load,
  1378. .manifest = avs_manifest,
  1379. };
  1380. struct avs_tplg *avs_tplg_new(struct snd_soc_component *comp)
  1381. {
  1382. struct avs_tplg *tplg;
  1383. tplg = devm_kzalloc(comp->card->dev, sizeof(*tplg), GFP_KERNEL);
  1384. if (!tplg)
  1385. return NULL;
  1386. tplg->comp = comp;
  1387. INIT_LIST_HEAD(&tplg->path_tmpl_list);
  1388. return tplg;
  1389. }
  1390. int avs_load_topology(struct snd_soc_component *comp, const char *filename)
  1391. {
  1392. const struct firmware *fw;
  1393. int ret;
  1394. ret = request_firmware(&fw, filename, comp->dev);
  1395. if (ret < 0) {
  1396. dev_err(comp->dev, "request topology \"%s\" failed: %d\n", filename, ret);
  1397. return ret;
  1398. }
  1399. ret = snd_soc_tplg_component_load(comp, &avs_tplg_ops, fw);
  1400. if (ret < 0)
  1401. dev_err(comp->dev, "load topology \"%s\" failed: %d\n", filename, ret);
  1402. release_firmware(fw);
  1403. return ret;
  1404. }
  1405. int avs_remove_topology(struct snd_soc_component *comp)
  1406. {
  1407. snd_soc_tplg_component_remove(comp);
  1408. return 0;
  1409. }