1717#include <ipc/topology.h>
1818#include <ipc4/module.h>
1919#include <rtos/kernel.h>
20+ #include <sof/audio/module_adapter/module/generic.h>
21+ #include <sof/lib/cpu-clk-manager.h>
2022
2123#include <errno.h>
2224#include <stdbool.h>
2325#include <stddef.h>
2426#include <stdint.h>
2527
2628LOG_MODULE_DECLARE (pipe , CONFIG_SOF_LOG_LEVEL );
29+ // LOG_MODULE_REGISTER(cpsBudget, CONFIG_SOF_LOG_LEVEL);
2730
2831/*
2932 * Check whether pipeline is incapable of acquiring data for capture.
@@ -267,24 +270,109 @@ static void pipeline_trigger_xrun(struct pipeline *p, struct comp_dev **host)
267270 } while (true);
268271}
269272
273+ static int add_pipeline_cps_consumption (struct comp_dev * current ,
274+ struct comp_buffer * calling_buf ,
275+ struct pipeline_walk_context * ctx , int dir )
276+ {
277+ struct pipeline_data * ppl_data = ctx -> comp_data ;
278+ struct ipc4_base_module_cfg * cd = NULL ;
279+
280+ pipe_dbg (ppl_data -> p , "pipeline_comp_complete(), current->comp.id = %u, dir = %u" ,
281+ dev_comp_id (current ), dir );
282+
283+ if (!comp_is_single_pipeline (current , ppl_data -> start )) {
284+ pipe_dbg (ppl_data -> p , "pipeline_comp_complete(), current is from another pipeline" );
285+ return 0 ;
286+ }
287+
288+ /* complete component init */
289+ current -> pipeline = ppl_data -> p ;
290+
291+ /* modules created throug module adapter have different priv_data */
292+ if (current -> drv -> type != SOF_COMP_MODULE_ADAPTER ) {
293+ cd = comp_get_drvdata (current );
294+ } else {
295+ struct processing_module * mod = comp_get_drvdata (current );
296+ struct module_data * md = & mod -> priv ;
297+ cd = & md -> cfg .base_cfg ;
298+ }
299+
300+ int kcps = cd -> cpc * 1000 / ppl_data -> p -> period ;
301+ core_kcps_adjust (0 , kcps );
302+ tr_err (pipe , "Registering KCPS consumption: %d, core: %d" , kcps , ppl_data -> p -> core );
303+ int summary_cps = core_kcps_get (0 );
304+ tr_err (pipe , "Sum of KCPS consumption: %d, core: %d" , summary_cps , ppl_data -> p -> core );
305+ return pipeline_for_each_comp (current , ctx , dir );
306+ }
307+
308+ static int remove_pipeline_cps_consumption (struct comp_dev * current ,
309+ struct comp_buffer * calling_buf ,
310+ struct pipeline_walk_context * ctx , int dir )
311+ {
312+ struct pipeline_data * ppl_data = ctx -> comp_data ;
313+ struct ipc4_base_module_cfg * cd = NULL ;
314+
315+ pipe_dbg (ppl_data -> p , "pipeline_comp_complete(), current->comp.id = %u, dir = %u" ,
316+ dev_comp_id (current ), dir );
317+
318+ if (!comp_is_single_pipeline (current , ppl_data -> start )) {
319+ pipe_dbg (ppl_data -> p , "pipeline_comp_complete(), current is from another pipeline" );
320+ return 0 ;
321+ }
322+
323+ /* complete component init */
324+ current -> pipeline = ppl_data -> p ;
325+
326+ /* modules created throug module adapter have different priv_data */
327+ if (current -> drv -> type != SOF_COMP_MODULE_ADAPTER ) {
328+ cd = comp_get_drvdata (current );
329+ } else {
330+ struct processing_module * mod = comp_get_drvdata (current );
331+ struct module_data * md = & mod -> priv ;
332+ cd = & md -> cfg .base_cfg ;
333+ }
334+
335+ int kcps = cd -> cpc * 1000 /ppl_data -> p -> period ;
336+ core_kcps_adjust (0 , - kcps ); /* 1000 chunks per second, so cpc value matches kcps? */
337+ tr_err (pipe , "Unregistering KCPS consumption: %d, core: %d" , kcps , ppl_data -> p -> core );
338+ int summary_cps = core_kcps_get (0 );
339+ tr_err (pipe , "Sum of KCPS consumption: %d, core: %d" , summary_cps , ppl_data -> p -> core );
340+ return pipeline_for_each_comp (current , ctx , dir );
341+ }
342+
343+
344+
345+
270346/* trigger pipeline in IPC context */
271347int pipeline_trigger (struct pipeline * p , struct comp_dev * host , int cmd )
272348{
273349 int ret ;
274-
350+ bool clocks_handled = false;
351+ struct pipeline_data data ;
352+ struct pipeline_walk_context walk_ctx = {
353+ .comp_func = remove_pipeline_cps_consumption ,
354+ .comp_data = & data ,
355+ };
275356 pipe_info (p , "pipe trigger cmd %d" , cmd );
276357
277358 p -> trigger .aborted = false;
278359
279360 switch (cmd ) {
280361 case COMP_TRIGGER_PAUSE :
362+ /* dirty - dont add kcps on fallthrough */
363+ clocks_handled = true;
364+ /* setup walking ctx for adding consumption */
365+ data .start = p -> source_comp ;
366+ data .p = p ;
367+ walk_ctx .comp_func = remove_pipeline_cps_consumption ;
368+
369+ ret = walk_ctx .comp_func (p -> source_comp , NULL , & walk_ctx , PPL_DIR_DOWNSTREAM );
281370 case COMP_TRIGGER_STOP :
282371 if (p -> status == COMP_STATE_PAUSED || p -> xrun_bytes ) {
283372 /* The task isn't running, trigger inline */
284373 ret = pipeline_trigger_run (p , host , cmd );
285374 return ret < 0 ? ret : 0 ;
286375 }
287-
288376 COMPILER_FALLTHROUGH ;
289377 case COMP_TRIGGER_XRUN :
290378 if (cmd == COMP_TRIGGER_XRUN )
@@ -294,6 +382,13 @@ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd)
294382 case COMP_TRIGGER_PRE_RELEASE :
295383 case COMP_TRIGGER_PRE_START :
296384 /* Add all connected pipelines to the list and trigger them all */
385+ /* setup walking ctx for removing consumption */
386+ data .start = p -> source_comp ;
387+ data .p = p ;
388+ walk_ctx .comp_func = add_pipeline_cps_consumption ;
389+
390+ if (!clocks_handled )
391+ ret = walk_ctx .comp_func (p -> source_comp , NULL , & walk_ctx , PPL_DIR_DOWNSTREAM );
297392 ret = pipeline_trigger_list (p , host , cmd );
298393 if (ret < 0 )
299394 return ret ;
0 commit comments