@@ -38,9 +38,26 @@ SOF_DEFINE_REG_UUID(dolby_dax_audio_processing);
3838#define DAX_ENUM_PROFILE_CONTROL_ID 0
3939#define DAX_ENUM_DEVICE_CONTROL_ID 1
4040
41+ #define DAX_OWNER_ID_INVALID 0
42+
43+ struct dax_shared_resource {
44+ void * instance ;
45+ struct dax_buffer persist_buffer ;
46+ struct dax_buffer scratch_buffer ;
47+ atomic_t owner_id_counter ;
48+ atomic_t owner ;
49+ atomic_t force_owner ; /* the owner should obtain resource immediately */
50+ atomic_t ref_count ;
51+ atomic_t initialized ;
52+ };
53+
54+ static struct dax_shared_resource shared_resource ;
55+
4156struct dax_adapter_data {
4257 struct sof_dax dax_ctx ;
4358 atomic_t proc_flags ;
59+ int32_t owner_id ;
60+ int32_t is_registered ;
4461};
4562
4663enum dax_flag_opt_mode {
@@ -246,9 +263,19 @@ static void destroy_instance(struct processing_module *mod)
246263 struct dax_adapter_data * adapter_data = module_get_private_data (mod );
247264 struct sof_dax * dax_ctx = & adapter_data -> dax_ctx ;
248265
249- dax_free (dax_ctx ); /* free internal dax instance in dax_ctx */
250- dax_buffer_release (mod , & dax_ctx -> persist_buffer );
251- dax_buffer_release (mod , & dax_ctx -> scratch_buffer );
266+ if (dax_ctx ) {
267+ dax_ctx -> p_dax = shared_resource .instance ;
268+ dax_free (dax_ctx ); /* free internal dax instance in dax_ctx if it is valid */
269+ rfree (shared_resource .persist_buffer .addr );
270+ rfree (shared_resource .scratch_buffer .addr );
271+ memset (& shared_resource .persist_buffer , 0 , sizeof (shared_resource .persist_buffer ));
272+ memset (& shared_resource .scratch_buffer , 0 , sizeof (shared_resource .scratch_buffer ));
273+ memset (& dax_ctx -> persist_buffer , 0 , sizeof (dax_ctx -> persist_buffer ));
274+ memset (& dax_ctx -> scratch_buffer , 0 , sizeof (dax_ctx -> scratch_buffer ));
275+ shared_resource .instance = NULL ;
276+ dax_ctx -> p_dax = NULL ;
277+ comp_info (mod -> dev , "freed instance" );
278+ }
252279}
253280
254281static int establish_instance (struct processing_module * mod )
@@ -261,25 +288,35 @@ static int establish_instance(struct processing_module *mod)
261288 uint32_t scratch_sz ;
262289
263290 persist_sz = dax_query_persist_memory (dax_ctx );
264- if (dax_buffer_alloc (mod , & dax_ctx -> persist_buffer , persist_sz ) != 0 ) {
291+ shared_resource .persist_buffer .addr = rballoc (SOF_MEM_FLAG_LARGE_BUFFER , persist_sz );
292+ if (!shared_resource .persist_buffer .addr ) {
265293 comp_err (dev , "allocate %u bytes failed for persist" , persist_sz );
266294 ret = - ENOMEM ;
267295 goto err ;
268296 }
269297 scratch_sz = dax_query_scratch_memory (dax_ctx );
270- if (dax_buffer_alloc (mod , & dax_ctx -> scratch_buffer , scratch_sz ) != 0 ) {
298+ shared_resource .scratch_buffer .addr = rballoc (SOF_MEM_FLAG_LARGE_BUFFER , scratch_sz );
299+ if (!shared_resource .scratch_buffer .addr ) {
271300 comp_err (dev , "allocate %u bytes failed for scratch" , scratch_sz );
272301 ret = - ENOMEM ;
273302 goto err ;
274303 }
304+
305+ shared_resource .persist_buffer .size = persist_sz ;
306+ shared_resource .scratch_buffer .size = scratch_sz ;
307+ dax_ctx -> persist_buffer = shared_resource .persist_buffer ;
308+ dax_ctx -> scratch_buffer = shared_resource .scratch_buffer ;
275309 ret = dax_init (dax_ctx );
276310 if (ret != 0 ) {
277311 comp_err (dev , "dax instance initialization failed, ret %d" , ret );
278312 goto err ;
279313 }
314+ shared_resource .instance = dax_ctx -> p_dax ;
280315
281- /* set DAX_ENABLE_MASK bit to trigger the fully update of kcontrol values */
282- flag_process (adapter_data , DAX_ENABLE_MASK , DAX_FLAG_SET );
316+ /* reset dax_ctx here because acquire_ownership is only the way to get shared instance */
317+ dax_ctx -> p_dax = NULL ;
318+ memset (& dax_ctx -> persist_buffer , 0 , sizeof (dax_ctx -> persist_buffer ));
319+ memset (& dax_ctx -> scratch_buffer , 0 , sizeof (dax_ctx -> scratch_buffer ));
283320
284321 comp_info (dev , "allocated: persist %u, scratch %u. version: %s" ,
285322 persist_sz , scratch_sz , dax_get_version ());
@@ -290,6 +327,82 @@ static int establish_instance(struct processing_module *mod)
290327 return ret ;
291328}
292329
330+ static bool is_instance_owned (struct processing_module * mod )
331+ {
332+ struct dax_adapter_data * adapter_data = module_get_private_data (mod );
333+
334+ return atomic_read (& shared_resource .owner ) == adapter_data -> owner_id ;
335+ }
336+
337+ static void release_ownership (struct processing_module * mod )
338+ {
339+ struct dax_adapter_data * adapter_data = module_get_private_data (mod );
340+ struct sof_dax * dax_ctx = & adapter_data -> dax_ctx ;
341+
342+ atomic_set (& shared_resource .owner , DAX_OWNER_ID_INVALID );
343+ dax_ctx -> p_dax = NULL ;
344+ memset (& dax_ctx -> persist_buffer , 0 , sizeof (dax_ctx -> persist_buffer ));
345+ memset (& dax_ctx -> scratch_buffer , 0 , sizeof (dax_ctx -> scratch_buffer ));
346+ comp_info (mod -> dev , "unbinded DAX instance from owner %d" , adapter_data -> owner_id );
347+ }
348+
349+ static void set_ownership (struct processing_module * mod , int32_t owner_id )
350+ {
351+ struct dax_adapter_data * adapter_data = module_get_private_data (mod );
352+ struct sof_dax * dax_ctx = & adapter_data -> dax_ctx ;
353+
354+ atomic_set (& shared_resource .owner , owner_id );
355+ dax_ctx -> p_dax = shared_resource .instance ;
356+ dax_ctx -> persist_buffer = shared_resource .persist_buffer ;
357+ dax_ctx -> scratch_buffer = shared_resource .scratch_buffer ;
358+
359+ /* reset instance buffer data */
360+ dax_set_enable (0 , dax_ctx );
361+
362+ /* set DAX_ENABLE_MASK bit to trigger the fully update of kcontrol values */
363+ flag_process (adapter_data , DAX_ENABLE_MASK , DAX_FLAG_SET );
364+
365+ comp_info (mod -> dev , "binded DAX instance to owner %d" , adapter_data -> owner_id );
366+ }
367+
368+ /* can only be called within sof_dax_process */
369+ static int acquire_ownership (struct processing_module * mod )
370+ {
371+ struct dax_adapter_data * adapter_data = module_get_private_data (mod );
372+ struct sof_dax * dax_ctx = & adapter_data -> dax_ctx ;
373+ int32_t force_owner ;
374+
375+ if (atomic_read (& shared_resource .initialized ) == 0 )
376+ return - EINVAL ;
377+
378+ force_owner = atomic_read (& shared_resource .force_owner );
379+ if (force_owner != DAX_OWNER_ID_INVALID && force_owner != adapter_data -> owner_id ) {
380+ /* release current ownership cause force_owner has more priority */
381+ if (is_instance_owned (mod ))
382+ release_ownership (mod );
383+ return 0 ;
384+ }
385+
386+ /* transfer owner safely */
387+ if (atomic_read (& shared_resource .owner ) == DAX_OWNER_ID_INVALID ) {
388+ set_ownership (mod , adapter_data -> owner_id );
389+ if (force_owner == adapter_data -> owner_id )
390+ atomic_set (& shared_resource .force_owner , DAX_OWNER_ID_INVALID );
391+ return 0 ;
392+ }
393+
394+ /* highest priority for speaker */
395+ if (dax_ctx -> out_device == DAX_AUDIO_DEVICE_OUT_SPEAKER ) {
396+ atomic_set (& shared_resource .force_owner , adapter_data -> owner_id );
397+ return 0 ;
398+ }
399+
400+ dax_ctx -> p_dax = NULL ;
401+ memset (& dax_ctx -> persist_buffer , 0 , sizeof (dax_ctx -> persist_buffer ));
402+ memset (& dax_ctx -> scratch_buffer , 0 , sizeof (dax_ctx -> scratch_buffer ));
403+ return - EBUSY ;
404+ }
405+
293406static int set_tuning_file (struct processing_module * mod , void * value , uint32_t size )
294407{
295408 int ret = 0 ;
@@ -313,17 +426,14 @@ static int set_tuning_file(struct processing_module *mod, void *value, uint32_t
313426
314427static int set_enable (struct processing_module * mod , int32_t enable )
315428{
316- int ret = 0 ;
429+ int ret ;
317430 struct dax_adapter_data * adapter_data = module_get_private_data (mod );
318431 struct sof_dax * dax_ctx = & adapter_data -> dax_ctx ;
319432
320- if (enable ) {
321- ret = dax_set_enable (1 , dax_ctx );
322- dax_ctx -> enable = (ret == 0 ? 1 : 0 );
323- } else {
324- dax_ctx -> enable = 0 ;
325- dax_set_enable (0 , dax_ctx );
326- }
433+ if (!is_instance_owned (mod ))
434+ return 0 ;
435+
436+ ret = dax_set_enable (enable , dax_ctx );
327437
328438 comp_info (mod -> dev , "set dax enable %d, ret %d" , enable , ret );
329439 return ret ;
@@ -336,7 +446,7 @@ static int set_volume(struct processing_module *mod, int32_t abs_volume)
336446 struct sof_dax * dax_ctx = & adapter_data -> dax_ctx ;
337447
338448 dax_ctx -> volume = abs_volume ;
339- if (!dax_ctx -> enable )
449+ if (!dax_ctx -> enable || ! is_instance_owned ( mod ) )
340450 return 0 ;
341451
342452 ret = dax_set_volume (abs_volume , dax_ctx );
@@ -351,6 +461,9 @@ static int set_device(struct processing_module *mod, int32_t out_device)
351461 struct sof_dax * dax_ctx = & adapter_data -> dax_ctx ;
352462
353463 dax_ctx -> out_device = out_device ;
464+ if (!dax_ctx -> enable || !is_instance_owned (mod ))
465+ return 0 ;
466+
354467 ret = dax_set_device (out_device , dax_ctx );
355468
356469 comp_info (mod -> dev , "set device %d, ret %d" , out_device , ret );
@@ -364,6 +477,9 @@ static int set_crosstalk_cancellation_enable(struct processing_module *mod, int3
364477 struct sof_dax * dax_ctx = & adapter_data -> dax_ctx ;
365478
366479 dax_ctx -> ctc_enable = enable ;
480+ if (!dax_ctx -> enable || !is_instance_owned (mod ))
481+ return 0 ;
482+
367483 ret = dax_set_ctc_enable (enable , dax_ctx );
368484
369485 comp_info (mod -> dev , "set ctc enable %d, ret %d" , enable , ret );
@@ -382,7 +498,7 @@ static int set_profile(struct processing_module *mod, int32_t profile_id)
382498 void * params ;
383499
384500 dax_ctx -> profile = profile_id ;
385- if (!dax_ctx -> enable )
501+ if (!dax_ctx -> enable || ! is_instance_owned ( mod ) )
386502 return 0 ;
387503
388504 params = dax_find_params (DAX_PARAM_ID_PROFILE , profile_id , & params_sz , dax_ctx );
@@ -403,7 +519,7 @@ static int set_tuning_device(struct processing_module *mod, int32_t tuning_devic
403519 void * params ;
404520
405521 dax_ctx -> tuning_device = tuning_device ;
406- if (!dax_ctx -> enable )
522+ if (!dax_ctx -> enable || ! is_instance_owned ( mod ) )
407523 return 0 ;
408524
409525 params = dax_find_params (DAX_PARAM_ID_TUNING_DEVICE , tuning_device , & params_sz , dax_ctx );
@@ -424,7 +540,7 @@ static int set_content_processing_enable(struct processing_module *mod, int32_t
424540 void * params ;
425541
426542 dax_ctx -> content_processing_enable = enable ;
427- if (!dax_ctx -> enable )
543+ if (!dax_ctx -> enable || ! is_instance_owned ( mod ) )
428544 return 0 ;
429545
430546 params = dax_find_params (DAX_PARAM_ID_CP_ENABLE , enable , & params_sz , dax_ctx );
@@ -542,6 +658,9 @@ static void check_and_update_settings(struct processing_module *mod)
542658 struct dax_adapter_data * adapter_data = module_get_private_data (mod );
543659 struct sof_dax * dax_ctx = & adapter_data -> dax_ctx ;
544660
661+ if (!is_instance_owned (mod ))
662+ return ;
663+
545664 if (flag_process (adapter_data , DAX_ENABLE_MASK , DAX_FLAG_READ_AND_CLEAR )) {
546665 set_enable (mod , dax_ctx -> enable );
547666 if (dax_ctx -> enable ) {
@@ -580,13 +699,16 @@ static int sof_dax_reset(struct processing_module *mod)
580699 struct dax_adapter_data * adapter_data = module_get_private_data (mod );
581700 struct sof_dax * dax_ctx ;
582701
583- /* dax instance will be established on prepare(), and destroyed on reset() */
584702 if (adapter_data ) {
585703 dax_ctx = & adapter_data -> dax_ctx ;
586704 if (flag_process (adapter_data , DAX_PROCESSING_MASK , DAX_FLAG_READ )) {
587705 flag_process (adapter_data , DAX_RESET_MASK , DAX_FLAG_SET );
588706 } else {
589- destroy_instance (mod );
707+ if (adapter_data -> is_registered == 1 ) {
708+ atomic_sub (& shared_resource .ref_count , 1 );
709+ release_ownership (mod );
710+ adapter_data -> is_registered = 0 ;
711+ }
590712 dax_buffer_release (mod , & dax_ctx -> input_buffer );
591713 dax_buffer_release (mod , & dax_ctx -> output_buffer );
592714 }
@@ -606,6 +728,12 @@ static int sof_dax_free(struct processing_module *mod)
606728 flag_process (adapter_data , DAX_FREE_MASK , DAX_FLAG_SET );
607729 } else {
608730 sof_dax_reset (mod );
731+
732+ if (atomic_read (& shared_resource .ref_count ) == 0 ) {
733+ destroy_instance (mod );
734+ atomic_set (& shared_resource .initialized , 0 );
735+ }
736+
609737 dax_buffer_release (mod , & dax_ctx -> tuning_file_buffer );
610738 mod_data_blob_handler_free (mod , dax_ctx -> blob_handler );
611739 dax_ctx -> blob_handler = NULL ;
@@ -661,6 +789,12 @@ static int sof_dax_init(struct processing_module *mod)
661789 return - ENOMEM ;
662790 }
663791
792+ if (atomic_read (& shared_resource .owner_id_counter ) == INT32_MAX )
793+ atomic_set (& shared_resource .owner_id_counter , 0 );
794+ atomic_add (& shared_resource .owner_id_counter , 1 );
795+ adapter_data -> owner_id = atomic_read (& shared_resource .owner_id_counter );
796+ comp_info (dev , "initialized, owner id %d" , adapter_data -> owner_id );
797+
664798 return 0 ;
665799}
666800
@@ -757,10 +891,20 @@ static int sof_dax_prepare(struct processing_module *mod, struct sof_source **so
757891 if (ret != 0 )
758892 return ret ;
759893
760- /* dax instance will be established on prepare(), and destroyed on reset() */
761- ret = establish_instance (mod );
762- if (ret != 0 )
763- return ret ;
894+ if (adapter_data -> is_registered == 0 ) {
895+ adapter_data -> is_registered = 1 ;
896+ atomic_add (& shared_resource .ref_count , 1 );
897+ }
898+
899+ if (atomic_read (& shared_resource .initialized ) == 0 ) {
900+ atomic_set (& shared_resource .initialized , 1 );
901+ ret = establish_instance (mod );
902+ if (ret ) {
903+ /* rollback initialization state */
904+ atomic_set (& shared_resource .initialized , 0 );
905+ return ret ;
906+ }
907+ }
764908
765909 dax_ctx -> sof_period_bytes = dev -> frames *
766910 dax_ctx -> output_media_format .num_channels *
@@ -832,6 +976,7 @@ static int sof_dax_process(struct processing_module *mod, struct sof_source **so
832976 dax_buffer_produce (dax_input_buffer , consumed_bytes );
833977 source_release_data (source , consumed_bytes );
834978
979+ acquire_ownership (mod );
835980 check_and_update_settings (mod );
836981
837982 /* internal input buffer -> internal output buffer */
0 commit comments