@@ -37,6 +37,25 @@ struct sof_ipc4_timestamp_info {
37
37
snd_pcm_sframes_t delay ;
38
38
};
39
39
40
+ /**
41
+ * struct sof_ipc4_pcm_stream_priv - IPC4 specific private data
42
+ * @time_info: pointer to time info struct if it is supported, otherwise NULL
43
+ * @chain_dma_allocated: indicates the ChainDMA allocation state
44
+ */
45
+ struct sof_ipc4_pcm_stream_priv {
46
+ struct sof_ipc4_timestamp_info * time_info ;
47
+
48
+ bool chain_dma_allocated ;
49
+ };
50
+
51
+ static inline struct sof_ipc4_timestamp_info *
52
+ sof_ipc4_sps_to_time_info (struct snd_sof_pcm_stream * sps )
53
+ {
54
+ struct sof_ipc4_pcm_stream_priv * stream_priv = sps -> private ;
55
+
56
+ return stream_priv -> time_info ;
57
+ }
58
+
40
59
static int sof_ipc4_set_multi_pipeline_state (struct snd_sof_dev * sdev , u32 state ,
41
60
struct ipc4_pipeline_set_state_data * trigger_list )
42
61
{
@@ -253,14 +272,17 @@ sof_ipc4_update_pipeline_state(struct snd_sof_dev *sdev, int state, int cmd,
253
272
*/
254
273
255
274
static int sof_ipc4_chain_dma_trigger (struct snd_sof_dev * sdev ,
256
- int direction ,
275
+ struct snd_sof_pcm * spcm , int direction ,
257
276
struct snd_sof_pcm_stream_pipeline_list * pipeline_list ,
258
277
int state , int cmd )
259
278
{
260
279
struct sof_ipc4_fw_data * ipc4_data = sdev -> private ;
280
+ struct sof_ipc4_pcm_stream_priv * stream_priv ;
261
281
bool allocate , enable , set_fifo_size ;
262
282
struct sof_ipc4_msg msg = {{ 0 }};
263
- int i ;
283
+ int ret , i ;
284
+
285
+ stream_priv = spcm -> stream [direction ].private ;
264
286
265
287
switch (state ) {
266
288
case SOF_IPC4_PIPE_RUNNING : /* Allocate and start chained dma */
@@ -281,6 +303,11 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
281
303
set_fifo_size = false;
282
304
break ;
283
305
case SOF_IPC4_PIPE_RESET : /* Disable and free chained DMA. */
306
+
307
+ /* ChainDMA can only be reset if it has been allocated */
308
+ if (!stream_priv -> chain_dma_allocated )
309
+ return 0 ;
310
+
284
311
allocate = false;
285
312
enable = false;
286
313
set_fifo_size = false;
@@ -338,7 +365,12 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
338
365
if (enable )
339
366
msg .primary |= SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK ;
340
367
341
- return sof_ipc_tx_message_no_reply (sdev -> ipc , & msg , 0 );
368
+ ret = sof_ipc_tx_message_no_reply (sdev -> ipc , & msg , 0 );
369
+ /* Update the ChainDMA allocation state */
370
+ if (!ret )
371
+ stream_priv -> chain_dma_allocated = allocate ;
372
+
373
+ return ret ;
342
374
}
343
375
344
376
static int sof_ipc4_trigger_pipelines (struct snd_soc_component * component ,
@@ -378,7 +410,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
378
410
* trigger function that handles the rest for the substream.
379
411
*/
380
412
if (pipeline -> use_chain_dma )
381
- return sof_ipc4_chain_dma_trigger (sdev , substream -> stream ,
413
+ return sof_ipc4_chain_dma_trigger (sdev , spcm , substream -> stream ,
382
414
pipeline_list , state , cmd );
383
415
384
416
/* allocate memory for the pipeline data */
@@ -452,7 +484,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
452
484
* Invalidate the stream_start_offset to make sure that it is
453
485
* going to be updated if the stream resumes
454
486
*/
455
- time_info = spcm -> stream [substream -> stream ]. private ;
487
+ time_info = sof_ipc4_sps_to_time_info ( & spcm -> stream [substream -> stream ]) ;
456
488
if (time_info )
457
489
time_info -> stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION ;
458
490
@@ -706,12 +738,16 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
706
738
static void sof_ipc4_pcm_free (struct snd_sof_dev * sdev , struct snd_sof_pcm * spcm )
707
739
{
708
740
struct snd_sof_pcm_stream_pipeline_list * pipeline_list ;
741
+ struct sof_ipc4_pcm_stream_priv * stream_priv ;
709
742
int stream ;
710
743
711
744
for_each_pcm_streams (stream ) {
712
745
pipeline_list = & spcm -> stream [stream ].pipeline_list ;
713
746
kfree (pipeline_list -> pipelines );
714
747
pipeline_list -> pipelines = NULL ;
748
+
749
+ stream_priv = spcm -> stream [stream ].private ;
750
+ kfree (stream_priv -> time_info );
715
751
kfree (spcm -> stream [stream ].private );
716
752
spcm -> stream [stream ].private = NULL ;
717
753
}
@@ -721,7 +757,8 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
721
757
{
722
758
struct snd_sof_pcm_stream_pipeline_list * pipeline_list ;
723
759
struct sof_ipc4_fw_data * ipc4_data = sdev -> private ;
724
- struct sof_ipc4_timestamp_info * stream_info ;
760
+ struct sof_ipc4_pcm_stream_priv * stream_priv ;
761
+ struct sof_ipc4_timestamp_info * time_info ;
725
762
bool support_info = true;
726
763
u32 abi_version ;
727
764
u32 abi_offset ;
@@ -749,33 +786,41 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
749
786
return - ENOMEM ;
750
787
}
751
788
789
+ stream_priv = kzalloc (sizeof (* stream_priv ), GFP_KERNEL );
790
+ if (!stream_priv ) {
791
+ sof_ipc4_pcm_free (sdev , spcm );
792
+ return - ENOMEM ;
793
+ }
794
+
795
+ spcm -> stream [stream ].private = stream_priv ;
796
+
752
797
if (!support_info )
753
798
continue ;
754
799
755
- stream_info = kzalloc (sizeof (* stream_info ), GFP_KERNEL );
756
- if (!stream_info ) {
800
+ time_info = kzalloc (sizeof (* time_info ), GFP_KERNEL );
801
+ if (!time_info ) {
757
802
sof_ipc4_pcm_free (sdev , spcm );
758
803
return - ENOMEM ;
759
804
}
760
805
761
- spcm -> stream [ stream ]. private = stream_info ;
806
+ stream_priv -> time_info = time_info ;
762
807
}
763
808
764
809
return 0 ;
765
810
}
766
811
767
- static void sof_ipc4_build_time_info (struct snd_sof_dev * sdev , struct snd_sof_pcm_stream * spcm )
812
+ static void sof_ipc4_build_time_info (struct snd_sof_dev * sdev , struct snd_sof_pcm_stream * sps )
768
813
{
769
814
struct sof_ipc4_copier * host_copier = NULL ;
770
815
struct sof_ipc4_copier * dai_copier = NULL ;
771
816
struct sof_ipc4_llp_reading_slot llp_slot ;
772
- struct sof_ipc4_timestamp_info * info ;
817
+ struct sof_ipc4_timestamp_info * time_info ;
773
818
struct snd_soc_dapm_widget * widget ;
774
819
struct snd_sof_dai * dai ;
775
820
int i ;
776
821
777
822
/* find host & dai to locate info in memory window */
778
- for_each_dapm_widgets (spcm -> list , i , widget ) {
823
+ for_each_dapm_widgets (sps -> list , i , widget ) {
779
824
struct snd_sof_widget * swidget = widget -> dobj .private ;
780
825
781
826
if (!swidget )
@@ -795,44 +840,44 @@ static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pc
795
840
return ;
796
841
}
797
842
798
- info = spcm -> private ;
799
- info -> host_copier = host_copier ;
800
- info -> dai_copier = dai_copier ;
801
- info -> llp_offset = offsetof(struct sof_ipc4_fw_registers , llp_gpdma_reading_slots ) +
802
- sdev -> fw_info_box .offset ;
843
+ time_info = sof_ipc4_sps_to_time_info ( sps ) ;
844
+ time_info -> host_copier = host_copier ;
845
+ time_info -> dai_copier = dai_copier ;
846
+ time_info -> llp_offset = offsetof(struct sof_ipc4_fw_registers ,
847
+ llp_gpdma_reading_slots ) + sdev -> fw_info_box .offset ;
803
848
804
849
/* find llp slot used by current dai */
805
850
for (i = 0 ; i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS ; i ++ ) {
806
- sof_mailbox_read (sdev , info -> llp_offset , & llp_slot , sizeof (llp_slot ));
851
+ sof_mailbox_read (sdev , time_info -> llp_offset , & llp_slot , sizeof (llp_slot ));
807
852
if (llp_slot .node_id == dai_copier -> data .gtw_cfg .node_id )
808
853
break ;
809
854
810
- info -> llp_offset += sizeof (llp_slot );
855
+ time_info -> llp_offset += sizeof (llp_slot );
811
856
}
812
857
813
858
if (i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS )
814
859
return ;
815
860
816
861
/* if no llp gpdma slot is used, check aggregated sdw slot */
817
- info -> llp_offset = offsetof(struct sof_ipc4_fw_registers , llp_sndw_reading_slots ) +
818
- sdev -> fw_info_box .offset ;
862
+ time_info -> llp_offset = offsetof(struct sof_ipc4_fw_registers ,
863
+ llp_sndw_reading_slots ) + sdev -> fw_info_box .offset ;
819
864
for (i = 0 ; i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS ; i ++ ) {
820
- sof_mailbox_read (sdev , info -> llp_offset , & llp_slot , sizeof (llp_slot ));
865
+ sof_mailbox_read (sdev , time_info -> llp_offset , & llp_slot , sizeof (llp_slot ));
821
866
if (llp_slot .node_id == dai_copier -> data .gtw_cfg .node_id )
822
867
break ;
823
868
824
- info -> llp_offset += sizeof (llp_slot );
869
+ time_info -> llp_offset += sizeof (llp_slot );
825
870
}
826
871
827
872
if (i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS )
828
873
return ;
829
874
830
875
/* check EVAD slot */
831
- info -> llp_offset = offsetof(struct sof_ipc4_fw_registers , llp_evad_reading_slot ) +
832
- sdev -> fw_info_box .offset ;
833
- sof_mailbox_read (sdev , info -> llp_offset , & llp_slot , sizeof (llp_slot ));
876
+ time_info -> llp_offset = offsetof(struct sof_ipc4_fw_registers ,
877
+ llp_evad_reading_slot ) + sdev -> fw_info_box .offset ;
878
+ sof_mailbox_read (sdev , time_info -> llp_offset , & llp_slot , sizeof (llp_slot ));
834
879
if (llp_slot .node_id != dai_copier -> data .gtw_cfg .node_id )
835
- info -> llp_offset = 0 ;
880
+ time_info -> llp_offset = 0 ;
836
881
}
837
882
838
883
static int sof_ipc4_pcm_hw_params (struct snd_soc_component * component ,
@@ -849,7 +894,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
849
894
if (!spcm )
850
895
return - EINVAL ;
851
896
852
- time_info = spcm -> stream [substream -> stream ]. private ;
897
+ time_info = sof_ipc4_sps_to_time_info ( & spcm -> stream [substream -> stream ]) ;
853
898
/* delay calculation is not supported by current fw_reg ABI */
854
899
if (!time_info )
855
900
return 0 ;
@@ -864,7 +909,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
864
909
865
910
static int sof_ipc4_get_stream_start_offset (struct snd_sof_dev * sdev ,
866
911
struct snd_pcm_substream * substream ,
867
- struct snd_sof_pcm_stream * stream ,
912
+ struct snd_sof_pcm_stream * sps ,
868
913
struct sof_ipc4_timestamp_info * time_info )
869
914
{
870
915
struct sof_ipc4_copier * host_copier = time_info -> host_copier ;
@@ -918,7 +963,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
918
963
struct sof_ipc4_timestamp_info * time_info ;
919
964
struct sof_ipc4_llp_reading_slot llp ;
920
965
snd_pcm_uframes_t head_cnt , tail_cnt ;
921
- struct snd_sof_pcm_stream * stream ;
966
+ struct snd_sof_pcm_stream * sps ;
922
967
u64 dai_cnt , host_cnt , host_ptr ;
923
968
struct snd_sof_pcm * spcm ;
924
969
int ret ;
@@ -927,8 +972,8 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
927
972
if (!spcm )
928
973
return - EOPNOTSUPP ;
929
974
930
- stream = & spcm -> stream [substream -> stream ];
931
- time_info = stream -> private ;
975
+ sps = & spcm -> stream [substream -> stream ];
976
+ time_info = sof_ipc4_sps_to_time_info ( sps ) ;
932
977
if (!time_info )
933
978
return - EOPNOTSUPP ;
934
979
@@ -938,7 +983,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
938
983
* the statistics is complete. And it will not change after the first initiailization.
939
984
*/
940
985
if (time_info -> stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION ) {
941
- ret = sof_ipc4_get_stream_start_offset (sdev , substream , stream , time_info );
986
+ ret = sof_ipc4_get_stream_start_offset (sdev , substream , sps , time_info );
942
987
if (ret < 0 )
943
988
return - EOPNOTSUPP ;
944
989
}
@@ -1030,15 +1075,13 @@ static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
1030
1075
{
1031
1076
struct snd_soc_pcm_runtime * rtd = snd_soc_substream_to_rtd (substream );
1032
1077
struct sof_ipc4_timestamp_info * time_info ;
1033
- struct snd_sof_pcm_stream * stream ;
1034
1078
struct snd_sof_pcm * spcm ;
1035
1079
1036
1080
spcm = snd_sof_find_spcm_dai (component , rtd );
1037
1081
if (!spcm )
1038
1082
return 0 ;
1039
1083
1040
- stream = & spcm -> stream [substream -> stream ];
1041
- time_info = stream -> private ;
1084
+ time_info = sof_ipc4_sps_to_time_info (& spcm -> stream [substream -> stream ]);
1042
1085
/*
1043
1086
* Report the stored delay value calculated in the pointer callback.
1044
1087
* In the unlikely event that the calculation was skipped/aborted, the
0 commit comments