ipc3-topology.c 83 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // This file is provided under a dual BSD/GPLv2 license. When using or
  4. // redistributing this file, you may do so under either license.
  5. //
  6. // Copyright(c) 2021 Intel Corporation
  7. //
  8. //
  9. #include <uapi/sound/sof/tokens.h>
  10. #include <sound/pcm_params.h>
  11. #include "sof-priv.h"
  12. #include "sof-audio.h"
  13. #include "ipc3-priv.h"
  14. #include "ops.h"
  15. /* Full volume for default values */
  16. #define VOL_ZERO_DB BIT(VOLUME_FWL)
  17. /* size of tplg ABI in bytes */
  18. #define SOF_IPC3_TPLG_ABI_SIZE 3
  19. /* Base of SOF_DAI_INTEL_ALH, this should be aligned with SOC_SDW_INTEL_BIDIR_PDI_BASE */
  20. #define INTEL_ALH_DAI_INDEX_BASE 2
  21. struct sof_widget_data {
  22. int ctrl_type;
  23. int ipc_cmd;
  24. void *pdata;
  25. size_t pdata_size;
  26. struct snd_sof_control *control;
  27. };
  28. struct sof_process_types {
  29. const char *name;
  30. enum sof_ipc_process_type type;
  31. enum sof_comp_type comp_type;
  32. };
  33. static const struct sof_process_types sof_process[] = {
  34. {"EQFIR", SOF_PROCESS_EQFIR, SOF_COMP_EQ_FIR},
  35. {"EQIIR", SOF_PROCESS_EQIIR, SOF_COMP_EQ_IIR},
  36. {"KEYWORD_DETECT", SOF_PROCESS_KEYWORD_DETECT, SOF_COMP_KEYWORD_DETECT},
  37. {"KPB", SOF_PROCESS_KPB, SOF_COMP_KPB},
  38. {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR},
  39. {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX},
  40. {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX},
  41. {"DCBLOCK", SOF_PROCESS_DCBLOCK, SOF_COMP_DCBLOCK},
  42. {"SMART_AMP", SOF_PROCESS_SMART_AMP, SOF_COMP_SMART_AMP},
  43. };
  44. static enum sof_ipc_process_type find_process(const char *name)
  45. {
  46. int i;
  47. for (i = 0; i < ARRAY_SIZE(sof_process); i++) {
  48. if (strcmp(name, sof_process[i].name) == 0)
  49. return sof_process[i].type;
  50. }
  51. return SOF_PROCESS_NONE;
  52. }
  53. static int get_token_process_type(void *elem, void *object, u32 offset)
  54. {
  55. u32 *val = (u32 *)((u8 *)object + offset);
  56. *val = find_process((const char *)elem);
  57. return 0;
  58. }
  59. /* Buffers */
  60. static const struct sof_topology_token buffer_tokens[] = {
  61. {SOF_TKN_BUF_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  62. offsetof(struct sof_ipc_buffer, size)},
  63. {SOF_TKN_BUF_CAPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  64. offsetof(struct sof_ipc_buffer, caps)},
  65. {SOF_TKN_BUF_FLAGS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  66. offsetof(struct sof_ipc_buffer, flags)},
  67. };
  68. /* DAI */
  69. static const struct sof_topology_token dai_tokens[] = {
  70. {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type,
  71. offsetof(struct sof_ipc_comp_dai, type)},
  72. {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  73. offsetof(struct sof_ipc_comp_dai, dai_index)},
  74. {SOF_TKN_DAI_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  75. offsetof(struct sof_ipc_comp_dai, direction)},
  76. };
  77. /* BE DAI link */
  78. static const struct sof_topology_token dai_link_tokens[] = {
  79. {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type,
  80. offsetof(struct sof_ipc_dai_config, type)},
  81. {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  82. offsetof(struct sof_ipc_dai_config, dai_index)},
  83. };
  84. /* scheduling */
  85. static const struct sof_topology_token sched_tokens[] = {
  86. {SOF_TKN_SCHED_PERIOD, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  87. offsetof(struct sof_ipc_pipe_new, period)},
  88. {SOF_TKN_SCHED_PRIORITY, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  89. offsetof(struct sof_ipc_pipe_new, priority)},
  90. {SOF_TKN_SCHED_MIPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  91. offsetof(struct sof_ipc_pipe_new, period_mips)},
  92. {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  93. offsetof(struct sof_ipc_pipe_new, core)},
  94. {SOF_TKN_SCHED_FRAMES, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  95. offsetof(struct sof_ipc_pipe_new, frames_per_sched)},
  96. {SOF_TKN_SCHED_TIME_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  97. offsetof(struct sof_ipc_pipe_new, time_domain)},
  98. };
  99. static const struct sof_topology_token pipeline_tokens[] = {
  100. {SOF_TKN_SCHED_DYNAMIC_PIPELINE, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16,
  101. offsetof(struct snd_sof_widget, dynamic_pipeline_widget)},
  102. };
  103. /* volume */
  104. static const struct sof_topology_token volume_tokens[] = {
  105. {SOF_TKN_VOLUME_RAMP_STEP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  106. offsetof(struct sof_ipc_comp_volume, ramp)},
  107. {SOF_TKN_VOLUME_RAMP_STEP_MS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  108. offsetof(struct sof_ipc_comp_volume, initial_ramp)},
  109. };
  110. /* SRC */
  111. static const struct sof_topology_token src_tokens[] = {
  112. {SOF_TKN_SRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  113. offsetof(struct sof_ipc_comp_src, source_rate)},
  114. {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  115. offsetof(struct sof_ipc_comp_src, sink_rate)},
  116. };
  117. /* ASRC */
  118. static const struct sof_topology_token asrc_tokens[] = {
  119. {SOF_TKN_ASRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  120. offsetof(struct sof_ipc_comp_asrc, source_rate)},
  121. {SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  122. offsetof(struct sof_ipc_comp_asrc, sink_rate)},
  123. {SOF_TKN_ASRC_ASYNCHRONOUS_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  124. offsetof(struct sof_ipc_comp_asrc, asynchronous_mode)},
  125. {SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  126. offsetof(struct sof_ipc_comp_asrc, operation_mode)},
  127. };
  128. /* EFFECT */
  129. static const struct sof_topology_token process_tokens[] = {
  130. {SOF_TKN_PROCESS_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_process_type,
  131. offsetof(struct sof_ipc_comp_process, type)},
  132. };
  133. /* PCM */
  134. static const struct sof_topology_token pcm_tokens[] = {
  135. {SOF_TKN_PCM_DMAC_CONFIG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  136. offsetof(struct sof_ipc_comp_host, dmac_config)},
  137. };
  138. /* Generic components */
  139. static const struct sof_topology_token comp_tokens[] = {
  140. {SOF_TKN_COMP_PERIOD_SINK_COUNT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  141. offsetof(struct sof_ipc_comp_config, periods_sink)},
  142. {SOF_TKN_COMP_PERIOD_SOURCE_COUNT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  143. offsetof(struct sof_ipc_comp_config, periods_source)},
  144. {SOF_TKN_COMP_FORMAT,
  145. SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_format,
  146. offsetof(struct sof_ipc_comp_config, frame_fmt)},
  147. };
  148. /* SSP */
  149. static const struct sof_topology_token ssp_tokens[] = {
  150. {SOF_TKN_INTEL_SSP_CLKS_CONTROL, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  151. offsetof(struct sof_ipc_dai_ssp_params, clks_control)},
  152. {SOF_TKN_INTEL_SSP_MCLK_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  153. offsetof(struct sof_ipc_dai_ssp_params, mclk_id)},
  154. {SOF_TKN_INTEL_SSP_SAMPLE_BITS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  155. offsetof(struct sof_ipc_dai_ssp_params, sample_valid_bits)},
  156. {SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  157. offsetof(struct sof_ipc_dai_ssp_params, frame_pulse_width)},
  158. {SOF_TKN_INTEL_SSP_QUIRKS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  159. offsetof(struct sof_ipc_dai_ssp_params, quirks)},
  160. {SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16,
  161. offsetof(struct sof_ipc_dai_ssp_params, tdm_per_slot_padding_flag)},
  162. {SOF_TKN_INTEL_SSP_BCLK_DELAY, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  163. offsetof(struct sof_ipc_dai_ssp_params, bclk_delay)},
  164. };
  165. /* ALH */
  166. static const struct sof_topology_token alh_tokens[] = {
  167. {SOF_TKN_INTEL_ALH_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  168. offsetof(struct sof_ipc_dai_alh_params, rate)},
  169. {SOF_TKN_INTEL_ALH_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  170. offsetof(struct sof_ipc_dai_alh_params, channels)},
  171. };
  172. /* DMIC */
  173. static const struct sof_topology_token dmic_tokens[] = {
  174. {SOF_TKN_INTEL_DMIC_DRIVER_VERSION, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  175. offsetof(struct sof_ipc_dai_dmic_params, driver_ipc_version)},
  176. {SOF_TKN_INTEL_DMIC_CLK_MIN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  177. offsetof(struct sof_ipc_dai_dmic_params, pdmclk_min)},
  178. {SOF_TKN_INTEL_DMIC_CLK_MAX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  179. offsetof(struct sof_ipc_dai_dmic_params, pdmclk_max)},
  180. {SOF_TKN_INTEL_DMIC_SAMPLE_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  181. offsetof(struct sof_ipc_dai_dmic_params, fifo_fs)},
  182. {SOF_TKN_INTEL_DMIC_DUTY_MIN, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  183. offsetof(struct sof_ipc_dai_dmic_params, duty_min)},
  184. {SOF_TKN_INTEL_DMIC_DUTY_MAX, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  185. offsetof(struct sof_ipc_dai_dmic_params, duty_max)},
  186. {SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  187. offsetof(struct sof_ipc_dai_dmic_params, num_pdm_active)},
  188. {SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  189. offsetof(struct sof_ipc_dai_dmic_params, fifo_bits)},
  190. {SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  191. offsetof(struct sof_ipc_dai_dmic_params, unmute_ramp_time)},
  192. };
  193. /* ESAI */
  194. static const struct sof_topology_token esai_tokens[] = {
  195. {SOF_TKN_IMX_ESAI_MCLK_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  196. offsetof(struct sof_ipc_dai_esai_params, mclk_id)},
  197. };
  198. /* SAI */
  199. static const struct sof_topology_token sai_tokens[] = {
  200. {SOF_TKN_IMX_SAI_MCLK_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  201. offsetof(struct sof_ipc_dai_sai_params, mclk_id)},
  202. };
  203. /*
  204. * DMIC PDM Tokens
  205. * SOF_TKN_INTEL_DMIC_PDM_CTRL_ID should be the first token
  206. * as it increments the index while parsing the array of pdm tokens
  207. * and determines the correct offset
  208. */
  209. static const struct sof_topology_token dmic_pdm_tokens[] = {
  210. {SOF_TKN_INTEL_DMIC_PDM_CTRL_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  211. offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, id)},
  212. {SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  213. offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, enable_mic_a)},
  214. {SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  215. offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, enable_mic_b)},
  216. {SOF_TKN_INTEL_DMIC_PDM_POLARITY_A, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  217. offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, polarity_mic_a)},
  218. {SOF_TKN_INTEL_DMIC_PDM_POLARITY_B, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  219. offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, polarity_mic_b)},
  220. {SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  221. offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, clk_edge)},
  222. {SOF_TKN_INTEL_DMIC_PDM_SKEW, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
  223. offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, skew)},
  224. };
  225. /* HDA */
  226. static const struct sof_topology_token hda_tokens[] = {
  227. {SOF_TKN_INTEL_HDA_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  228. offsetof(struct sof_ipc_dai_hda_params, rate)},
  229. {SOF_TKN_INTEL_HDA_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  230. offsetof(struct sof_ipc_dai_hda_params, channels)},
  231. };
  232. /* AFE */
  233. static const struct sof_topology_token afe_tokens[] = {
  234. {SOF_TKN_MEDIATEK_AFE_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  235. offsetof(struct sof_ipc_dai_mtk_afe_params, rate)},
  236. {SOF_TKN_MEDIATEK_AFE_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  237. offsetof(struct sof_ipc_dai_mtk_afe_params, channels)},
  238. {SOF_TKN_MEDIATEK_AFE_FORMAT, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_format,
  239. offsetof(struct sof_ipc_dai_mtk_afe_params, format)},
  240. };
  241. /* ACPDMIC */
  242. static const struct sof_topology_token acpdmic_tokens[] = {
  243. {SOF_TKN_AMD_ACPDMIC_RATE,
  244. SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  245. offsetof(struct sof_ipc_dai_acpdmic_params, pdm_rate)},
  246. {SOF_TKN_AMD_ACPDMIC_CH,
  247. SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  248. offsetof(struct sof_ipc_dai_acpdmic_params, pdm_ch)},
  249. };
  250. /* ACPI2S */
  251. static const struct sof_topology_token acpi2s_tokens[] = {
  252. {SOF_TKN_AMD_ACPI2S_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  253. offsetof(struct sof_ipc_dai_acp_params, fsync_rate)},
  254. {SOF_TKN_AMD_ACPI2S_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  255. offsetof(struct sof_ipc_dai_acp_params, tdm_slots)},
  256. {SOF_TKN_AMD_ACPI2S_TDM_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  257. offsetof(struct sof_ipc_dai_acp_params, tdm_mode)},
  258. };
  259. /* MICFIL PDM */
  260. static const struct sof_topology_token micfil_pdm_tokens[] = {
  261. {SOF_TKN_IMX_MICFIL_RATE,
  262. SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  263. offsetof(struct sof_ipc_dai_micfil_params, pdm_rate)},
  264. {SOF_TKN_IMX_MICFIL_CH,
  265. SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  266. offsetof(struct sof_ipc_dai_micfil_params, pdm_ch)},
  267. };
  268. /* ACP_SDW */
  269. static const struct sof_topology_token acp_sdw_tokens[] = {
  270. {SOF_TKN_AMD_ACP_SDW_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  271. offsetof(struct sof_ipc_dai_acp_sdw_params, rate)},
  272. {SOF_TKN_AMD_ACP_SDW_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  273. offsetof(struct sof_ipc_dai_acp_sdw_params, channels)},
  274. };
  275. /* Core tokens */
  276. static const struct sof_topology_token core_tokens[] = {
  277. {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
  278. offsetof(struct sof_ipc_comp, core)},
  279. };
  280. /* Component extended tokens */
  281. static const struct sof_topology_token comp_ext_tokens[] = {
  282. {SOF_TKN_COMP_UUID, SND_SOC_TPLG_TUPLE_TYPE_UUID, get_token_uuid,
  283. offsetof(struct snd_sof_widget, uuid)},
  284. };
  285. static const struct sof_token_info ipc3_token_list[SOF_TOKEN_COUNT] = {
  286. [SOF_PCM_TOKENS] = {"PCM tokens", pcm_tokens, ARRAY_SIZE(pcm_tokens)},
  287. [SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)},
  288. [SOF_SCHED_TOKENS] = {"Scheduler tokens", sched_tokens, ARRAY_SIZE(sched_tokens)},
  289. [SOF_COMP_TOKENS] = {"Comp tokens", comp_tokens, ARRAY_SIZE(comp_tokens)},
  290. [SOF_CORE_TOKENS] = {"Core tokens", core_tokens, ARRAY_SIZE(core_tokens)},
  291. [SOF_COMP_EXT_TOKENS] = {"AFE tokens", comp_ext_tokens, ARRAY_SIZE(comp_ext_tokens)},
  292. [SOF_BUFFER_TOKENS] = {"Buffer tokens", buffer_tokens, ARRAY_SIZE(buffer_tokens)},
  293. [SOF_VOLUME_TOKENS] = {"Volume tokens", volume_tokens, ARRAY_SIZE(volume_tokens)},
  294. [SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)},
  295. [SOF_ASRC_TOKENS] = {"ASRC tokens", asrc_tokens, ARRAY_SIZE(asrc_tokens)},
  296. [SOF_PROCESS_TOKENS] = {"Process tokens", process_tokens, ARRAY_SIZE(process_tokens)},
  297. [SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)},
  298. [SOF_DAI_LINK_TOKENS] = {"DAI link tokens", dai_link_tokens, ARRAY_SIZE(dai_link_tokens)},
  299. [SOF_HDA_TOKENS] = {"HDA tokens", hda_tokens, ARRAY_SIZE(hda_tokens)},
  300. [SOF_SSP_TOKENS] = {"SSP tokens", ssp_tokens, ARRAY_SIZE(ssp_tokens)},
  301. [SOF_ALH_TOKENS] = {"ALH tokens", alh_tokens, ARRAY_SIZE(alh_tokens)},
  302. [SOF_DMIC_TOKENS] = {"DMIC tokens", dmic_tokens, ARRAY_SIZE(dmic_tokens)},
  303. [SOF_DMIC_PDM_TOKENS] = {"DMIC PDM tokens", dmic_pdm_tokens, ARRAY_SIZE(dmic_pdm_tokens)},
  304. [SOF_ESAI_TOKENS] = {"ESAI tokens", esai_tokens, ARRAY_SIZE(esai_tokens)},
  305. [SOF_SAI_TOKENS] = {"SAI tokens", sai_tokens, ARRAY_SIZE(sai_tokens)},
  306. [SOF_AFE_TOKENS] = {"AFE tokens", afe_tokens, ARRAY_SIZE(afe_tokens)},
  307. [SOF_ACPDMIC_TOKENS] = {"ACPDMIC tokens", acpdmic_tokens, ARRAY_SIZE(acpdmic_tokens)},
  308. [SOF_ACPI2S_TOKENS] = {"ACPI2S tokens", acpi2s_tokens, ARRAY_SIZE(acpi2s_tokens)},
  309. [SOF_MICFIL_TOKENS] = {"MICFIL PDM tokens",
  310. micfil_pdm_tokens, ARRAY_SIZE(micfil_pdm_tokens)},
  311. [SOF_ACP_SDW_TOKENS] = {"ACP_SDW tokens", acp_sdw_tokens, ARRAY_SIZE(acp_sdw_tokens)},
  312. };
  313. /**
  314. * sof_comp_alloc - allocate and initialize buffer for a new component
  315. * @swidget: pointer to struct snd_sof_widget containing extended data
  316. * @ipc_size: IPC payload size that will be updated depending on valid
  317. * extended data.
  318. * @index: ID of the pipeline the component belongs to
  319. *
  320. * Return: The pointer to the new allocated component, NULL if failed.
  321. */
  322. static void *sof_comp_alloc(struct snd_sof_widget *swidget, size_t *ipc_size,
  323. int index)
  324. {
  325. struct sof_ipc_comp *comp;
  326. size_t total_size = *ipc_size;
  327. size_t ext_size = sizeof(swidget->uuid);
  328. /* only non-zero UUID is valid */
  329. if (!guid_is_null(&swidget->uuid))
  330. total_size += ext_size;
  331. comp = kzalloc(total_size, GFP_KERNEL);
  332. if (!comp)
  333. return NULL;
  334. /* configure comp new IPC message */
  335. comp->hdr.size = total_size;
  336. comp->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
  337. comp->id = swidget->comp_id;
  338. comp->pipeline_id = index;
  339. comp->core = swidget->core;
  340. /* handle the extended data if needed */
  341. if (total_size > *ipc_size) {
  342. /* append extended data to the end of the component */
  343. memcpy((u8 *)comp + *ipc_size, &swidget->uuid, ext_size);
  344. comp->ext_data_length = ext_size;
  345. }
  346. /* update ipc_size and return */
  347. *ipc_size = total_size;
  348. return comp;
  349. }
  350. static void sof_dbg_comp_config(struct snd_soc_component *scomp, struct sof_ipc_comp_config *config)
  351. {
  352. dev_dbg(scomp->dev, " config: periods snk %d src %d fmt %d\n",
  353. config->periods_sink, config->periods_source,
  354. config->frame_fmt);
  355. }
  356. static int sof_ipc3_widget_setup_comp_host(struct snd_sof_widget *swidget)
  357. {
  358. struct snd_soc_component *scomp = swidget->scomp;
  359. struct sof_ipc_comp_host *host;
  360. size_t ipc_size = sizeof(*host);
  361. int ret;
  362. host = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id);
  363. if (!host)
  364. return -ENOMEM;
  365. swidget->private = host;
  366. /* configure host comp IPC message */
  367. host->comp.type = SOF_COMP_HOST;
  368. host->config.hdr.size = sizeof(host->config);
  369. if (swidget->id == snd_soc_dapm_aif_out)
  370. host->direction = SOF_IPC_STREAM_CAPTURE;
  371. else
  372. host->direction = SOF_IPC_STREAM_PLAYBACK;
  373. /* parse one set of pcm_tokens */
  374. ret = sof_update_ipc_object(scomp, host, SOF_PCM_TOKENS, swidget->tuples,
  375. swidget->num_tuples, sizeof(*host), 1);
  376. if (ret < 0)
  377. goto err;
  378. /* parse one set of comp_tokens */
  379. ret = sof_update_ipc_object(scomp, &host->config, SOF_COMP_TOKENS, swidget->tuples,
  380. swidget->num_tuples, sizeof(host->config), 1);
  381. if (ret < 0)
  382. goto err;
  383. dev_dbg(scomp->dev, "loaded host %s\n", swidget->widget->name);
  384. sof_dbg_comp_config(scomp, &host->config);
  385. return 0;
  386. err:
  387. kfree(swidget->private);
  388. swidget->private = NULL;
  389. return ret;
  390. }
  391. static void sof_ipc3_widget_free_comp(struct snd_sof_widget *swidget)
  392. {
  393. kfree(swidget->private);
  394. }
  395. static int sof_ipc3_widget_setup_comp_tone(struct snd_sof_widget *swidget)
  396. {
  397. struct snd_soc_component *scomp = swidget->scomp;
  398. struct sof_ipc_comp_tone *tone;
  399. size_t ipc_size = sizeof(*tone);
  400. int ret;
  401. tone = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id);
  402. if (!tone)
  403. return -ENOMEM;
  404. swidget->private = tone;
  405. /* configure siggen IPC message */
  406. tone->comp.type = SOF_COMP_TONE;
  407. tone->config.hdr.size = sizeof(tone->config);
  408. /* parse one set of comp tokens */
  409. ret = sof_update_ipc_object(scomp, &tone->config, SOF_COMP_TOKENS, swidget->tuples,
  410. swidget->num_tuples, sizeof(tone->config), 1);
  411. if (ret < 0) {
  412. kfree(swidget->private);
  413. swidget->private = NULL;
  414. return ret;
  415. }
  416. dev_dbg(scomp->dev, "tone %s: frequency %d amplitude %d\n",
  417. swidget->widget->name, tone->frequency, tone->amplitude);
  418. sof_dbg_comp_config(scomp, &tone->config);
  419. return 0;
  420. }
  421. static int sof_ipc3_widget_setup_comp_mixer(struct snd_sof_widget *swidget)
  422. {
  423. struct snd_soc_component *scomp = swidget->scomp;
  424. struct sof_ipc_comp_mixer *mixer;
  425. size_t ipc_size = sizeof(*mixer);
  426. int ret;
  427. mixer = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id);
  428. if (!mixer)
  429. return -ENOMEM;
  430. swidget->private = mixer;
  431. /* configure mixer IPC message */
  432. mixer->comp.type = SOF_COMP_MIXER;
  433. mixer->config.hdr.size = sizeof(mixer->config);
  434. /* parse one set of comp tokens */
  435. ret = sof_update_ipc_object(scomp, &mixer->config, SOF_COMP_TOKENS,
  436. swidget->tuples, swidget->num_tuples,
  437. sizeof(mixer->config), 1);
  438. if (ret < 0) {
  439. kfree(swidget->private);
  440. swidget->private = NULL;
  441. return ret;
  442. }
  443. dev_dbg(scomp->dev, "loaded mixer %s\n", swidget->widget->name);
  444. sof_dbg_comp_config(scomp, &mixer->config);
  445. return 0;
  446. }
  447. static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
  448. {
  449. struct snd_soc_component *scomp = swidget->scomp;
  450. struct snd_sof_pipeline *spipe = swidget->spipe;
  451. struct sof_ipc_pipe_new *pipeline;
  452. struct snd_sof_widget *comp_swidget;
  453. int ret;
  454. pipeline = kzalloc_obj(*pipeline);
  455. if (!pipeline)
  456. return -ENOMEM;
  457. /* configure pipeline IPC message */
  458. pipeline->hdr.size = sizeof(*pipeline);
  459. pipeline->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_NEW;
  460. pipeline->pipeline_id = swidget->pipeline_id;
  461. pipeline->comp_id = swidget->comp_id;
  462. swidget->private = pipeline;
  463. /* component at start of pipeline is our stream id */
  464. comp_swidget = snd_sof_find_swidget(scomp, swidget->widget->sname);
  465. if (!comp_swidget) {
  466. dev_err(scomp->dev, "scheduler %s refers to non existent widget %s\n",
  467. swidget->widget->name, swidget->widget->sname);
  468. ret = -EINVAL;
  469. goto err;
  470. }
  471. pipeline->sched_id = comp_swidget->comp_id;
  472. /* parse one set of scheduler tokens */
  473. ret = sof_update_ipc_object(scomp, pipeline, SOF_SCHED_TOKENS, swidget->tuples,
  474. swidget->num_tuples, sizeof(*pipeline), 1);
  475. if (ret < 0)
  476. goto err;
  477. /* parse one set of pipeline tokens */
  478. ret = sof_update_ipc_object(scomp, swidget, SOF_PIPELINE_TOKENS, swidget->tuples,
  479. swidget->num_tuples, sizeof(*swidget), 1);
  480. if (ret < 0)
  481. goto err;
  482. if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE))
  483. pipeline->core = SOF_DSP_PRIMARY_CORE;
  484. if (sof_debug_check_flag(SOF_DBG_DYNAMIC_PIPELINES_OVERRIDE))
  485. swidget->dynamic_pipeline_widget =
  486. sof_debug_check_flag(SOF_DBG_DYNAMIC_PIPELINES_ENABLE);
  487. dev_dbg(scomp->dev, "pipeline %s: period %d pri %d mips %d core %d frames %d dynamic %d\n",
  488. swidget->widget->name, pipeline->period, pipeline->priority,
  489. pipeline->period_mips, pipeline->core, pipeline->frames_per_sched,
  490. swidget->dynamic_pipeline_widget);
  491. swidget->core = pipeline->core;
  492. spipe->core_mask |= BIT(pipeline->core);
  493. return 0;
  494. err:
  495. kfree(swidget->private);
  496. swidget->private = NULL;
  497. return ret;
  498. }
  499. static int sof_ipc3_widget_setup_comp_buffer(struct snd_sof_widget *swidget)
  500. {
  501. struct snd_soc_component *scomp = swidget->scomp;
  502. struct sof_ipc_buffer *buffer;
  503. int ret;
  504. buffer = kzalloc_obj(*buffer);
  505. if (!buffer)
  506. return -ENOMEM;
  507. swidget->private = buffer;
  508. /* configure dai IPC message */
  509. buffer->comp.hdr.size = sizeof(*buffer);
  510. buffer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_BUFFER_NEW;
  511. buffer->comp.id = swidget->comp_id;
  512. buffer->comp.type = SOF_COMP_BUFFER;
  513. buffer->comp.pipeline_id = swidget->pipeline_id;
  514. buffer->comp.core = swidget->core;
  515. /* parse one set of buffer tokens */
  516. ret = sof_update_ipc_object(scomp, buffer, SOF_BUFFER_TOKENS, swidget->tuples,
  517. swidget->num_tuples, sizeof(*buffer), 1);
  518. if (ret < 0) {
  519. kfree(swidget->private);
  520. swidget->private = NULL;
  521. return ret;
  522. }
  523. dev_dbg(scomp->dev, "buffer %s: size %d caps 0x%x\n",
  524. swidget->widget->name, buffer->size, buffer->caps);
  525. return 0;
  526. }
  527. static int sof_ipc3_widget_setup_comp_src(struct snd_sof_widget *swidget)
  528. {
  529. struct snd_soc_component *scomp = swidget->scomp;
  530. struct sof_ipc_comp_src *src;
  531. size_t ipc_size = sizeof(*src);
  532. int ret;
  533. src = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id);
  534. if (!src)
  535. return -ENOMEM;
  536. swidget->private = src;
  537. /* configure src IPC message */
  538. src->comp.type = SOF_COMP_SRC;
  539. src->config.hdr.size = sizeof(src->config);
  540. /* parse one set of src tokens */
  541. ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples,
  542. swidget->num_tuples, sizeof(*src), 1);
  543. if (ret < 0)
  544. goto err;
  545. /* parse one set of comp tokens */
  546. ret = sof_update_ipc_object(scomp, &src->config, SOF_COMP_TOKENS,
  547. swidget->tuples, swidget->num_tuples, sizeof(src->config), 1);
  548. if (ret < 0)
  549. goto err;
  550. dev_dbg(scomp->dev, "src %s: source rate %d sink rate %d\n",
  551. swidget->widget->name, src->source_rate, src->sink_rate);
  552. sof_dbg_comp_config(scomp, &src->config);
  553. return 0;
  554. err:
  555. kfree(swidget->private);
  556. swidget->private = NULL;
  557. return ret;
  558. }
  559. static int sof_ipc3_widget_setup_comp_asrc(struct snd_sof_widget *swidget)
  560. {
  561. struct snd_soc_component *scomp = swidget->scomp;
  562. struct sof_ipc_comp_asrc *asrc;
  563. size_t ipc_size = sizeof(*asrc);
  564. int ret;
  565. asrc = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id);
  566. if (!asrc)
  567. return -ENOMEM;
  568. swidget->private = asrc;
  569. /* configure ASRC IPC message */
  570. asrc->comp.type = SOF_COMP_ASRC;
  571. asrc->config.hdr.size = sizeof(asrc->config);
  572. /* parse one set of asrc tokens */
  573. ret = sof_update_ipc_object(scomp, asrc, SOF_ASRC_TOKENS, swidget->tuples,
  574. swidget->num_tuples, sizeof(*asrc), 1);
  575. if (ret < 0)
  576. goto err;
  577. /* parse one set of comp tokens */
  578. ret = sof_update_ipc_object(scomp, &asrc->config, SOF_COMP_TOKENS,
  579. swidget->tuples, swidget->num_tuples, sizeof(asrc->config), 1);
  580. if (ret < 0)
  581. goto err;
  582. dev_dbg(scomp->dev, "asrc %s: source rate %d sink rate %d asynch %d operation %d\n",
  583. swidget->widget->name, asrc->source_rate, asrc->sink_rate,
  584. asrc->asynchronous_mode, asrc->operation_mode);
  585. sof_dbg_comp_config(scomp, &asrc->config);
  586. return 0;
  587. err:
  588. kfree(swidget->private);
  589. swidget->private = NULL;
  590. return ret;
  591. }
  592. /*
  593. * Mux topology
  594. */
  595. static int sof_ipc3_widget_setup_comp_mux(struct snd_sof_widget *swidget)
  596. {
  597. struct snd_soc_component *scomp = swidget->scomp;
  598. struct sof_ipc_comp_mux *mux;
  599. size_t ipc_size = sizeof(*mux);
  600. int ret;
  601. mux = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id);
  602. if (!mux)
  603. return -ENOMEM;
  604. swidget->private = mux;
  605. /* configure mux IPC message */
  606. mux->comp.type = SOF_COMP_MUX;
  607. mux->config.hdr.size = sizeof(mux->config);
  608. /* parse one set of comp tokens */
  609. ret = sof_update_ipc_object(scomp, &mux->config, SOF_COMP_TOKENS,
  610. swidget->tuples, swidget->num_tuples, sizeof(mux->config), 1);
  611. if (ret < 0) {
  612. kfree(swidget->private);
  613. swidget->private = NULL;
  614. return ret;
  615. }
  616. dev_dbg(scomp->dev, "loaded mux %s\n", swidget->widget->name);
  617. sof_dbg_comp_config(scomp, &mux->config);
  618. return 0;
  619. }
  620. /*
  621. * PGA Topology
  622. */
  623. static int sof_ipc3_widget_setup_comp_pga(struct snd_sof_widget *swidget)
  624. {
  625. struct snd_soc_component *scomp = swidget->scomp;
  626. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
  627. struct sof_ipc_comp_volume *volume;
  628. struct snd_sof_control *scontrol;
  629. size_t ipc_size = sizeof(*volume);
  630. int min_step, max_step;
  631. int ret;
  632. volume = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id);
  633. if (!volume)
  634. return -ENOMEM;
  635. swidget->private = volume;
  636. /* configure volume IPC message */
  637. volume->comp.type = SOF_COMP_VOLUME;
  638. volume->config.hdr.size = sizeof(volume->config);
  639. /* parse one set of volume tokens */
  640. ret = sof_update_ipc_object(scomp, volume, SOF_VOLUME_TOKENS, swidget->tuples,
  641. swidget->num_tuples, sizeof(*volume), 1);
  642. if (ret < 0)
  643. goto err;
  644. /* parse one set of comp tokens */
  645. ret = sof_update_ipc_object(scomp, &volume->config, SOF_COMP_TOKENS,
  646. swidget->tuples, swidget->num_tuples,
  647. sizeof(volume->config), 1);
  648. if (ret < 0)
  649. goto err;
  650. dev_dbg(scomp->dev, "loaded PGA %s\n", swidget->widget->name);
  651. sof_dbg_comp_config(scomp, &volume->config);
  652. list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
  653. if (scontrol->comp_id == swidget->comp_id &&
  654. scontrol->volume_table) {
  655. min_step = scontrol->min_volume_step;
  656. max_step = scontrol->max_volume_step;
  657. volume->min_value = scontrol->volume_table[min_step];
  658. volume->max_value = scontrol->volume_table[max_step];
  659. volume->channels = scontrol->num_channels;
  660. break;
  661. }
  662. }
  663. return 0;
  664. err:
  665. kfree(swidget->private);
  666. swidget->private = NULL;
  667. return ret;
  668. }
  669. static int sof_get_control_data(struct snd_soc_component *scomp,
  670. struct snd_soc_dapm_widget *widget,
  671. struct sof_widget_data *wdata, size_t *size)
  672. {
  673. const struct snd_kcontrol_new *kc;
  674. struct sof_ipc_ctrl_data *cdata;
  675. struct soc_mixer_control *sm;
  676. struct soc_bytes_ext *sbe;
  677. struct soc_enum *se;
  678. int i;
  679. *size = 0;
  680. for (i = 0; i < widget->num_kcontrols; i++) {
  681. kc = &widget->kcontrol_news[i];
  682. switch (widget->dobj.widget.kcontrol_type[i]) {
  683. case SND_SOC_TPLG_TYPE_MIXER:
  684. sm = (struct soc_mixer_control *)kc->private_value;
  685. wdata[i].control = sm->dobj.private;
  686. break;
  687. case SND_SOC_TPLG_TYPE_BYTES:
  688. sbe = (struct soc_bytes_ext *)kc->private_value;
  689. wdata[i].control = sbe->dobj.private;
  690. break;
  691. case SND_SOC_TPLG_TYPE_ENUM:
  692. se = (struct soc_enum *)kc->private_value;
  693. wdata[i].control = se->dobj.private;
  694. break;
  695. default:
  696. dev_err(scomp->dev, "Unknown kcontrol type %u in widget %s\n",
  697. widget->dobj.widget.kcontrol_type[i], widget->name);
  698. return -EINVAL;
  699. }
  700. if (!wdata[i].control) {
  701. dev_err(scomp->dev, "No scontrol for widget %s\n", widget->name);
  702. return -EINVAL;
  703. }
  704. cdata = wdata[i].control->ipc_control_data;
  705. if (widget->dobj.widget.kcontrol_type[i] == SND_SOC_TPLG_TYPE_BYTES) {
  706. /* make sure data is valid - data can be updated at runtime */
  707. if (cdata->data->magic != SOF_ABI_MAGIC)
  708. return -EINVAL;
  709. wdata[i].pdata = cdata->data->data;
  710. wdata[i].pdata_size = cdata->data->size;
  711. } else {
  712. /* points to the control data union */
  713. wdata[i].pdata = cdata->chanv;
  714. /*
  715. * wdata[i].control->size is calculated with struct_size
  716. * and includes the size of struct sof_ipc_ctrl_data
  717. */
  718. wdata[i].pdata_size = wdata[i].control->size -
  719. sizeof(struct sof_ipc_ctrl_data);
  720. }
  721. *size += wdata[i].pdata_size;
  722. /* get data type */
  723. switch (cdata->cmd) {
  724. case SOF_CTRL_CMD_VOLUME:
  725. case SOF_CTRL_CMD_ENUM:
  726. case SOF_CTRL_CMD_SWITCH:
  727. wdata[i].ipc_cmd = SOF_IPC_COMP_SET_VALUE;
  728. wdata[i].ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET;
  729. break;
  730. case SOF_CTRL_CMD_BINARY:
  731. wdata[i].ipc_cmd = SOF_IPC_COMP_SET_DATA;
  732. wdata[i].ctrl_type = SOF_CTRL_TYPE_DATA_SET;
  733. break;
  734. default:
  735. break;
  736. }
  737. }
  738. return 0;
  739. }
  740. static int sof_process_load(struct snd_soc_component *scomp,
  741. struct snd_sof_widget *swidget, int type)
  742. {
  743. struct snd_soc_dapm_widget *widget = swidget->widget;
  744. struct sof_ipc_comp_process *process;
  745. struct sof_widget_data *wdata = NULL;
  746. size_t ipc_data_size = 0;
  747. size_t ipc_size;
  748. int offset = 0;
  749. int ret;
  750. int i;
  751. /* allocate struct for widget control data sizes and types */
  752. if (widget->num_kcontrols) {
  753. wdata = kzalloc_objs(*wdata, widget->num_kcontrols);
  754. if (!wdata)
  755. return -ENOMEM;
  756. /* get possible component controls and get size of all pdata */
  757. ret = sof_get_control_data(scomp, widget, wdata, &ipc_data_size);
  758. if (ret < 0)
  759. goto out;
  760. }
  761. ipc_size = sizeof(struct sof_ipc_comp_process) + ipc_data_size;
  762. /* we are exceeding max ipc size, config needs to be sent separately */
  763. if (ipc_size > SOF_IPC_MSG_MAX_SIZE) {
  764. ipc_size -= ipc_data_size;
  765. ipc_data_size = 0;
  766. }
  767. process = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id);
  768. if (!process) {
  769. ret = -ENOMEM;
  770. goto out;
  771. }
  772. swidget->private = process;
  773. /* configure iir IPC message */
  774. process->comp.type = type;
  775. process->config.hdr.size = sizeof(process->config);
  776. /* parse one set of comp tokens */
  777. ret = sof_update_ipc_object(scomp, &process->config, SOF_COMP_TOKENS,
  778. swidget->tuples, swidget->num_tuples,
  779. sizeof(process->config), 1);
  780. if (ret < 0)
  781. goto err;
  782. dev_dbg(scomp->dev, "loaded process %s\n", swidget->widget->name);
  783. sof_dbg_comp_config(scomp, &process->config);
  784. /*
  785. * found private data in control, so copy it.
  786. * get possible component controls - get size of all pdata,
  787. * then memcpy with headers
  788. */
  789. if (ipc_data_size) {
  790. for (i = 0; i < widget->num_kcontrols; i++) {
  791. if (!wdata[i].pdata_size)
  792. continue;
  793. memcpy(&process->data[offset], wdata[i].pdata,
  794. wdata[i].pdata_size);
  795. offset += wdata[i].pdata_size;
  796. }
  797. }
  798. process->size = ipc_data_size;
  799. kfree(wdata);
  800. return 0;
  801. err:
  802. kfree(swidget->private);
  803. swidget->private = NULL;
  804. out:
  805. kfree(wdata);
  806. return ret;
  807. }
  808. static enum sof_comp_type find_process_comp_type(enum sof_ipc_process_type type)
  809. {
  810. int i;
  811. for (i = 0; i < ARRAY_SIZE(sof_process); i++) {
  812. if (sof_process[i].type == type)
  813. return sof_process[i].comp_type;
  814. }
  815. return SOF_COMP_NONE;
  816. }
  817. /*
  818. * Processing Component Topology - can be "effect", "codec", or general
  819. * "processing".
  820. */
  821. static int sof_widget_update_ipc_comp_process(struct snd_sof_widget *swidget)
  822. {
  823. struct snd_soc_component *scomp = swidget->scomp;
  824. struct sof_ipc_comp_process config;
  825. int ret;
  826. memset(&config, 0, sizeof(config));
  827. config.comp.core = swidget->core;
  828. /* parse one set of process tokens */
  829. ret = sof_update_ipc_object(scomp, &config, SOF_PROCESS_TOKENS, swidget->tuples,
  830. swidget->num_tuples, sizeof(config), 1);
  831. if (ret < 0)
  832. return ret;
  833. /* now load process specific data and send IPC */
  834. return sof_process_load(scomp, swidget, find_process_comp_type(config.type));
  835. }
  836. static int sof_link_hda_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  837. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  838. {
  839. struct sof_dai_private_data *private = dai->private;
  840. u32 size = sizeof(*config);
  841. int ret;
  842. /* init IPC */
  843. memset(&config->hda, 0, sizeof(config->hda));
  844. config->hdr.size = size;
  845. /* parse one set of HDA tokens */
  846. ret = sof_update_ipc_object(scomp, &config->hda, SOF_HDA_TOKENS, slink->tuples,
  847. slink->num_tuples, size, 1);
  848. if (ret < 0)
  849. return ret;
  850. dev_dbg(scomp->dev, "HDA config rate %d channels %d\n",
  851. config->hda.rate, config->hda.channels);
  852. config->hda.link_dma_ch = DMA_CHAN_INVALID;
  853. dai->number_configs = 1;
  854. dai->current_config = 0;
  855. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  856. if (!private->dai_config)
  857. return -ENOMEM;
  858. return 0;
  859. }
  860. static void sof_dai_set_format(struct snd_soc_tplg_hw_config *hw_config,
  861. struct sof_ipc_dai_config *config)
  862. {
  863. /* clock directions wrt codec */
  864. config->format &= ~SOF_DAI_FMT_CLOCK_PROVIDER_MASK;
  865. if (hw_config->bclk_provider == SND_SOC_TPLG_BCLK_CP) {
  866. /* codec is bclk provider */
  867. if (hw_config->fsync_provider == SND_SOC_TPLG_FSYNC_CP)
  868. config->format |= SOF_DAI_FMT_CBP_CFP;
  869. else
  870. config->format |= SOF_DAI_FMT_CBP_CFC;
  871. } else {
  872. /* codec is bclk consumer */
  873. if (hw_config->fsync_provider == SND_SOC_TPLG_FSYNC_CP)
  874. config->format |= SOF_DAI_FMT_CBC_CFP;
  875. else
  876. config->format |= SOF_DAI_FMT_CBC_CFC;
  877. }
  878. /* inverted clocks ? */
  879. config->format &= ~SOF_DAI_FMT_INV_MASK;
  880. if (hw_config->invert_bclk) {
  881. if (hw_config->invert_fsync)
  882. config->format |= SOF_DAI_FMT_IB_IF;
  883. else
  884. config->format |= SOF_DAI_FMT_IB_NF;
  885. } else {
  886. if (hw_config->invert_fsync)
  887. config->format |= SOF_DAI_FMT_NB_IF;
  888. else
  889. config->format |= SOF_DAI_FMT_NB_NF;
  890. }
  891. }
  892. static int sof_link_sai_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  893. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  894. {
  895. struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
  896. struct sof_dai_private_data *private = dai->private;
  897. u32 size = sizeof(*config);
  898. int ret;
  899. /* handle master/slave and inverted clocks */
  900. sof_dai_set_format(hw_config, config);
  901. /* init IPC */
  902. memset(&config->sai, 0, sizeof(config->sai));
  903. config->hdr.size = size;
  904. /* parse one set of SAI tokens */
  905. ret = sof_update_ipc_object(scomp, &config->sai, SOF_SAI_TOKENS, slink->tuples,
  906. slink->num_tuples, size, 1);
  907. if (ret < 0)
  908. return ret;
  909. config->sai.mclk_rate = le32_to_cpu(hw_config->mclk_rate);
  910. config->sai.bclk_rate = le32_to_cpu(hw_config->bclk_rate);
  911. config->sai.fsync_rate = le32_to_cpu(hw_config->fsync_rate);
  912. config->sai.mclk_direction = hw_config->mclk_direction;
  913. config->sai.tdm_slots = le32_to_cpu(hw_config->tdm_slots);
  914. config->sai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width);
  915. config->sai.rx_slots = le32_to_cpu(hw_config->rx_slots);
  916. config->sai.tx_slots = le32_to_cpu(hw_config->tx_slots);
  917. dev_info(scomp->dev,
  918. "tplg: config SAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n",
  919. config->dai_index, config->format,
  920. config->sai.mclk_rate, config->sai.tdm_slot_width,
  921. config->sai.tdm_slots, config->sai.mclk_id);
  922. if (config->sai.tdm_slots < 1 || config->sai.tdm_slots > 8) {
  923. dev_err(scomp->dev, "Invalid channel count for SAI%d\n", config->dai_index);
  924. return -EINVAL;
  925. }
  926. dai->number_configs = 1;
  927. dai->current_config = 0;
  928. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  929. if (!private->dai_config)
  930. return -ENOMEM;
  931. return 0;
  932. }
  933. static int sof_link_esai_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  934. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  935. {
  936. struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
  937. struct sof_dai_private_data *private = dai->private;
  938. u32 size = sizeof(*config);
  939. int ret;
  940. /* handle master/slave and inverted clocks */
  941. sof_dai_set_format(hw_config, config);
  942. /* init IPC */
  943. memset(&config->esai, 0, sizeof(config->esai));
  944. config->hdr.size = size;
  945. /* parse one set of ESAI tokens */
  946. ret = sof_update_ipc_object(scomp, &config->esai, SOF_ESAI_TOKENS, slink->tuples,
  947. slink->num_tuples, size, 1);
  948. if (ret < 0)
  949. return ret;
  950. config->esai.mclk_rate = le32_to_cpu(hw_config->mclk_rate);
  951. config->esai.bclk_rate = le32_to_cpu(hw_config->bclk_rate);
  952. config->esai.fsync_rate = le32_to_cpu(hw_config->fsync_rate);
  953. config->esai.mclk_direction = hw_config->mclk_direction;
  954. config->esai.tdm_slots = le32_to_cpu(hw_config->tdm_slots);
  955. config->esai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width);
  956. config->esai.rx_slots = le32_to_cpu(hw_config->rx_slots);
  957. config->esai.tx_slots = le32_to_cpu(hw_config->tx_slots);
  958. dev_info(scomp->dev,
  959. "tplg: config ESAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n",
  960. config->dai_index, config->format,
  961. config->esai.mclk_rate, config->esai.tdm_slot_width,
  962. config->esai.tdm_slots, config->esai.mclk_id);
  963. if (config->esai.tdm_slots < 1 || config->esai.tdm_slots > 8) {
  964. dev_err(scomp->dev, "Invalid channel count for ESAI%d\n", config->dai_index);
  965. return -EINVAL;
  966. }
  967. dai->number_configs = 1;
  968. dai->current_config = 0;
  969. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  970. if (!private->dai_config)
  971. return -ENOMEM;
  972. return 0;
  973. }
  974. static int sof_link_micfil_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  975. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  976. {
  977. struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
  978. struct sof_dai_private_data *private = dai->private;
  979. u32 size = sizeof(*config);
  980. int ret;
  981. /* handle master/slave and inverted clocks */
  982. sof_dai_set_format(hw_config, config);
  983. config->hdr.size = size;
  984. /* parse the required set of MICFIL PDM tokens based on num_hw_cfgs */
  985. ret = sof_update_ipc_object(scomp, &config->micfil, SOF_MICFIL_TOKENS, slink->tuples,
  986. slink->num_tuples, size, slink->num_hw_configs);
  987. if (ret < 0)
  988. return ret;
  989. dev_info(scomp->dev, "MICFIL PDM config dai_index %d channel %d rate %d\n",
  990. config->dai_index, config->micfil.pdm_ch, config->micfil.pdm_rate);
  991. dai->number_configs = 1;
  992. dai->current_config = 0;
  993. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  994. if (!private->dai_config)
  995. return -ENOMEM;
  996. return 0;
  997. }
  998. static int sof_link_acp_dmic_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  999. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  1000. {
  1001. struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
  1002. struct sof_dai_private_data *private = dai->private;
  1003. u32 size = sizeof(*config);
  1004. int ret;
  1005. /* handle master/slave and inverted clocks */
  1006. sof_dai_set_format(hw_config, config);
  1007. config->hdr.size = size;
  1008. /* parse the required set of ACPDMIC tokens based on num_hw_cfgs */
  1009. ret = sof_update_ipc_object(scomp, &config->acpdmic, SOF_ACPDMIC_TOKENS, slink->tuples,
  1010. slink->num_tuples, size, slink->num_hw_configs);
  1011. if (ret < 0)
  1012. return ret;
  1013. dev_info(scomp->dev, "ACP_DMIC config ACP%d channel %d rate %d\n",
  1014. config->dai_index, config->acpdmic.pdm_ch,
  1015. config->acpdmic.pdm_rate);
  1016. dai->number_configs = 1;
  1017. dai->current_config = 0;
  1018. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  1019. if (!private->dai_config)
  1020. return -ENOMEM;
  1021. return 0;
  1022. }
  1023. static int sof_link_acp_bt_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  1024. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  1025. {
  1026. struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
  1027. struct sof_dai_private_data *private = dai->private;
  1028. u32 size = sizeof(*config);
  1029. int ret;
  1030. /* handle master/slave and inverted clocks */
  1031. sof_dai_set_format(hw_config, config);
  1032. /* init IPC */
  1033. memset(&config->acpbt, 0, sizeof(config->acpbt));
  1034. config->hdr.size = size;
  1035. ret = sof_update_ipc_object(scomp, &config->acpbt, SOF_ACPI2S_TOKENS, slink->tuples,
  1036. slink->num_tuples, size, slink->num_hw_configs);
  1037. if (ret < 0)
  1038. return ret;
  1039. dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d tdm_mode %d\n",
  1040. config->dai_index, config->acpbt.tdm_slots,
  1041. config->acpbt.fsync_rate, config->acpbt.tdm_mode);
  1042. dai->number_configs = 1;
  1043. dai->current_config = 0;
  1044. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  1045. if (!private->dai_config)
  1046. return -ENOMEM;
  1047. return 0;
  1048. }
  1049. static int sof_link_acp_sp_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  1050. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  1051. {
  1052. struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
  1053. struct sof_dai_private_data *private = dai->private;
  1054. u32 size = sizeof(*config);
  1055. int ret;
  1056. /* handle master/slave and inverted clocks */
  1057. sof_dai_set_format(hw_config, config);
  1058. /* init IPC */
  1059. memset(&config->acpsp, 0, sizeof(config->acpsp));
  1060. config->hdr.size = size;
  1061. ret = sof_update_ipc_object(scomp, &config->acpsp, SOF_ACPI2S_TOKENS, slink->tuples,
  1062. slink->num_tuples, size, slink->num_hw_configs);
  1063. if (ret < 0)
  1064. return ret;
  1065. dev_info(scomp->dev, "ACP_SP config ACP%d channel %d rate %d tdm_mode %d\n",
  1066. config->dai_index, config->acpsp.tdm_slots,
  1067. config->acpsp.fsync_rate, config->acpsp.tdm_mode);
  1068. dai->number_configs = 1;
  1069. dai->current_config = 0;
  1070. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  1071. if (!private->dai_config)
  1072. return -ENOMEM;
  1073. return 0;
  1074. }
  1075. static int sof_link_acp_hs_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  1076. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  1077. {
  1078. struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
  1079. struct sof_dai_private_data *private = dai->private;
  1080. u32 size = sizeof(*config);
  1081. int ret;
  1082. /* Configures the DAI hardware format and inverted clocks */
  1083. sof_dai_set_format(hw_config, config);
  1084. /* init IPC */
  1085. memset(&config->acphs, 0, sizeof(config->acphs));
  1086. config->hdr.size = size;
  1087. ret = sof_update_ipc_object(scomp, &config->acphs, SOF_ACPI2S_TOKENS, slink->tuples,
  1088. slink->num_tuples, size, slink->num_hw_configs);
  1089. if (ret < 0)
  1090. return ret;
  1091. dev_info(scomp->dev, "ACP_HS config ACP%d channel %d rate %d tdm_mode %d\n",
  1092. config->dai_index, config->acphs.tdm_slots,
  1093. config->acphs.fsync_rate, config->acphs.tdm_mode);
  1094. dai->number_configs = 1;
  1095. dai->current_config = 0;
  1096. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  1097. if (!private->dai_config)
  1098. return -ENOMEM;
  1099. return 0;
  1100. }
  1101. static int sof_link_acp_sdw_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  1102. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  1103. {
  1104. struct sof_dai_private_data *private = dai->private;
  1105. u32 size = sizeof(*config);
  1106. int ret;
  1107. /* parse the required set of ACP_SDW tokens based on num_hw_cfgs */
  1108. ret = sof_update_ipc_object(scomp, &config->acp_sdw, SOF_ACP_SDW_TOKENS, slink->tuples,
  1109. slink->num_tuples, size, slink->num_hw_configs);
  1110. if (ret < 0)
  1111. return ret;
  1112. /* init IPC */
  1113. config->hdr.size = size;
  1114. dev_dbg(scomp->dev, "ACP SDW config rate %d channels %d\n",
  1115. config->acp_sdw.rate, config->acp_sdw.channels);
  1116. /* set config for all DAI's with name matching the link name */
  1117. dai->number_configs = 1;
  1118. dai->current_config = 0;
  1119. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  1120. if (!private->dai_config)
  1121. return -ENOMEM;
  1122. return 0;
  1123. }
  1124. static int sof_link_afe_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  1125. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  1126. {
  1127. struct sof_dai_private_data *private = dai->private;
  1128. u32 size = sizeof(*config);
  1129. int ret;
  1130. config->hdr.size = size;
  1131. /* parse the required set of AFE tokens based on num_hw_cfgs */
  1132. ret = sof_update_ipc_object(scomp, &config->afe, SOF_AFE_TOKENS, slink->tuples,
  1133. slink->num_tuples, size, slink->num_hw_configs);
  1134. if (ret < 0)
  1135. return ret;
  1136. dev_dbg(scomp->dev, "AFE config rate %d channels %d format:%d\n",
  1137. config->afe.rate, config->afe.channels, config->afe.format);
  1138. config->afe.stream_id = DMA_CHAN_INVALID;
  1139. dai->number_configs = 1;
  1140. dai->current_config = 0;
  1141. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  1142. if (!private->dai_config)
  1143. return -ENOMEM;
  1144. return 0;
  1145. }
  1146. static int sof_link_ssp_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  1147. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  1148. {
  1149. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
  1150. struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
  1151. struct sof_dai_private_data *private = dai->private;
  1152. u32 size = sizeof(*config);
  1153. int current_config = 0;
  1154. int i, ret;
  1155. /*
  1156. * Parse common data, we should have 1 common data per hw_config.
  1157. */
  1158. ret = sof_update_ipc_object(scomp, &config->ssp, SOF_SSP_TOKENS, slink->tuples,
  1159. slink->num_tuples, size, slink->num_hw_configs);
  1160. if (ret < 0)
  1161. return ret;
  1162. /* process all possible hw configs */
  1163. for (i = 0; i < slink->num_hw_configs; i++) {
  1164. if (le32_to_cpu(hw_config[i].id) == slink->default_hw_cfg_id)
  1165. current_config = i;
  1166. /* handle master/slave and inverted clocks */
  1167. sof_dai_set_format(&hw_config[i], &config[i]);
  1168. config[i].hdr.size = size;
  1169. if (sdev->mclk_id_override) {
  1170. dev_dbg(scomp->dev, "tplg: overriding topology mclk_id %d by quirk %d\n",
  1171. config[i].ssp.mclk_id, sdev->mclk_id_quirk);
  1172. config[i].ssp.mclk_id = sdev->mclk_id_quirk;
  1173. }
  1174. /* copy differentiating hw configs to ipc structs */
  1175. config[i].ssp.mclk_rate = le32_to_cpu(hw_config[i].mclk_rate);
  1176. config[i].ssp.bclk_rate = le32_to_cpu(hw_config[i].bclk_rate);
  1177. config[i].ssp.fsync_rate = le32_to_cpu(hw_config[i].fsync_rate);
  1178. config[i].ssp.tdm_slots = le32_to_cpu(hw_config[i].tdm_slots);
  1179. config[i].ssp.tdm_slot_width = le32_to_cpu(hw_config[i].tdm_slot_width);
  1180. config[i].ssp.mclk_direction = hw_config[i].mclk_direction;
  1181. config[i].ssp.rx_slots = le32_to_cpu(hw_config[i].rx_slots);
  1182. config[i].ssp.tx_slots = le32_to_cpu(hw_config[i].tx_slots);
  1183. dev_dbg(scomp->dev, "tplg: config SSP%d fmt %#x mclk %d bclk %d fclk %d width (%d)%d slots %d mclk id %d quirks %d clks_control %#x\n",
  1184. config[i].dai_index, config[i].format,
  1185. config[i].ssp.mclk_rate, config[i].ssp.bclk_rate,
  1186. config[i].ssp.fsync_rate, config[i].ssp.sample_valid_bits,
  1187. config[i].ssp.tdm_slot_width, config[i].ssp.tdm_slots,
  1188. config[i].ssp.mclk_id, config[i].ssp.quirks, config[i].ssp.clks_control);
  1189. /* validate SSP fsync rate and channel count */
  1190. if (config[i].ssp.fsync_rate < 8000 || config[i].ssp.fsync_rate > 192000) {
  1191. dev_err(scomp->dev, "Invalid fsync rate for SSP%d\n", config[i].dai_index);
  1192. return -EINVAL;
  1193. }
  1194. if (config[i].ssp.tdm_slots < 1 || config[i].ssp.tdm_slots > 8) {
  1195. dev_err(scomp->dev, "Invalid channel count for SSP%d\n",
  1196. config[i].dai_index);
  1197. return -EINVAL;
  1198. }
  1199. }
  1200. dai->number_configs = slink->num_hw_configs;
  1201. dai->current_config = current_config;
  1202. private->dai_config = kmemdup(config, size * slink->num_hw_configs, GFP_KERNEL);
  1203. if (!private->dai_config)
  1204. return -ENOMEM;
  1205. return 0;
  1206. }
  1207. static int sof_link_dmic_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  1208. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  1209. {
  1210. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
  1211. struct sof_dai_private_data *private = dai->private;
  1212. struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
  1213. struct sof_ipc_fw_version *v = &ready->version;
  1214. size_t size = sizeof(*config);
  1215. int i, ret;
  1216. /* Ensure the entire DMIC config struct is zeros */
  1217. memset(&config->dmic, 0, sizeof(config->dmic));
  1218. /* parse the required set of DMIC tokens based on num_hw_cfgs */
  1219. ret = sof_update_ipc_object(scomp, &config->dmic, SOF_DMIC_TOKENS, slink->tuples,
  1220. slink->num_tuples, size, slink->num_hw_configs);
  1221. if (ret < 0)
  1222. return ret;
  1223. /* parse the required set of DMIC PDM tokens based on number of active PDM's */
  1224. ret = sof_update_ipc_object(scomp, &config->dmic.pdm[0], SOF_DMIC_PDM_TOKENS,
  1225. slink->tuples, slink->num_tuples,
  1226. sizeof(struct sof_ipc_dai_dmic_pdm_ctrl),
  1227. config->dmic.num_pdm_active);
  1228. if (ret < 0)
  1229. return ret;
  1230. /* set IPC header size */
  1231. config->hdr.size = size;
  1232. /* debug messages */
  1233. dev_dbg(scomp->dev, "tplg: config DMIC%d driver version %d\n",
  1234. config->dai_index, config->dmic.driver_ipc_version);
  1235. dev_dbg(scomp->dev, "pdmclk_min %d pdm_clkmax %d duty_min %d\n",
  1236. config->dmic.pdmclk_min, config->dmic.pdmclk_max,
  1237. config->dmic.duty_min);
  1238. dev_dbg(scomp->dev, "duty_max %d fifo_fs %d num_pdms active %d\n",
  1239. config->dmic.duty_max, config->dmic.fifo_fs,
  1240. config->dmic.num_pdm_active);
  1241. dev_dbg(scomp->dev, "fifo word length %d\n", config->dmic.fifo_bits);
  1242. for (i = 0; i < config->dmic.num_pdm_active; i++) {
  1243. dev_dbg(scomp->dev, "pdm %d mic a %d mic b %d\n",
  1244. config->dmic.pdm[i].id,
  1245. config->dmic.pdm[i].enable_mic_a,
  1246. config->dmic.pdm[i].enable_mic_b);
  1247. dev_dbg(scomp->dev, "pdm %d polarity a %d polarity b %d\n",
  1248. config->dmic.pdm[i].id,
  1249. config->dmic.pdm[i].polarity_mic_a,
  1250. config->dmic.pdm[i].polarity_mic_b);
  1251. dev_dbg(scomp->dev, "pdm %d clk_edge %d skew %d\n",
  1252. config->dmic.pdm[i].id,
  1253. config->dmic.pdm[i].clk_edge,
  1254. config->dmic.pdm[i].skew);
  1255. }
  1256. /*
  1257. * this takes care of backwards compatible handling of fifo_bits_b.
  1258. * It is deprecated since firmware ABI version 3.0.1.
  1259. */
  1260. if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1))
  1261. config->dmic.fifo_bits_b = config->dmic.fifo_bits;
  1262. dai->number_configs = 1;
  1263. dai->current_config = 0;
  1264. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  1265. if (!private->dai_config)
  1266. return -ENOMEM;
  1267. return 0;
  1268. }
  1269. static int sof_link_alh_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
  1270. struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
  1271. {
  1272. struct sof_dai_private_data *private = dai->private;
  1273. u32 size = sizeof(*config);
  1274. int ret;
  1275. /* parse the required set of ALH tokens based on num_hw_cfgs */
  1276. ret = sof_update_ipc_object(scomp, &config->alh, SOF_ALH_TOKENS, slink->tuples,
  1277. slink->num_tuples, size, slink->num_hw_configs);
  1278. if (ret < 0)
  1279. return ret;
  1280. /* init IPC */
  1281. config->hdr.size = size;
  1282. /* set config for all DAI's with name matching the link name */
  1283. dai->number_configs = 1;
  1284. dai->current_config = 0;
  1285. private->dai_config = kmemdup(config, size, GFP_KERNEL);
  1286. if (!private->dai_config)
  1287. return -ENOMEM;
  1288. return 0;
  1289. }
  1290. static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget)
  1291. {
  1292. struct snd_soc_component *scomp = swidget->scomp;
  1293. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
  1294. struct snd_sof_dai *dai = swidget->private;
  1295. struct sof_dai_private_data *private;
  1296. struct sof_ipc_comp_dai *comp_dai;
  1297. size_t ipc_size = sizeof(*comp_dai);
  1298. struct sof_ipc_dai_config *config;
  1299. struct snd_sof_dai_link *slink;
  1300. int ret;
  1301. private = kzalloc_obj(*private);
  1302. if (!private)
  1303. return -ENOMEM;
  1304. dai->private = private;
  1305. private->comp_dai = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id);
  1306. if (!private->comp_dai) {
  1307. ret = -ENOMEM;
  1308. goto free;
  1309. }
  1310. /* configure dai IPC message */
  1311. comp_dai = private->comp_dai;
  1312. comp_dai->comp.type = SOF_COMP_DAI;
  1313. comp_dai->config.hdr.size = sizeof(comp_dai->config);
  1314. /* parse one set of DAI tokens */
  1315. ret = sof_update_ipc_object(scomp, comp_dai, SOF_DAI_TOKENS, swidget->tuples,
  1316. swidget->num_tuples, sizeof(*comp_dai), 1);
  1317. if (ret < 0)
  1318. goto free_comp;
  1319. /* update comp_tokens */
  1320. ret = sof_update_ipc_object(scomp, &comp_dai->config, SOF_COMP_TOKENS,
  1321. swidget->tuples, swidget->num_tuples,
  1322. sizeof(comp_dai->config), 1);
  1323. if (ret < 0)
  1324. goto free_comp;
  1325. /* Subtract the base to match the FW dai index. */
  1326. if (comp_dai->type == SOF_DAI_INTEL_ALH) {
  1327. if (comp_dai->dai_index < INTEL_ALH_DAI_INDEX_BASE) {
  1328. dev_err(sdev->dev,
  1329. "Invalid ALH dai index %d, only Pin numbers >= %d can be used\n",
  1330. comp_dai->dai_index, INTEL_ALH_DAI_INDEX_BASE);
  1331. ret = -EINVAL;
  1332. goto free_comp;
  1333. }
  1334. comp_dai->dai_index -= INTEL_ALH_DAI_INDEX_BASE;
  1335. }
  1336. dev_dbg(scomp->dev, "dai %s: type %d index %d\n",
  1337. swidget->widget->name, comp_dai->type, comp_dai->dai_index);
  1338. sof_dbg_comp_config(scomp, &comp_dai->config);
  1339. /* now update DAI config */
  1340. list_for_each_entry(slink, &sdev->dai_link_list, list) {
  1341. struct sof_ipc_dai_config common_config;
  1342. int i;
  1343. if (strcmp(slink->link->name, dai->name))
  1344. continue;
  1345. /* Reserve memory for all hw configs, eventually freed by widget */
  1346. config = kzalloc_objs(*config, slink->num_hw_configs);
  1347. if (!config) {
  1348. ret = -ENOMEM;
  1349. goto free_comp;
  1350. }
  1351. /* parse one set of DAI link tokens */
  1352. ret = sof_update_ipc_object(scomp, &common_config, SOF_DAI_LINK_TOKENS,
  1353. slink->tuples, slink->num_tuples,
  1354. sizeof(common_config), 1);
  1355. if (ret < 0)
  1356. goto free_config;
  1357. for (i = 0; i < slink->num_hw_configs; i++) {
  1358. config[i].hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG;
  1359. config[i].format = le32_to_cpu(slink->hw_configs[i].fmt);
  1360. config[i].type = common_config.type;
  1361. config[i].dai_index = comp_dai->dai_index;
  1362. }
  1363. switch (common_config.type) {
  1364. case SOF_DAI_INTEL_SSP:
  1365. ret = sof_link_ssp_load(scomp, slink, config, dai);
  1366. break;
  1367. case SOF_DAI_INTEL_DMIC:
  1368. ret = sof_link_dmic_load(scomp, slink, config, dai);
  1369. break;
  1370. case SOF_DAI_INTEL_HDA:
  1371. ret = sof_link_hda_load(scomp, slink, config, dai);
  1372. break;
  1373. case SOF_DAI_INTEL_ALH:
  1374. ret = sof_link_alh_load(scomp, slink, config, dai);
  1375. break;
  1376. case SOF_DAI_IMX_SAI:
  1377. ret = sof_link_sai_load(scomp, slink, config, dai);
  1378. break;
  1379. case SOF_DAI_IMX_ESAI:
  1380. ret = sof_link_esai_load(scomp, slink, config, dai);
  1381. break;
  1382. case SOF_DAI_IMX_MICFIL:
  1383. ret = sof_link_micfil_load(scomp, slink, config, dai);
  1384. break;
  1385. case SOF_DAI_AMD_BT:
  1386. ret = sof_link_acp_bt_load(scomp, slink, config, dai);
  1387. break;
  1388. case SOF_DAI_AMD_SP:
  1389. case SOF_DAI_AMD_SP_VIRTUAL:
  1390. ret = sof_link_acp_sp_load(scomp, slink, config, dai);
  1391. break;
  1392. case SOF_DAI_AMD_HS:
  1393. case SOF_DAI_AMD_HS_VIRTUAL:
  1394. ret = sof_link_acp_hs_load(scomp, slink, config, dai);
  1395. break;
  1396. case SOF_DAI_AMD_DMIC:
  1397. ret = sof_link_acp_dmic_load(scomp, slink, config, dai);
  1398. break;
  1399. case SOF_DAI_MEDIATEK_AFE:
  1400. ret = sof_link_afe_load(scomp, slink, config, dai);
  1401. break;
  1402. case SOF_DAI_AMD_SDW:
  1403. ret = sof_link_acp_sdw_load(scomp, slink, config, dai);
  1404. break;
  1405. default:
  1406. break;
  1407. }
  1408. if (ret < 0) {
  1409. dev_err(scomp->dev, "failed to load config for dai %s\n", dai->name);
  1410. goto free_config;
  1411. }
  1412. kfree(config);
  1413. }
  1414. return 0;
  1415. free_config:
  1416. kfree(config);
  1417. free_comp:
  1418. kfree(comp_dai);
  1419. free:
  1420. kfree(private);
  1421. dai->private = NULL;
  1422. return ret;
  1423. }
  1424. static void sof_ipc3_widget_free_comp_dai(struct snd_sof_widget *swidget)
  1425. {
  1426. switch (swidget->id) {
  1427. case snd_soc_dapm_dai_in:
  1428. case snd_soc_dapm_dai_out:
  1429. {
  1430. struct snd_sof_dai *dai = swidget->private;
  1431. struct sof_dai_private_data *dai_data;
  1432. if (!dai)
  1433. return;
  1434. dai_data = dai->private;
  1435. if (dai_data) {
  1436. kfree(dai_data->comp_dai);
  1437. kfree(dai_data->dai_config);
  1438. kfree(dai_data);
  1439. }
  1440. kfree(dai);
  1441. break;
  1442. }
  1443. default:
  1444. break;
  1445. }
  1446. }
  1447. static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute)
  1448. {
  1449. struct sof_ipc_pipe_comp_connect connect;
  1450. int ret;
  1451. connect.hdr.size = sizeof(connect);
  1452. connect.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT;
  1453. connect.source_id = sroute->src_widget->comp_id;
  1454. connect.sink_id = sroute->sink_widget->comp_id;
  1455. dev_dbg(sdev->dev, "setting up route %s -> %s\n",
  1456. sroute->src_widget->widget->name,
  1457. sroute->sink_widget->widget->name);
  1458. /* send ipc */
  1459. ret = sof_ipc_tx_message_no_reply(sdev->ipc, &connect, sizeof(connect));
  1460. if (ret < 0)
  1461. dev_err(sdev->dev, "%s: route %s -> %s failed\n", __func__,
  1462. sroute->src_widget->widget->name, sroute->sink_widget->widget->name);
  1463. return ret;
  1464. }
  1465. static int sof_ipc3_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
  1466. {
  1467. struct sof_ipc_ctrl_data *cdata;
  1468. size_t priv_size_check;
  1469. int ret;
  1470. if (scontrol->max_size < (sizeof(*cdata) + sizeof(struct sof_abi_hdr))) {
  1471. dev_err(sdev->dev, "%s: insufficient size for a bytes control: %zu.\n",
  1472. __func__, scontrol->max_size);
  1473. return -EINVAL;
  1474. }
  1475. if (scontrol->priv_size > scontrol->max_size - sizeof(*cdata)) {
  1476. dev_err(sdev->dev,
  1477. "%s: bytes data size %zu exceeds max %zu.\n", __func__,
  1478. scontrol->priv_size, scontrol->max_size - sizeof(*cdata));
  1479. return -EINVAL;
  1480. }
  1481. scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL);
  1482. if (!scontrol->ipc_control_data)
  1483. return -ENOMEM;
  1484. scontrol->size = sizeof(struct sof_ipc_ctrl_data) + scontrol->priv_size;
  1485. cdata = scontrol->ipc_control_data;
  1486. cdata->cmd = SOF_CTRL_CMD_BINARY;
  1487. cdata->index = scontrol->index;
  1488. if (scontrol->priv_size > 0) {
  1489. memcpy(cdata->data, scontrol->priv, scontrol->priv_size);
  1490. kfree(scontrol->priv);
  1491. scontrol->priv = NULL;
  1492. if (cdata->data->magic != SOF_ABI_MAGIC) {
  1493. dev_err(sdev->dev, "Wrong ABI magic 0x%08x.\n", cdata->data->magic);
  1494. ret = -EINVAL;
  1495. goto err;
  1496. }
  1497. if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
  1498. dev_err(sdev->dev, "Incompatible ABI version 0x%08x.\n",
  1499. cdata->data->abi);
  1500. ret = -EINVAL;
  1501. goto err;
  1502. }
  1503. priv_size_check = cdata->data->size + sizeof(struct sof_abi_hdr);
  1504. if (priv_size_check != scontrol->priv_size) {
  1505. dev_err(sdev->dev, "Conflict in bytes (%zu) vs. priv size (%zu).\n",
  1506. priv_size_check, scontrol->priv_size);
  1507. ret = -EINVAL;
  1508. goto err;
  1509. }
  1510. }
  1511. return 0;
  1512. err:
  1513. kfree(scontrol->ipc_control_data);
  1514. scontrol->ipc_control_data = NULL;
  1515. return ret;
  1516. }
  1517. static int sof_ipc3_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
  1518. {
  1519. struct sof_ipc_ctrl_data *cdata;
  1520. int i;
  1521. /* init the volume get/put data */
  1522. scontrol->size = struct_size(cdata, chanv, scontrol->num_channels);
  1523. scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL);
  1524. if (!scontrol->ipc_control_data)
  1525. return -ENOMEM;
  1526. cdata = scontrol->ipc_control_data;
  1527. cdata->index = scontrol->index;
  1528. /* set cmd for mixer control */
  1529. if (scontrol->max == 1) {
  1530. cdata->cmd = SOF_CTRL_CMD_SWITCH;
  1531. return 0;
  1532. }
  1533. cdata->cmd = SOF_CTRL_CMD_VOLUME;
  1534. /* set default volume values to 0dB in control */
  1535. for (i = 0; i < scontrol->num_channels; i++) {
  1536. cdata->chanv[i].channel = i;
  1537. cdata->chanv[i].value = VOL_ZERO_DB;
  1538. }
  1539. return 0;
  1540. }
  1541. static int sof_ipc3_control_load_enum(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
  1542. {
  1543. struct sof_ipc_ctrl_data *cdata;
  1544. /* init the enum get/put data */
  1545. scontrol->size = struct_size(cdata, chanv, scontrol->num_channels);
  1546. scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL);
  1547. if (!scontrol->ipc_control_data)
  1548. return -ENOMEM;
  1549. cdata = scontrol->ipc_control_data;
  1550. cdata->index = scontrol->index;
  1551. cdata->cmd = SOF_CTRL_CMD_ENUM;
  1552. return 0;
  1553. }
  1554. static int sof_ipc3_control_setup(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
  1555. {
  1556. switch (scontrol->info_type) {
  1557. case SND_SOC_TPLG_CTL_VOLSW:
  1558. case SND_SOC_TPLG_CTL_VOLSW_SX:
  1559. case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
  1560. return sof_ipc3_control_load_volume(sdev, scontrol);
  1561. case SND_SOC_TPLG_CTL_BYTES:
  1562. return sof_ipc3_control_load_bytes(sdev, scontrol);
  1563. case SND_SOC_TPLG_CTL_ENUM:
  1564. case SND_SOC_TPLG_CTL_ENUM_VALUE:
  1565. return sof_ipc3_control_load_enum(sdev, scontrol);
  1566. default:
  1567. break;
  1568. }
  1569. return 0;
  1570. }
  1571. static int sof_ipc3_control_free(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
  1572. {
  1573. struct sof_ipc_free fcomp;
  1574. fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_FREE;
  1575. fcomp.hdr.size = sizeof(fcomp);
  1576. fcomp.id = scontrol->comp_id;
  1577. /* send IPC to the DSP */
  1578. return sof_ipc_tx_message_no_reply(sdev->ipc, &fcomp, sizeof(fcomp));
  1579. }
  1580. /* send pcm params ipc */
  1581. static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, int dir)
  1582. {
  1583. struct snd_soc_component *scomp = swidget->scomp;
  1584. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
  1585. struct snd_pcm_hw_params *params;
  1586. struct sof_ipc_pcm_params pcm;
  1587. struct snd_sof_pcm *spcm;
  1588. int ret;
  1589. /* get runtime PCM params using widget's stream name */
  1590. spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname);
  1591. if (!spcm) {
  1592. dev_err(scomp->dev, "Cannot find PCM for %s\n", swidget->widget->name);
  1593. return -EINVAL;
  1594. }
  1595. params = &spcm->params[dir];
  1596. /* set IPC PCM params */
  1597. memset(&pcm, 0, sizeof(pcm));
  1598. pcm.hdr.size = sizeof(pcm);
  1599. pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS;
  1600. pcm.comp_id = swidget->comp_id;
  1601. pcm.params.hdr.size = sizeof(pcm.params);
  1602. pcm.params.direction = dir;
  1603. pcm.params.sample_valid_bytes = params_width(params) >> 3;
  1604. pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED;
  1605. pcm.params.rate = params_rate(params);
  1606. pcm.params.channels = params_channels(params);
  1607. pcm.params.host_period_bytes = params_period_bytes(params);
  1608. /* set format */
  1609. switch (params_format(params)) {
  1610. case SNDRV_PCM_FORMAT_S16:
  1611. pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE;
  1612. break;
  1613. case SNDRV_PCM_FORMAT_S24:
  1614. pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE;
  1615. break;
  1616. case SNDRV_PCM_FORMAT_S32:
  1617. pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE;
  1618. break;
  1619. default:
  1620. return -EINVAL;
  1621. }
  1622. /* send IPC to the DSP */
  1623. ret = sof_ipc_tx_message_no_reply(sdev->ipc, &pcm, sizeof(pcm));
  1624. if (ret < 0)
  1625. dev_err(scomp->dev, "%s: PCM params failed for %s\n", __func__,
  1626. swidget->widget->name);
  1627. return ret;
  1628. }
  1629. /* send stream trigger ipc */
  1630. static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int cmd)
  1631. {
  1632. struct snd_soc_component *scomp = swidget->scomp;
  1633. struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
  1634. struct sof_ipc_stream stream;
  1635. int ret;
  1636. /* set IPC stream params */
  1637. stream.hdr.size = sizeof(stream);
  1638. stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | cmd;
  1639. stream.comp_id = swidget->comp_id;
  1640. /* send IPC to the DSP */
  1641. ret = sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream));
  1642. if (ret < 0)
  1643. dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name);
  1644. return ret;
  1645. }
  1646. static int sof_ipc3_keyword_dapm_event(struct snd_soc_dapm_widget *w,
  1647. struct snd_kcontrol *k, int event)
  1648. {
  1649. struct snd_sof_widget *swidget = w->dobj.private;
  1650. struct snd_soc_component *scomp;
  1651. int stream = SNDRV_PCM_STREAM_CAPTURE;
  1652. struct snd_sof_pcm *spcm;
  1653. int ret = 0;
  1654. if (!swidget)
  1655. return 0;
  1656. scomp = swidget->scomp;
  1657. dev_dbg(scomp->dev, "received event %d for widget %s\n",
  1658. event, w->name);
  1659. /* get runtime PCM params using widget's stream name */
  1660. spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname);
  1661. if (!spcm) {
  1662. dev_err(scomp->dev, "%s: Cannot find PCM for %s\n", __func__,
  1663. swidget->widget->name);
  1664. return -EINVAL;
  1665. }
  1666. /* process events */
  1667. switch (event) {
  1668. case SND_SOC_DAPM_PRE_PMU:
  1669. if (spcm->stream[stream].suspend_ignored) {
  1670. dev_dbg(scomp->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n");
  1671. return 0;
  1672. }
  1673. /* set pcm params */
  1674. ret = sof_ipc3_keyword_detect_pcm_params(swidget, stream);
  1675. if (ret < 0) {
  1676. dev_err(scomp->dev, "%s: Failed to set pcm params for widget %s\n",
  1677. __func__, swidget->widget->name);
  1678. break;
  1679. }
  1680. /* start trigger */
  1681. ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_TRIG_START);
  1682. if (ret < 0)
  1683. dev_err(scomp->dev, "%s: Failed to trigger widget %s\n", __func__,
  1684. swidget->widget->name);
  1685. break;
  1686. case SND_SOC_DAPM_POST_PMD:
  1687. if (spcm->stream[stream].suspend_ignored) {
  1688. dev_dbg(scomp->dev,
  1689. "POST_PMD event ignored, KWD pipeline will remain RUNNING\n");
  1690. return 0;
  1691. }
  1692. /* stop trigger */
  1693. ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP);
  1694. if (ret < 0)
  1695. dev_err(scomp->dev, "%s: Failed to trigger widget %s\n", __func__,
  1696. swidget->widget->name);
  1697. /* pcm free */
  1698. ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_PCM_FREE);
  1699. if (ret < 0)
  1700. dev_err(scomp->dev, "%s: Failed to free PCM for widget %s\n", __func__,
  1701. swidget->widget->name);
  1702. break;
  1703. default:
  1704. break;
  1705. }
  1706. return ret;
  1707. }
  1708. /* event handlers for keyword detect component */
  1709. static const struct snd_soc_tplg_widget_events sof_kwd_events[] = {
  1710. {SOF_KEYWORD_DETECT_DAPM_EVENT, sof_ipc3_keyword_dapm_event},
  1711. };
  1712. static int sof_ipc3_widget_bind_event(struct snd_soc_component *scomp,
  1713. struct snd_sof_widget *swidget, u16 event_type)
  1714. {
  1715. struct sof_ipc_comp *ipc_comp;
  1716. /* validate widget event type */
  1717. switch (event_type) {
  1718. case SOF_KEYWORD_DETECT_DAPM_EVENT:
  1719. /* only KEYWORD_DETECT comps should handle this */
  1720. if (swidget->id != snd_soc_dapm_effect)
  1721. break;
  1722. ipc_comp = swidget->private;
  1723. if (ipc_comp && ipc_comp->type != SOF_COMP_KEYWORD_DETECT)
  1724. break;
  1725. /* bind event to keyword detect comp */
  1726. return snd_soc_tplg_widget_bind_event(swidget->widget, sof_kwd_events,
  1727. ARRAY_SIZE(sof_kwd_events), event_type);
  1728. default:
  1729. break;
  1730. }
  1731. dev_err(scomp->dev, "Invalid event type %d for widget %s\n", event_type,
  1732. swidget->widget->name);
  1733. return -EINVAL;
  1734. }
  1735. static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
  1736. {
  1737. struct sof_ipc_pipe_ready ready;
  1738. int ret;
  1739. dev_dbg(sdev->dev, "tplg: complete pipeline %s id %d\n",
  1740. swidget->widget->name, swidget->comp_id);
  1741. memset(&ready, 0, sizeof(ready));
  1742. ready.hdr.size = sizeof(ready);
  1743. ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE;
  1744. ready.comp_id = swidget->comp_id;
  1745. ret = sof_ipc_tx_message_no_reply(sdev->ipc, &ready, sizeof(ready));
  1746. if (ret < 0)
  1747. return ret;
  1748. return 1;
  1749. }
  1750. static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
  1751. {
  1752. struct sof_ipc_free ipc_free = {
  1753. .hdr = {
  1754. .size = sizeof(ipc_free),
  1755. .cmd = SOF_IPC_GLB_TPLG_MSG,
  1756. },
  1757. .id = swidget->comp_id,
  1758. };
  1759. int ret;
  1760. if (!swidget->private)
  1761. return 0;
  1762. switch (swidget->id) {
  1763. case snd_soc_dapm_scheduler:
  1764. {
  1765. ipc_free.hdr.cmd |= SOF_IPC_TPLG_PIPE_FREE;
  1766. break;
  1767. }
  1768. case snd_soc_dapm_buffer:
  1769. ipc_free.hdr.cmd |= SOF_IPC_TPLG_BUFFER_FREE;
  1770. break;
  1771. default:
  1772. ipc_free.hdr.cmd |= SOF_IPC_TPLG_COMP_FREE;
  1773. break;
  1774. }
  1775. ret = sof_ipc_tx_message_no_reply(sdev->ipc, &ipc_free, sizeof(ipc_free));
  1776. if (ret < 0)
  1777. dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name);
  1778. return ret;
  1779. }
  1780. static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget,
  1781. unsigned int flags, struct snd_sof_dai_config_data *data)
  1782. {
  1783. struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
  1784. struct snd_sof_dai *dai = swidget->private;
  1785. struct sof_dai_private_data *private;
  1786. struct sof_ipc_dai_config *config;
  1787. int ret = 0;
  1788. if (!dai || !dai->private) {
  1789. dev_err(sdev->dev, "No private data for DAI %s\n", swidget->widget->name);
  1790. return -EINVAL;
  1791. }
  1792. private = dai->private;
  1793. if (!private->dai_config) {
  1794. dev_err(sdev->dev, "No config for DAI %s\n", dai->name);
  1795. return -EINVAL;
  1796. }
  1797. config = &private->dai_config[dai->current_config];
  1798. if (!config) {
  1799. dev_err(sdev->dev, "Invalid current config for DAI %s\n", dai->name);
  1800. return -EINVAL;
  1801. }
  1802. switch (config->type) {
  1803. case SOF_DAI_INTEL_SSP:
  1804. /*
  1805. * DAI_CONFIG IPC during hw_params/hw_free for SSP DAI's is not supported in older
  1806. * firmware
  1807. */
  1808. if (v->abi_version < SOF_ABI_VER(3, 18, 0) &&
  1809. ((flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) ||
  1810. (flags & SOF_DAI_CONFIG_FLAGS_HW_FREE)))
  1811. return 0;
  1812. break;
  1813. case SOF_DAI_INTEL_HDA:
  1814. if (data)
  1815. config->hda.link_dma_ch = data->dai_data;
  1816. break;
  1817. case SOF_DAI_INTEL_ALH:
  1818. if (data) {
  1819. /* save the dai_index during hw_params and reuse it for hw_free */
  1820. if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
  1821. /* Subtract the base to match the FW dai index. */
  1822. if (data->dai_index < INTEL_ALH_DAI_INDEX_BASE) {
  1823. dev_err(sdev->dev,
  1824. "Invalid ALH dai index %d, only Pin numbers >= %d can be used\n",
  1825. config->dai_index, INTEL_ALH_DAI_INDEX_BASE);
  1826. return -EINVAL;
  1827. }
  1828. config->dai_index = data->dai_index - INTEL_ALH_DAI_INDEX_BASE;
  1829. }
  1830. config->alh.stream_id = data->dai_data;
  1831. }
  1832. break;
  1833. default:
  1834. break;
  1835. }
  1836. /*
  1837. * The dai_config op is invoked several times and the flags argument varies as below:
  1838. * BE DAI hw_params: When the op is invoked during the BE DAI hw_params, flags contains
  1839. * SOF_DAI_CONFIG_FLAGS_HW_PARAMS along with quirks
  1840. * FE DAI hw_params: When invoked during FE DAI hw_params after the DAI widget has
  1841. * just been set up in the DSP, flags is set to SOF_DAI_CONFIG_FLAGS_HW_PARAMS with no
  1842. * quirks
  1843. * BE DAI trigger: When invoked during the BE DAI trigger, flags is set to
  1844. * SOF_DAI_CONFIG_FLAGS_PAUSE and contains no quirks
  1845. * BE DAI hw_free: When invoked during the BE DAI hw_free, flags is set to
  1846. * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks
  1847. * FE DAI hw_free: When invoked during the FE DAI hw_free, flags is set to
  1848. * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks
  1849. *
  1850. * The DAI_CONFIG IPC is sent to the DSP, only after the widget is set up during the FE
  1851. * DAI hw_params. But since the BE DAI hw_params precedes the FE DAI hw_params, the quirks
  1852. * need to be preserved when assigning the flags before sending the IPC.
  1853. * For the case of PAUSE/HW_FREE, since there are no quirks, flags can be used as is.
  1854. */
  1855. if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
  1856. /* Clear stale command */
  1857. config->flags &= ~SOF_DAI_CONFIG_FLAGS_CMD_MASK;
  1858. config->flags |= flags;
  1859. } else {
  1860. config->flags = flags;
  1861. }
  1862. /* only send the IPC if the widget is set up in the DSP */
  1863. if (swidget->use_count > 0) {
  1864. ret = sof_ipc_tx_message_no_reply(sdev->ipc, config, config->hdr.size);
  1865. if (ret < 0)
  1866. dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name);
  1867. /* clear the flags once the IPC has been sent even if it fails */
  1868. config->flags = SOF_DAI_CONFIG_FLAGS_NONE;
  1869. }
  1870. return ret;
  1871. }
  1872. static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
  1873. {
  1874. int ret;
  1875. if (!swidget->private)
  1876. return 0;
  1877. switch (swidget->id) {
  1878. case snd_soc_dapm_dai_in:
  1879. case snd_soc_dapm_dai_out:
  1880. {
  1881. struct snd_sof_dai *dai = swidget->private;
  1882. struct sof_dai_private_data *dai_data = dai->private;
  1883. struct sof_ipc_comp *comp = &dai_data->comp_dai->comp;
  1884. ret = sof_ipc_tx_message_no_reply(sdev->ipc, dai_data->comp_dai, comp->hdr.size);
  1885. break;
  1886. }
  1887. case snd_soc_dapm_scheduler:
  1888. {
  1889. struct sof_ipc_pipe_new *pipeline;
  1890. pipeline = swidget->private;
  1891. ret = sof_ipc_tx_message_no_reply(sdev->ipc, pipeline, sizeof(*pipeline));
  1892. break;
  1893. }
  1894. default:
  1895. {
  1896. struct sof_ipc_cmd_hdr *hdr;
  1897. hdr = swidget->private;
  1898. ret = sof_ipc_tx_message_no_reply(sdev->ipc, swidget->private, hdr->size);
  1899. break;
  1900. }
  1901. }
  1902. if (ret < 0)
  1903. dev_err(sdev->dev, "Failed to setup widget %s\n", swidget->widget->name);
  1904. return ret;
  1905. }
  1906. static int sof_ipc3_set_up_all_pipelines(struct snd_sof_dev *sdev, bool verify)
  1907. {
  1908. struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
  1909. struct snd_sof_widget *swidget;
  1910. struct snd_sof_route *sroute;
  1911. int ret;
  1912. /* restore pipeline components */
  1913. list_for_each_entry(swidget, &sdev->widget_list, list) {
  1914. /* only set up the widgets belonging to static pipelines */
  1915. if (!verify && swidget->dynamic_pipeline_widget)
  1916. continue;
  1917. /*
  1918. * For older firmware, skip scheduler widgets in this loop,
  1919. * sof_widget_setup() will be called in the 'complete pipeline' loop
  1920. */
  1921. if (v->abi_version < SOF_ABI_VER(3, 19, 0) &&
  1922. swidget->id == snd_soc_dapm_scheduler)
  1923. continue;
  1924. /* update DAI config. The IPC will be sent in sof_widget_setup() */
  1925. if (WIDGET_IS_DAI(swidget->id)) {
  1926. struct snd_sof_dai *dai = swidget->private;
  1927. struct sof_dai_private_data *private;
  1928. struct sof_ipc_dai_config *config;
  1929. if (!dai || !dai->private)
  1930. continue;
  1931. private = dai->private;
  1932. if (!private->dai_config)
  1933. continue;
  1934. config = private->dai_config;
  1935. /*
  1936. * The link DMA channel would be invalidated for running
  1937. * streams but not for streams that were in the PAUSED
  1938. * state during suspend. So invalidate it here before setting
  1939. * the dai config in the DSP.
  1940. */
  1941. if (config->type == SOF_DAI_INTEL_HDA)
  1942. config->hda.link_dma_ch = DMA_CHAN_INVALID;
  1943. }
  1944. ret = sof_widget_setup(sdev, swidget);
  1945. if (ret < 0)
  1946. return ret;
  1947. }
  1948. /* restore pipeline connections */
  1949. list_for_each_entry(sroute, &sdev->route_list, list) {
  1950. /* only set up routes belonging to static pipelines */
  1951. if (!verify && (sroute->src_widget->dynamic_pipeline_widget ||
  1952. sroute->sink_widget->dynamic_pipeline_widget))
  1953. continue;
  1954. /*
  1955. * For virtual routes, both sink and source are not buffer. IPC3 only supports
  1956. * connections between a buffer and a component. Ignore the rest.
  1957. */
  1958. if (sroute->src_widget->id != snd_soc_dapm_buffer &&
  1959. sroute->sink_widget->id != snd_soc_dapm_buffer)
  1960. continue;
  1961. ret = sof_route_setup(sdev, sroute->src_widget->widget,
  1962. sroute->sink_widget->widget);
  1963. if (ret < 0) {
  1964. dev_err(sdev->dev, "%s: route set up failed\n", __func__);
  1965. return ret;
  1966. }
  1967. }
  1968. /* complete pipeline */
  1969. list_for_each_entry(swidget, &sdev->widget_list, list) {
  1970. switch (swidget->id) {
  1971. case snd_soc_dapm_scheduler:
  1972. /* only complete static pipelines */
  1973. if (!verify && swidget->dynamic_pipeline_widget)
  1974. continue;
  1975. if (v->abi_version < SOF_ABI_VER(3, 19, 0)) {
  1976. ret = sof_widget_setup(sdev, swidget);
  1977. if (ret < 0)
  1978. return ret;
  1979. }
  1980. swidget->spipe->complete = sof_ipc3_complete_pipeline(sdev, swidget);
  1981. if (swidget->spipe->complete < 0)
  1982. return swidget->spipe->complete;
  1983. break;
  1984. default:
  1985. break;
  1986. }
  1987. }
  1988. return 0;
  1989. }
  1990. /*
  1991. * Free the PCM, its associated widgets and set the prepared flag to false for all PCMs that
  1992. * did not get suspended(ex: paused streams) so the widgets can be set up again during resume.
  1993. */
  1994. static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev)
  1995. {
  1996. struct snd_sof_widget *swidget;
  1997. int ret;
  1998. /*
  1999. * free all PCMs and their associated DAPM widgets if their connected DAPM widget
  2000. * list is not NULL. This should only be true for paused streams at this point.
  2001. * This is equivalent to the handling of FE DAI suspend trigger for running streams.
  2002. */
  2003. ret = sof_pcm_free_all_streams(sdev);
  2004. if (ret)
  2005. return ret;
  2006. /*
  2007. * free any left over DAI widgets. This is equivalent to the handling of suspend trigger
  2008. * for the BE DAI for running streams.
  2009. */
  2010. list_for_each_entry(swidget, &sdev->widget_list, list)
  2011. if (WIDGET_IS_DAI(swidget->id) && swidget->use_count == 1) {
  2012. ret = sof_widget_free(sdev, swidget);
  2013. if (ret < 0)
  2014. return ret;
  2015. }
  2016. return 0;
  2017. }
  2018. static int sof_ipc3_free_widgets_in_list(struct snd_sof_dev *sdev, bool include_scheduler,
  2019. bool *dyn_widgets, bool verify)
  2020. {
  2021. struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
  2022. struct snd_sof_widget *swidget;
  2023. int ret;
  2024. list_for_each_entry(swidget, &sdev->widget_list, list) {
  2025. if (swidget->dynamic_pipeline_widget) {
  2026. *dyn_widgets = true;
  2027. continue;
  2028. }
  2029. /* Do not free widgets for static pipelines with FW older than SOF2.2 */
  2030. if (!verify && !swidget->dynamic_pipeline_widget &&
  2031. SOF_FW_VER(v->major, v->minor, v->micro) < SOF_FW_VER(2, 2, 0)) {
  2032. scoped_guard(mutex, &swidget->setup_mutex)
  2033. swidget->use_count = 0;
  2034. if (swidget->spipe)
  2035. swidget->spipe->complete = 0;
  2036. continue;
  2037. }
  2038. if (include_scheduler && swidget->id != snd_soc_dapm_scheduler)
  2039. continue;
  2040. if (!include_scheduler && swidget->id == snd_soc_dapm_scheduler)
  2041. continue;
  2042. ret = sof_widget_free(sdev, swidget);
  2043. if (ret < 0)
  2044. return ret;
  2045. }
  2046. return 0;
  2047. }
  2048. /*
  2049. * For older firmware, this function doesn't free widgets for static pipelines during suspend.
  2050. * It only resets use_count for all widgets.
  2051. */
  2052. static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify)
  2053. {
  2054. struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
  2055. struct snd_sof_widget *swidget;
  2056. struct snd_sof_route *sroute;
  2057. bool dyn_widgets = false;
  2058. int ret;
  2059. /*
  2060. * This function is called during suspend and for one-time topology verification during
  2061. * first boot. In both cases, there is no need to protect swidget->use_count and
  2062. * sroute->setup because during suspend all running streams are suspended and during
  2063. * topology loading the sound card unavailable to open PCMs. Do not free the scheduler
  2064. * widgets yet so that the secondary cores do not get powered down before all the widgets
  2065. * associated with the scheduler are freed.
  2066. */
  2067. ret = sof_ipc3_free_widgets_in_list(sdev, false, &dyn_widgets, verify);
  2068. if (ret < 0)
  2069. return ret;
  2070. /*
  2071. * Tear down all pipelines associated with PCMs that did not get suspended
  2072. * and unset the prepare flag so that they can be set up again during resume.
  2073. * Skip this step for older firmware unless topology has any
  2074. * dynamic pipeline (in which case the step is mandatory).
  2075. */
  2076. if (!verify && (dyn_widgets || SOF_FW_VER(v->major, v->minor, v->micro) >=
  2077. SOF_FW_VER(2, 2, 0))) {
  2078. ret = sof_tear_down_left_over_pipelines(sdev);
  2079. if (ret < 0) {
  2080. dev_err(sdev->dev, "failed to tear down paused pipelines\n");
  2081. return ret;
  2082. }
  2083. }
  2084. /* free all the scheduler widgets now. This will also power down the secondary cores */
  2085. ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify);
  2086. if (ret < 0)
  2087. return ret;
  2088. list_for_each_entry(sroute, &sdev->route_list, list)
  2089. sroute->setup = false;
  2090. /*
  2091. * before suspending, make sure the refcounts are all zeroed out. There's no way
  2092. * to recover at this point but this will help root cause bad sequences leading to
  2093. * more issues on resume
  2094. */
  2095. list_for_each_entry(swidget, &sdev->widget_list, list) {
  2096. if (swidget->use_count != 0) {
  2097. dev_err(sdev->dev, "%s: widget %s is still in use: count %d\n",
  2098. __func__, swidget->widget->name, swidget->use_count);
  2099. }
  2100. }
  2101. return 0;
  2102. }
  2103. static int sof_ipc3_dai_get_param(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int param_type)
  2104. {
  2105. struct sof_dai_private_data *private = dai->private;
  2106. if (!private || !private->dai_config)
  2107. return 0;
  2108. switch (private->dai_config->type) {
  2109. case SOF_DAI_INTEL_SSP:
  2110. switch (param_type) {
  2111. case SOF_DAI_PARAM_INTEL_SSP_MCLK:
  2112. return private->dai_config->ssp.mclk_rate;
  2113. case SOF_DAI_PARAM_INTEL_SSP_BCLK:
  2114. return private->dai_config->ssp.bclk_rate;
  2115. case SOF_DAI_PARAM_INTEL_SSP_TDM_SLOTS:
  2116. return private->dai_config->ssp.tdm_slots;
  2117. default:
  2118. dev_err(sdev->dev, "invalid SSP param %d\n", param_type);
  2119. break;
  2120. }
  2121. break;
  2122. default:
  2123. /* not yet implemented for platforms other than the above */
  2124. dev_err(sdev->dev, "DAI type %d not supported yet!\n", private->dai_config->type);
  2125. break;
  2126. }
  2127. return -EINVAL;
  2128. }
  2129. static int sof_ipc3_parse_manifest(struct snd_soc_component *scomp, int index,
  2130. struct snd_soc_tplg_manifest *man)
  2131. {
  2132. u32 size = le32_to_cpu(man->priv.size);
  2133. u32 abi_version;
  2134. /* backward compatible with tplg without ABI info */
  2135. if (!size) {
  2136. dev_dbg(scomp->dev, "No topology ABI info\n");
  2137. return 0;
  2138. }
  2139. if (size != SOF_IPC3_TPLG_ABI_SIZE) {
  2140. dev_err(scomp->dev, "%s: Invalid topology ABI size: %u\n",
  2141. __func__, size);
  2142. return -EINVAL;
  2143. }
  2144. dev_info(scomp->dev,
  2145. "Topology: ABI %d:%d:%d Kernel ABI %d:%d:%d\n",
  2146. man->priv.data[0], man->priv.data[1], man->priv.data[2],
  2147. SOF_ABI_MAJOR, SOF_ABI_MINOR, SOF_ABI_PATCH);
  2148. abi_version = SOF_ABI_VER(man->priv.data[0], man->priv.data[1], man->priv.data[2]);
  2149. if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, abi_version)) {
  2150. dev_err(scomp->dev, "%s: Incompatible topology ABI version\n", __func__);
  2151. return -EINVAL;
  2152. }
  2153. if (IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS) &&
  2154. SOF_ABI_VERSION_MINOR(abi_version) > SOF_ABI_MINOR) {
  2155. dev_err(scomp->dev, "%s: Topology ABI is more recent than kernel\n", __func__);
  2156. return -EINVAL;
  2157. }
  2158. return 0;
  2159. }
  2160. static int sof_ipc3_link_setup(struct snd_sof_dev *sdev, struct snd_soc_dai_link *link)
  2161. {
  2162. if (link->no_pcm)
  2163. return 0;
  2164. /*
  2165. * set default trigger order for all links. Exceptions to
  2166. * the rule will be handled in sof_pcm_dai_link_fixup()
  2167. * For playback, the sequence is the following: start FE,
  2168. * start BE, stop BE, stop FE; for Capture the sequence is
  2169. * inverted start BE, start FE, stop FE, stop BE
  2170. */
  2171. link->trigger[SNDRV_PCM_STREAM_PLAYBACK] = SND_SOC_DPCM_TRIGGER_PRE;
  2172. link->trigger[SNDRV_PCM_STREAM_CAPTURE] = SND_SOC_DPCM_TRIGGER_POST;
  2173. return 0;
  2174. }
  2175. /* token list for each topology object */
  2176. static enum sof_tokens host_token_list[] = {
  2177. SOF_CORE_TOKENS,
  2178. SOF_COMP_EXT_TOKENS,
  2179. SOF_PCM_TOKENS,
  2180. SOF_COMP_TOKENS,
  2181. };
  2182. static enum sof_tokens comp_generic_token_list[] = {
  2183. SOF_CORE_TOKENS,
  2184. SOF_COMP_EXT_TOKENS,
  2185. SOF_COMP_TOKENS,
  2186. };
  2187. static enum sof_tokens buffer_token_list[] = {
  2188. SOF_BUFFER_TOKENS,
  2189. };
  2190. static enum sof_tokens pipeline_token_list[] = {
  2191. SOF_CORE_TOKENS,
  2192. SOF_COMP_EXT_TOKENS,
  2193. SOF_PIPELINE_TOKENS,
  2194. SOF_SCHED_TOKENS,
  2195. };
  2196. static enum sof_tokens asrc_token_list[] = {
  2197. SOF_CORE_TOKENS,
  2198. SOF_COMP_EXT_TOKENS,
  2199. SOF_ASRC_TOKENS,
  2200. SOF_COMP_TOKENS,
  2201. };
  2202. static enum sof_tokens src_token_list[] = {
  2203. SOF_CORE_TOKENS,
  2204. SOF_COMP_EXT_TOKENS,
  2205. SOF_SRC_TOKENS,
  2206. SOF_COMP_TOKENS
  2207. };
  2208. static enum sof_tokens pga_token_list[] = {
  2209. SOF_CORE_TOKENS,
  2210. SOF_COMP_EXT_TOKENS,
  2211. SOF_VOLUME_TOKENS,
  2212. SOF_COMP_TOKENS,
  2213. };
  2214. static enum sof_tokens dai_token_list[] = {
  2215. SOF_CORE_TOKENS,
  2216. SOF_COMP_EXT_TOKENS,
  2217. SOF_DAI_TOKENS,
  2218. SOF_COMP_TOKENS,
  2219. };
  2220. static enum sof_tokens process_token_list[] = {
  2221. SOF_CORE_TOKENS,
  2222. SOF_COMP_EXT_TOKENS,
  2223. SOF_PROCESS_TOKENS,
  2224. SOF_COMP_TOKENS,
  2225. };
  2226. static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = {
  2227. [snd_soc_dapm_aif_in] = {sof_ipc3_widget_setup_comp_host, sof_ipc3_widget_free_comp,
  2228. host_token_list, ARRAY_SIZE(host_token_list), NULL},
  2229. [snd_soc_dapm_aif_out] = {sof_ipc3_widget_setup_comp_host, sof_ipc3_widget_free_comp,
  2230. host_token_list, ARRAY_SIZE(host_token_list), NULL},
  2231. [snd_soc_dapm_dai_in] = {sof_ipc3_widget_setup_comp_dai, sof_ipc3_widget_free_comp_dai,
  2232. dai_token_list, ARRAY_SIZE(dai_token_list), NULL},
  2233. [snd_soc_dapm_dai_out] = {sof_ipc3_widget_setup_comp_dai, sof_ipc3_widget_free_comp_dai,
  2234. dai_token_list, ARRAY_SIZE(dai_token_list), NULL},
  2235. [snd_soc_dapm_buffer] = {sof_ipc3_widget_setup_comp_buffer, sof_ipc3_widget_free_comp,
  2236. buffer_token_list, ARRAY_SIZE(buffer_token_list), NULL},
  2237. [snd_soc_dapm_mixer] = {sof_ipc3_widget_setup_comp_mixer, sof_ipc3_widget_free_comp,
  2238. comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list),
  2239. NULL},
  2240. [snd_soc_dapm_src] = {sof_ipc3_widget_setup_comp_src, sof_ipc3_widget_free_comp,
  2241. src_token_list, ARRAY_SIZE(src_token_list), NULL},
  2242. [snd_soc_dapm_asrc] = {sof_ipc3_widget_setup_comp_asrc, sof_ipc3_widget_free_comp,
  2243. asrc_token_list, ARRAY_SIZE(asrc_token_list), NULL},
  2244. [snd_soc_dapm_siggen] = {sof_ipc3_widget_setup_comp_tone, sof_ipc3_widget_free_comp,
  2245. comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list),
  2246. NULL},
  2247. [snd_soc_dapm_scheduler] = {sof_ipc3_widget_setup_comp_pipeline, sof_ipc3_widget_free_comp,
  2248. pipeline_token_list, ARRAY_SIZE(pipeline_token_list), NULL},
  2249. [snd_soc_dapm_pga] = {sof_ipc3_widget_setup_comp_pga, sof_ipc3_widget_free_comp,
  2250. pga_token_list, ARRAY_SIZE(pga_token_list), NULL},
  2251. [snd_soc_dapm_mux] = {sof_ipc3_widget_setup_comp_mux, sof_ipc3_widget_free_comp,
  2252. comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), NULL},
  2253. [snd_soc_dapm_demux] = {sof_ipc3_widget_setup_comp_mux, sof_ipc3_widget_free_comp,
  2254. comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list),
  2255. NULL},
  2256. [snd_soc_dapm_effect] = {sof_widget_update_ipc_comp_process, sof_ipc3_widget_free_comp,
  2257. process_token_list, ARRAY_SIZE(process_token_list),
  2258. sof_ipc3_widget_bind_event},
  2259. };
  2260. const struct sof_ipc_tplg_ops ipc3_tplg_ops = {
  2261. .widget = tplg_ipc3_widget_ops,
  2262. .control = &tplg_ipc3_control_ops,
  2263. .route_setup = sof_ipc3_route_setup,
  2264. .control_setup = sof_ipc3_control_setup,
  2265. .control_free = sof_ipc3_control_free,
  2266. .pipeline_complete = sof_ipc3_complete_pipeline,
  2267. .token_list = ipc3_token_list,
  2268. .widget_free = sof_ipc3_widget_free,
  2269. .widget_setup = sof_ipc3_widget_setup,
  2270. .dai_config = sof_ipc3_dai_config,
  2271. .dai_get_param = sof_ipc3_dai_get_param,
  2272. .set_up_all_pipelines = sof_ipc3_set_up_all_pipelines,
  2273. .tear_down_all_pipelines = sof_ipc3_tear_down_all_pipelines,
  2274. .parse_manifest = sof_ipc3_parse_manifest,
  2275. .link_setup = sof_ipc3_link_setup,
  2276. };