@@ -119,7 +119,7 @@ static int plug_ctl_get_attribute(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
119119 struct snd_soc_tplg_bytes_control * bytes_ctl ;
120120 int err = 0 ;
121121
122- switch (hdr -> type ) {
122+ switch (hdr -> ops . info ) {
123123 case SND_SOC_TPLG_CTL_VOLSW :
124124 case SND_SOC_TPLG_CTL_VOLSW_SX :
125125 case SND_SOC_TPLG_CTL_VOLSW_XR_SX :
@@ -138,7 +138,7 @@ static int plug_ctl_get_attribute(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
138138 case SND_SOC_TPLG_CTL_ENUM_VALUE :
139139 enum_ctl = (struct snd_soc_tplg_enum_control * )hdr ;
140140 * type = SND_CTL_ELEM_TYPE_ENUMERATED ;
141- * count = enum_ctl -> num_channels ;
141+ * count = enum_ctl -> items ;
142142 break ;
143143 case SND_SOC_TPLG_CTL_RANGE :
144144 case SND_SOC_TPLG_CTL_STROBE :
@@ -373,7 +373,7 @@ static int plug_ctl_get_enumerated_info(snd_ctl_ext_t *ext, snd_ctl_ext_key_t ke
373373 (struct snd_soc_tplg_enum_control * )hdr ;
374374 int err = 0 ;
375375
376- switch (hdr -> type ) {
376+ switch (hdr -> ops . info ) {
377377 case SND_SOC_TPLG_CTL_ENUM :
378378 case SND_SOC_TPLG_CTL_ENUM_VALUE :
379379 * items = enum_ctl -> items ;
@@ -395,10 +395,8 @@ static int plug_ctl_get_enumerated_name(snd_ctl_ext_t *ext, snd_ctl_ext_key_t ke
395395 struct snd_soc_tplg_enum_control * enum_ctl =
396396 (struct snd_soc_tplg_enum_control * )hdr ;
397397
398- printf ("%s %d\n" , __func__ , __LINE__ );
399-
400- if (item >= enum_ctl -> count ) {
401- SNDERR ("invalid item %d for enum using key %d" , item , key );
398+ if (item >= enum_ctl -> items ) {
399+ SNDERR ("invalid item %d for enum using key %d\n" , item , key );
402400 return - EINVAL ;
403401 }
404402
@@ -409,12 +407,143 @@ static int plug_ctl_get_enumerated_name(snd_ctl_ext_t *ext, snd_ctl_ext_key_t ke
409407static int plug_ctl_read_enumerated (snd_ctl_ext_t * ext , snd_ctl_ext_key_t key ,
410408 unsigned int * items )
411409{
410+ snd_sof_ctl_t * ctl = ext -> private_data ;
411+ struct snd_soc_tplg_enum_control * enum_ctl = CTL_GET_TPLG_ENUM (ctl , key );
412+ struct ipc4_module_large_config config = {{ 0 }};
413+ struct ipc4_module_large_config_reply * reply ;
414+ struct sof_ipc4_control_msg_payload * data ;
415+ char * reply_data ;
416+ void * msg ;
417+ int size , reply_data_size ;
418+ int i , err ;
419+
420+ /* configure the IPC message */
421+ plug_ctl_ipc_message (& config , SOF_IPC4_ENUM_CONTROL_PARAM_ID , 0 ,
422+ ctl -> glb -> ctl [key ].module_id , ctl -> glb -> ctl [key ].instance_id ,
423+ SOF_IPC4_MOD_LARGE_CONFIG_GET );
424+
425+ config .extension .r .final_block = 1 ;
426+ config .extension .r .init_block = 1 ;
427+
428+ size = sizeof (config );
429+ msg = calloc (size , 1 );
430+ if (!msg )
431+ return - ENOMEM ;
432+
433+ /* reply contains both the requested data and the reply status */
434+ reply_data_size = sizeof (* reply ) + sizeof (* data ) +
435+ enum_ctl -> num_channels * sizeof (data -> chanv [0 ]);
436+ reply_data = calloc (reply_data_size , 1 );
437+ if (!reply_data_size ) {
438+ free (msg );
439+ return - ENOMEM ;
440+ }
441+
442+ /* send the IPC message */
443+ memcpy (msg , & config , sizeof (config ));
444+ err = plug_mq_cmd_tx_rx (& ctl -> ipc_tx , & ctl -> ipc_rx ,
445+ msg , size , reply_data , reply_data_size );
446+ free (msg );
447+ if (err < 0 ) {
448+ SNDERR ("failed to get enum items for control %s\n" , enum_ctl -> hdr .name );
449+ goto out ;
450+ }
451+
452+ reply = (struct ipc4_module_large_config_reply * )reply_data ;
453+ if (reply -> primary .r .status != IPC4_SUCCESS ) {
454+ SNDERR ("enum control %s get failed with status %d\n" ,
455+ enum_ctl -> hdr .name , reply -> primary .r .status );
456+ err = - EINVAL ;
457+ goto out ;
458+ }
459+
460+ /* check data sanity */
461+ data = (struct sof_ipc4_control_msg_payload * )(reply_data + sizeof (* reply ));
462+ if (data -> num_elems != enum_ctl -> num_channels ) {
463+ SNDERR ("Channel count %d doesn't match the expected value %d for enum ctl %s\n" ,
464+ data -> num_elems , enum_ctl -> num_channels , enum_ctl -> hdr .name );
465+ err = - EINVAL ;
466+ goto out ;
467+ }
468+
469+ /* set the enum items based on the received data */
470+ for (i = 0 ; i < enum_ctl -> num_channels ; i ++ )
471+ items [i ] = data -> chanv [i ].value ;
472+ out :
473+ free (reply_data );
412474 return 0 ;
413475}
414476
415477static int plug_ctl_write_enumerated (snd_ctl_ext_t * ext , snd_ctl_ext_key_t key ,
416478 unsigned int * items )
417479{
480+ snd_sof_ctl_t * ctl = ext -> private_data ;
481+ struct snd_soc_tplg_enum_control * enum_ctl = CTL_GET_TPLG_ENUM (ctl , key );
482+ struct ipc4_module_large_config config = {{ 0 }};
483+ struct sof_ipc4_control_msg_payload * data ;
484+ struct ipc4_message_reply reply ;
485+ void * msg ;
486+ int data_size , msg_size ;
487+ int err , i ;
488+
489+ /* size of control data */
490+ data_size = enum_ctl -> num_channels * sizeof (struct sof_ipc4_ctrl_value_chan ) +
491+ sizeof (* data );
492+
493+ /* allocate memory for control data */
494+ data = calloc (data_size , 1 );
495+ if (!data )
496+ return - ENOMEM ;
497+
498+ /* set param ID and number of channels */
499+ data -> id = ctl -> glb -> ctl [key ].index ;
500+ data -> num_elems = enum_ctl -> num_channels ;
501+
502+ /* set the enum values */
503+ for (i = 0 ; i < data -> num_elems ; i ++ ) {
504+ data -> chanv [i ].channel = i ;
505+ data -> chanv [i ].value = items [i ];
506+ }
507+
508+ /* configure the IPC message */
509+ plug_ctl_ipc_message (& config , SOF_IPC4_ENUM_CONTROL_PARAM_ID , data_size ,
510+ ctl -> glb -> ctl [key ].module_id , ctl -> glb -> ctl [key ].instance_id ,
511+ SOF_IPC4_MOD_LARGE_CONFIG_SET );
512+
513+ /*
514+ * enum controls can have a maximum of 16 texts/values. So the entire data can be sent
515+ * in a single IPC message
516+ */
517+ config .extension .r .final_block = 1 ;
518+ config .extension .r .init_block = 1 ;
519+
520+ /* allocate memory for IPC message */
521+ msg_size = sizeof (config ) + data_size ;
522+ msg = calloc (msg_size , 1 );
523+ if (!msg ) {
524+ free (data );
525+ return - ENOMEM ;
526+ }
527+
528+ /* set the IPC message data */
529+ memcpy (msg , & config , sizeof (config ));
530+ memcpy (msg + sizeof (config ), data , data_size );
531+ free (data );
532+
533+ /* send the message and check status */
534+ err = plug_mq_cmd_tx_rx (& ctl -> ipc_tx , & ctl -> ipc_rx , msg , msg_size , & reply , sizeof (reply ));
535+ free (msg );
536+ if (err < 0 ) {
537+ SNDERR ("failed to set enum control %s\n" , enum_ctl -> hdr .name );
538+ return err ;
539+ }
540+
541+ if (reply .primary .r .status != IPC4_SUCCESS ) {
542+ SNDERR ("enum control %s set failed with status %d\n" ,
543+ enum_ctl -> hdr .name , reply .primary .r .status );
544+ return - EINVAL ;
545+ }
546+
418547 return 0 ;
419548}
420549
0 commit comments