@@ -572,9 +572,9 @@ static void build_config(struct comp_data *cd, struct module_config *cfg)
572572 cd -> config .out_channels_count = out_fmt -> channels_count ;
573573
574574 /* Build default coefficient array (unity Q10 on diagonal, i.e. pass-through mode) */
575- memset (& cd -> coeffs_config , 0 , sizeof (cd -> coeffs_config ));
575+ memset (cd -> coeffs_config , 0 , sizeof (* cd -> coeffs_config ));
576576 for (i = 0 ; i < MIN (SEL_SOURCE_CHANNELS_MAX , SEL_SINK_CHANNELS_MAX ); i ++ )
577- cd -> coeffs_config . coeffs [i ][i ] = 1 << 10 ;
577+ cd -> coeffs_config -> coeffs [i ][i ] = 1 << 10 ;
578578}
579579
580580static int selector_init (struct processing_module * mod )
@@ -620,6 +620,18 @@ static int selector_init(struct processing_module *mod)
620620 cd -> sel_ipc4_cfg .init_payload_fmt = payload_fmt ;
621621 md -> private = cd ;
622622
623+ /* Allocate space for max number of configurations. */
624+ cd -> multi_coeffs_config_size =
625+ SEL_MAX_NUM_CONFIGS * sizeof (struct ipc4_selector_coeffs_config );
626+ cd -> multi_coeffs_config = mod_zalloc (mod , cd -> multi_coeffs_config_size );
627+ if (!cd -> multi_coeffs_config ) {
628+ mod_free (mod , cd );
629+ return - ENOMEM ;
630+ }
631+
632+ /* Default configuration is set to first configuration */
633+ cd -> coeffs_config = & cd -> multi_coeffs_config [0 ];
634+
623635 if (payload_fmt == IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT ) {
624636 size_t size = sizeof (struct sof_selector_ipc4_pin_config );
625637
@@ -733,6 +745,7 @@ static int selector_free(struct processing_module *mod)
733745
734746 comp_dbg (mod -> dev , "entry" );
735747
748+ mod_free (mod , cd -> multi_coeffs_config );
736749 mod_free (mod , cd );
737750
738751 return 0 ;
@@ -769,12 +782,26 @@ static int selector_set_config(struct processing_module *mod, uint32_t config_id
769782 size_t response_size )
770783{
771784 struct comp_data * cd = module_get_private_data (mod );
785+ int n ;
772786
773787 if (config_id == IPC4_SELECTOR_COEFFS_CONFIG_ID ) {
774- if (data_offset_size != sizeof (cd -> coeffs_config ))
788+ if (data_offset_size > cd -> multi_coeffs_config_size ) {
789+ comp_err (mod -> dev , "The configuration blob is too large" );
790+ return - EINVAL ;
791+ }
792+
793+ /* The size must be N times the coefficient vectors size of one channels
794+ * up/down mix profile.
795+ */
796+ n = data_offset_size / sizeof (struct ipc4_selector_coeffs_config );
797+ if (data_offset_size != n * sizeof (struct ipc4_selector_coeffs_config )) {
798+ comp_err (mod -> dev , "Invalid configuration size." );
775799 return - EINVAL ;
800+ }
776801
777- memcpy_s (& cd -> coeffs_config , sizeof (cd -> coeffs_config ), fragment , data_offset_size );
802+ memcpy_s (cd -> multi_coeffs_config , cd -> multi_coeffs_config_size ,
803+ fragment , data_offset_size );
804+ cd -> num_configs = n ;
778805 return 0 ;
779806 }
780807
@@ -825,7 +852,10 @@ static int selector_prepare(struct processing_module *mod,
825852 struct comp_dev * dev = mod -> dev ;
826853 struct comp_buffer * sinkb , * sourceb ;
827854 size_t sink_size ;
855+ unsigned int source_channels ;
856+ unsigned int sink_channels ;
828857 int ret ;
858+ int i ;
829859
830860 comp_dbg (dev , "entry" );
831861
@@ -855,9 +885,9 @@ static int selector_prepare(struct processing_module *mod,
855885 * proper number of channels [1] for selector to actually
856886 * reduce channel count between source and sink
857887 */
858- comp_info ( dev , "source sink channel = %u %u" ,
859- audio_stream_get_channels (& sourceb -> stream ),
860- audio_stream_get_channels ( & sinkb -> stream ) );
888+ source_channels = audio_stream_get_channels ( & sourceb -> stream );
889+ sink_channels = audio_stream_get_channels (& sinkb -> stream );
890+ comp_dbg ( dev , "source sink channel = %u %u" , source_channels , sink_channels );
861891
862892 sink_size = audio_stream_get_size (& sinkb -> stream );
863893
@@ -891,6 +921,28 @@ static int selector_prepare(struct processing_module *mod,
891921 return - EINVAL ;
892922 }
893923
924+ /* The first config for coefficients always exists, originating from configuration blob
925+ * or default values (1.0) from set_selector_params().
926+ */
927+ cd -> coeffs_config = cd -> multi_coeffs_config ;
928+ if (cd -> num_configs > 1 ) {
929+ /* Use a 8ch pass-through blob if same number of channels */
930+ if (source_channels == sink_channels ) {
931+ source_channels = 8 ;
932+ sink_channels = 8 ;
933+ }
934+
935+ for (i = 0 ; i < cd -> num_configs ; i ++ ) {
936+ if (cd -> multi_coeffs_config [i ].source_channels_count == source_channels &&
937+ cd -> multi_coeffs_config [i ].sink_channels_count == sink_channels ) {
938+ comp_info (dev , "Using coefficients for %d to %d channels." ,
939+ source_channels , sink_channels );
940+ cd -> coeffs_config = & cd -> multi_coeffs_config [i ];
941+ break ;
942+ }
943+ }
944+ }
945+
894946 return 0 ;
895947}
896948
0 commit comments