1313#include "sof-audio.h"
1414#include "ops.h"
1515
16+ struct sof_widget_data {
17+ int ctrl_type ;
18+ int ipc_cmd ;
19+ struct sof_abi_hdr * pdata ;
20+ struct snd_sof_control * control ;
21+ };
22+
23+ struct sof_process_types {
24+ const char * name ;
25+ enum sof_ipc_process_type type ;
26+ enum sof_comp_type comp_type ;
27+ };
28+
29+ static const struct sof_process_types sof_process [] = {
30+ {"EQFIR" , SOF_PROCESS_EQFIR , SOF_COMP_EQ_FIR },
31+ {"EQIIR" , SOF_PROCESS_EQIIR , SOF_COMP_EQ_IIR },
32+ {"KEYWORD_DETECT" , SOF_PROCESS_KEYWORD_DETECT , SOF_COMP_KEYWORD_DETECT },
33+ {"KPB" , SOF_PROCESS_KPB , SOF_COMP_KPB },
34+ {"CHAN_SELECTOR" , SOF_PROCESS_CHAN_SELECTOR , SOF_COMP_SELECTOR },
35+ {"MUX" , SOF_PROCESS_MUX , SOF_COMP_MUX },
36+ {"DEMUX" , SOF_PROCESS_DEMUX , SOF_COMP_DEMUX },
37+ {"DCBLOCK" , SOF_PROCESS_DCBLOCK , SOF_COMP_DCBLOCK },
38+ {"SMART_AMP" , SOF_PROCESS_SMART_AMP , SOF_COMP_SMART_AMP },
39+ };
40+
41+ static enum sof_ipc_process_type find_process (const char * name )
42+ {
43+ int i ;
44+
45+ for (i = 0 ; i < ARRAY_SIZE (sof_process ); i ++ ) {
46+ if (strcmp (name , sof_process [i ].name ) == 0 )
47+ return sof_process [i ].type ;
48+ }
49+
50+ return SOF_PROCESS_NONE ;
51+ }
52+
53+ static int get_token_process_type (void * elem , void * object , u32 offset )
54+ {
55+ u32 * val = (u32 * )((u8 * )object + offset );
56+
57+ * val = find_process ((const char * )elem );
58+ return 0 ;
59+ }
60+
1661/* Buffers */
1762static const struct sof_topology_token buffer_tokens [] = {
1863 {SOF_TKN_BUF_SIZE , SND_SOC_TPLG_TUPLE_TYPE_WORD , get_token_u32 ,
@@ -71,6 +116,12 @@ static const struct sof_topology_token asrc_tokens[] = {
71116 offsetof(struct sof_ipc_comp_asrc , operation_mode )},
72117};
73118
119+ /* EFFECT */
120+ static const struct sof_topology_token process_tokens [] = {
121+ {SOF_TKN_PROCESS_TYPE , SND_SOC_TPLG_TUPLE_TYPE_STRING , get_token_process_type ,
122+ offsetof(struct sof_ipc_comp_process , type )},
123+ };
124+
74125/* PCM */
75126static const struct sof_topology_token pcm_tokens [] = {
76127 {SOF_TKN_PCM_DMAC_CONFIG , SND_SOC_TPLG_TUPLE_TYPE_WORD , get_token_u32 ,
@@ -111,6 +162,7 @@ static const struct sof_token_info ipc3_token_list[SOF_TOKEN_COUNT] = {
111162 [SOF_VOLUME_TOKENS ] = {"Volume tokens" , volume_tokens , ARRAY_SIZE (volume_tokens )},
112163 [SOF_SRC_TOKENS ] = {"SRC tokens" , src_tokens , ARRAY_SIZE (src_tokens )},
113164 [SOF_ASRC_TOKENS ] = {"ASRC tokens" , asrc_tokens , ARRAY_SIZE (asrc_tokens )},
165+ [SOF_PROCESS_TOKENS ] = {"Process tokens" , process_tokens , ARRAY_SIZE (process_tokens )},
114166};
115167
116168/**
@@ -558,6 +610,193 @@ static int sof_ipc3_widget_setup_comp_pga(struct snd_sof_widget *swidget)
558610 return ret ;
559611}
560612
613+ static int sof_get_control_data (struct snd_soc_component * scomp ,
614+ struct snd_soc_dapm_widget * widget ,
615+ struct sof_widget_data * wdata , size_t * size )
616+ {
617+ const struct snd_kcontrol_new * kc ;
618+ struct soc_mixer_control * sm ;
619+ struct soc_bytes_ext * sbe ;
620+ struct soc_enum * se ;
621+ int i ;
622+
623+ * size = 0 ;
624+
625+ for (i = 0 ; i < widget -> num_kcontrols ; i ++ ) {
626+ kc = & widget -> kcontrol_news [i ];
627+
628+ switch (widget -> dobj .widget .kcontrol_type [i ]) {
629+ case SND_SOC_TPLG_TYPE_MIXER :
630+ sm = (struct soc_mixer_control * )kc -> private_value ;
631+ wdata [i ].control = sm -> dobj .private ;
632+ break ;
633+ case SND_SOC_TPLG_TYPE_BYTES :
634+ sbe = (struct soc_bytes_ext * )kc -> private_value ;
635+ wdata [i ].control = sbe -> dobj .private ;
636+ break ;
637+ case SND_SOC_TPLG_TYPE_ENUM :
638+ se = (struct soc_enum * )kc -> private_value ;
639+ wdata [i ].control = se -> dobj .private ;
640+ break ;
641+ default :
642+ dev_err (scomp -> dev , "Unknown kcontrol type %u in widget %s\n" ,
643+ widget -> dobj .widget .kcontrol_type [i ], widget -> name );
644+ return - EINVAL ;
645+ }
646+
647+ if (!wdata [i ].control ) {
648+ dev_err (scomp -> dev , "No scontrol for widget %s\n" , widget -> name );
649+ return - EINVAL ;
650+ }
651+
652+ wdata [i ].pdata = wdata [i ].control -> control_data -> data ;
653+ if (!wdata [i ].pdata )
654+ return - EINVAL ;
655+
656+ /* make sure data is valid - data can be updated at runtime */
657+ if (widget -> dobj .widget .kcontrol_type [i ] == SND_SOC_TPLG_TYPE_BYTES &&
658+ wdata [i ].pdata -> magic != SOF_ABI_MAGIC )
659+ return - EINVAL ;
660+
661+ * size += wdata [i ].pdata -> size ;
662+
663+ /* get data type */
664+ switch (wdata [i ].control -> control_data -> cmd ) {
665+ case SOF_CTRL_CMD_VOLUME :
666+ case SOF_CTRL_CMD_ENUM :
667+ case SOF_CTRL_CMD_SWITCH :
668+ wdata [i ].ipc_cmd = SOF_IPC_COMP_SET_VALUE ;
669+ wdata [i ].ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET ;
670+ break ;
671+ case SOF_CTRL_CMD_BINARY :
672+ wdata [i ].ipc_cmd = SOF_IPC_COMP_SET_DATA ;
673+ wdata [i ].ctrl_type = SOF_CTRL_TYPE_DATA_SET ;
674+ break ;
675+ default :
676+ break ;
677+ }
678+ }
679+
680+ return 0 ;
681+ }
682+
683+ static int sof_process_load (struct snd_soc_component * scomp ,
684+ struct snd_sof_widget * swidget , int type )
685+ {
686+ struct snd_soc_dapm_widget * widget = swidget -> widget ;
687+ struct sof_ipc_comp_process * process ;
688+ struct sof_widget_data * wdata = NULL ;
689+ size_t ipc_data_size = 0 ;
690+ size_t ipc_size ;
691+ int offset = 0 ;
692+ int ret ;
693+ int i ;
694+
695+ /* allocate struct for widget control data sizes and types */
696+ if (widget -> num_kcontrols ) {
697+ wdata = kcalloc (widget -> num_kcontrols , sizeof (* wdata ), GFP_KERNEL );
698+ if (!wdata )
699+ return - ENOMEM ;
700+
701+ /* get possible component controls and get size of all pdata */
702+ ret = sof_get_control_data (scomp , widget , wdata , & ipc_data_size );
703+ if (ret < 0 )
704+ goto out ;
705+ }
706+
707+ ipc_size = sizeof (struct sof_ipc_comp_process ) + ipc_data_size ;
708+
709+ /* we are exceeding max ipc size, config needs to be sent separately */
710+ if (ipc_size > SOF_IPC_MSG_MAX_SIZE ) {
711+ ipc_size -= ipc_data_size ;
712+ ipc_data_size = 0 ;
713+ }
714+
715+ process = sof_comp_alloc (swidget , & ipc_size , swidget -> pipeline_id );
716+ if (!process ) {
717+ ret = - ENOMEM ;
718+ goto out ;
719+ }
720+
721+ swidget -> private = process ;
722+
723+ /* configure iir IPC message */
724+ process -> comp .type = type ;
725+ process -> config .hdr .size = sizeof (process -> config );
726+
727+ /* parse one set of comp tokens */
728+ ret = sof_update_ipc_object (scomp , & process -> config , SOF_COMP_TOKENS ,
729+ swidget -> tuples , swidget -> num_tuples ,
730+ sizeof (process -> config ), 1 );
731+ if (ret < 0 )
732+ goto err ;
733+
734+ dev_dbg (scomp -> dev , "loaded process %s\n" , swidget -> widget -> name );
735+ sof_dbg_comp_config (scomp , & process -> config );
736+
737+ /*
738+ * found private data in control, so copy it.
739+ * get possible component controls - get size of all pdata,
740+ * then memcpy with headers
741+ */
742+ if (ipc_data_size ) {
743+ for (i = 0 ; i < widget -> num_kcontrols ; i ++ ) {
744+ memcpy (& process -> data [offset ],
745+ wdata [i ].pdata -> data ,
746+ wdata [i ].pdata -> size );
747+ offset += wdata [i ].pdata -> size ;
748+ }
749+ }
750+
751+ process -> size = ipc_data_size ;
752+
753+ kfree (wdata );
754+
755+ return 0 ;
756+ err :
757+ kfree (swidget -> private );
758+ swidget -> private = NULL ;
759+ out :
760+ kfree (wdata );
761+ return ret ;
762+ }
763+
764+ static enum sof_comp_type find_process_comp_type (enum sof_ipc_process_type type )
765+ {
766+ int i ;
767+
768+ for (i = 0 ; i < ARRAY_SIZE (sof_process ); i ++ ) {
769+ if (sof_process [i ].type == type )
770+ return sof_process [i ].comp_type ;
771+ }
772+
773+ return SOF_COMP_NONE ;
774+ }
775+
776+ /*
777+ * Processing Component Topology - can be "effect", "codec", or general
778+ * "processing".
779+ */
780+
781+ static int sof_widget_update_ipc_comp_process (struct snd_sof_widget * swidget )
782+ {
783+ struct snd_soc_component * scomp = swidget -> scomp ;
784+ struct sof_ipc_comp_process config ;
785+ int ret ;
786+
787+ memset (& config , 0 , sizeof (config ));
788+ config .comp .core = swidget -> core ;
789+
790+ /* parse one set of process tokens */
791+ ret = sof_update_ipc_object (scomp , & config , SOF_PROCESS_TOKENS , swidget -> tuples ,
792+ swidget -> num_tuples , sizeof (config ), 1 );
793+ if (ret < 0 )
794+ return ret ;
795+
796+ /* now load process specific data and send IPC */
797+ return sof_process_load (scomp , swidget , find_process_comp_type (config .type ));
798+ }
799+
561800/* token list for each topology object */
562801static enum sof_tokens host_token_list [] = {
563802 SOF_CORE_TOKENS ,
@@ -604,6 +843,13 @@ static enum sof_tokens pga_token_list[] = {
604843 SOF_COMP_TOKENS ,
605844};
606845
846+ static enum sof_tokens process_token_list [] = {
847+ SOF_CORE_TOKENS ,
848+ SOF_COMP_EXT_TOKENS ,
849+ SOF_PROCESS_TOKENS ,
850+ SOF_COMP_TOKENS ,
851+ };
852+
607853static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops [SND_SOC_DAPM_TYPE_COUNT ] = {
608854 [snd_soc_dapm_aif_in ] = {sof_ipc3_widget_setup_comp_host , sof_ipc3_widget_free_comp ,
609855 host_token_list , ARRAY_SIZE (host_token_list ), NULL },
@@ -630,6 +876,8 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TY
630876 [snd_soc_dapm_demux ] = {sof_ipc3_widget_setup_comp_mux , sof_ipc3_widget_free_comp ,
631877 comp_generic_token_list , ARRAY_SIZE (comp_generic_token_list ),
632878 NULL },
879+ [snd_soc_dapm_effect ] = {sof_widget_update_ipc_comp_process , sof_ipc3_widget_free_comp ,
880+ process_token_list , ARRAY_SIZE (process_token_list ), NULL },
633881};
634882
635883static const struct sof_ipc_tplg_ops ipc3_tplg_ops = {
0 commit comments