@@ -284,6 +284,105 @@ static void sof_ipc4_refresh_generic_control(struct snd_sof_control *scontrol)
284284 kfree (data );
285285}
286286
287+ static int
288+ sof_ipc4_set_bytes_control_data (struct snd_sof_control * scontrol , bool lock )
289+ {
290+ struct sof_ipc4_control_data * cdata = scontrol -> ipc_control_data ;
291+ struct snd_soc_component * scomp = scontrol -> scomp ;
292+ struct sof_ipc4_control_msg_payload * msg_data ;
293+ struct sof_abi_hdr * data = cdata -> data ;
294+ struct sof_ipc4_msg * msg = & cdata -> msg ;
295+ size_t data_size ;
296+ int ret ;
297+
298+ data_size = struct_size (msg_data , data , data -> size );
299+ msg_data = kzalloc (data_size , GFP_KERNEL );
300+ if (!msg_data )
301+ return - ENOMEM ;
302+
303+ msg_data -> id = cdata -> index ;
304+ msg_data -> num_elems = data -> size ;
305+ memcpy (msg_data -> data , data -> data , data -> size );
306+
307+ msg -> extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID (data -> type );
308+
309+ msg -> data_ptr = msg_data ;
310+ msg -> data_size = data_size ;
311+
312+ ret = sof_ipc4_set_get_kcontrol_data (scontrol , true, lock );
313+ msg -> data_ptr = NULL ;
314+ msg -> data_size = 0 ;
315+ if (ret < 0 )
316+ dev_err (scomp -> dev , "%s: Failed to set control update for %s\n" ,
317+ __func__ , scontrol -> name );
318+
319+ kfree (msg_data );
320+
321+ return ret ;
322+ }
323+
324+ static int
325+ sof_ipc4_refresh_bytes_control (struct snd_sof_control * scontrol , bool lock )
326+ {
327+ struct sof_ipc4_control_data * cdata = scontrol -> ipc_control_data ;
328+ struct snd_soc_component * scomp = scontrol -> scomp ;
329+ struct sof_ipc4_control_msg_payload * msg_data ;
330+ struct sof_abi_hdr * data = cdata -> data ;
331+ struct sof_ipc4_msg * msg = & cdata -> msg ;
332+ size_t data_size ;
333+ int ret = 0 ;
334+
335+ if (!scontrol -> comp_data_dirty )
336+ return 0 ;
337+
338+ if (!pm_runtime_active (scomp -> dev ))
339+ return 0 ;
340+
341+ data_size = scontrol -> max_size - sizeof (* data );
342+ if (data_size < sizeof (* msg_data ))
343+ data_size = sizeof (* msg_data );
344+
345+ msg_data = kzalloc (data_size , GFP_KERNEL );
346+ if (!msg_data )
347+ return - ENOMEM ;
348+
349+ msg -> extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID (data -> type );
350+
351+ msg_data -> id = cdata -> index ;
352+ msg_data -> num_elems = 0 ; /* ignored for bytes */
353+
354+ msg -> data_ptr = msg_data ;
355+ msg -> data_size = data_size ;
356+
357+ scontrol -> comp_data_dirty = false;
358+ ret = sof_ipc4_set_get_kcontrol_data (scontrol , false, lock );
359+ if (!ret ) {
360+ if (msg -> data_size > scontrol -> max_size - sizeof (* data )) {
361+ dev_err (scomp -> dev ,
362+ "%s: no space for data in %s (%zu, %zu)\n" ,
363+ __func__ , scontrol -> name , msg -> data_size ,
364+ scontrol -> max_size - sizeof (* data ));
365+ goto out ;
366+ }
367+
368+ data -> size = msg -> data_size ;
369+ scontrol -> size = sizeof (* cdata ) + sizeof (* data ) + data -> size ;
370+ memcpy (data -> data , msg -> data_ptr , data -> size );
371+ } else {
372+ dev_err (scomp -> dev , "Failed to read control data for %s\n" ,
373+ scontrol -> name );
374+ scontrol -> comp_data_dirty = true;
375+ }
376+
377+ out :
378+ msg -> data_ptr = NULL ;
379+ msg -> data_size = 0 ;
380+
381+ kfree (msg_data );
382+
383+ return ret ;
384+ }
385+
287386static bool sof_ipc4_switch_put (struct snd_sof_control * scontrol ,
288387 struct snd_ctl_elem_value * ucontrol )
289388{
@@ -423,6 +522,13 @@ static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev,
423522 }
424523 }
425524
525+ if (data -> type == SOF_IPC4_BYTES_CONTROL_PARAM_ID ) {
526+ if (set )
527+ return sof_ipc4_set_bytes_control_data (scontrol , lock );
528+ else
529+ return sof_ipc4_refresh_bytes_control (scontrol , lock );
530+ }
531+
426532 msg -> extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID (data -> type );
427533
428534 msg -> data_ptr = data -> data ;
@@ -507,6 +613,8 @@ static int sof_ipc4_bytes_get(struct snd_sof_control *scontrol,
507613 return - EINVAL ;
508614 }
509615
616+ sof_ipc4_refresh_bytes_control (scontrol , true);
617+
510618 size = data -> size + sizeof (* data );
511619
512620 /* copy back to kcontrol */
@@ -661,6 +769,8 @@ static int sof_ipc4_bytes_ext_get(struct snd_sof_control *scontrol,
661769 const unsigned int __user * binary_data ,
662770 unsigned int size )
663771{
772+ sof_ipc4_refresh_bytes_control (scontrol , true);
773+
664774 return _sof_ipc4_bytes_ext_get (scontrol , binary_data , size , false);
665775}
666776
@@ -714,6 +824,9 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message)
714824 case SOF_IPC4_ENUM_CONTROL_PARAM_ID :
715825 type = SND_SOC_TPLG_TYPE_ENUM ;
716826 break ;
827+ case SOF_IPC4_BYTES_CONTROL_PARAM_ID :
828+ type = SND_SOC_TPLG_TYPE_BYTES ;
829+ break ;
717830 default :
718831 dev_err (sdev -> dev ,
719832 "%s: Invalid control type for module %u.%u: %u\n" ,
@@ -764,23 +877,38 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message)
764877 * The message includes the updated value/data, update the
765878 * control's local cache using the received notification
766879 */
767- for ( i = 0 ; i < msg_data -> num_elems ; i ++ ) {
768- u32 channel = msg_data -> chanv [ i ]. channel ;
880+ if ( type == SND_SOC_TPLG_TYPE_BYTES ) {
881+ struct sof_abi_hdr * data = cdata -> data ;
769882
770- if (channel >= scontrol -> num_channels ) {
883+ if (msg_data -> num_elems > scontrol -> max_size - sizeof ( * data ) ) {
771884 dev_warn (sdev -> dev ,
772- "Invalid channel index for %s: %u\n" ,
773- scontrol -> name , i );
774-
775- /*
776- * Mark the scontrol as dirty to force a refresh
777- * on next read
778- */
779- scontrol -> comp_data_dirty = true;
780- break ;
885+ "%s: no space for data in %s (%u, %zu)\n" ,
886+ __func__ , scontrol -> name , msg_data -> num_elems ,
887+ scontrol -> max_size - sizeof (* data ));
888+ } else {
889+ memcpy (data -> data , msg_data -> data , msg_data -> num_elems );
890+ data -> size = msg_data -> num_elems ;
891+ scontrol -> size = sizeof (* cdata ) + sizeof (* data ) + data -> size ;
892+ }
893+ } else {
894+ for (i = 0 ; i < msg_data -> num_elems ; i ++ ) {
895+ u32 channel = msg_data -> chanv [i ].channel ;
896+
897+ if (channel >= scontrol -> num_channels ) {
898+ dev_warn (sdev -> dev ,
899+ "Invalid channel index for %s: %u\n" ,
900+ scontrol -> name , i );
901+
902+ /*
903+ * Mark the scontrol as dirty to force a refresh
904+ * on next read
905+ */
906+ scontrol -> comp_data_dirty = true;
907+ break ;
908+ }
909+
910+ cdata -> chanv [channel ].value = msg_data -> chanv [i ].value ;
781911 }
782-
783- cdata -> chanv [channel ].value = msg_data -> chanv [i ].value ;
784912 }
785913 } else {
786914 /*
0 commit comments