From 7e5d40aaf77059c5b759ac05e10b1775da292486 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Tue, 28 Nov 2023 10:51:07 -0800 Subject: [PATCH] component: pipeline: Refactor direction testing in pipeline propagation Clean up some cut/paste code that had spread around, replacing it with a simpler "comp_same_dir()" predicate. No behavioral changes, just refactoring. Also remove the big comment that was repeated in triplicate. It explained this as error handling (i.e. it must be broken topology from which we want to recover), but in fact cross-pipeline widget connections in modern SOF do run in opposite directions (c.f. echo cancellation, which need to look at the output stream to process microphone input, or smart amp devices that do the reverse). So just explain it as policy: we don't propagate across opposite-direction pipelines, period. Usages that need them need to manage their pipeline lifecycles manually. Signed-off-by: Andy Ross --- src/audio/pipeline/pipeline-graph.c | 26 +++----------- src/audio/pipeline/pipeline-params.c | 49 ++++----------------------- src/include/sof/audio/component_ext.h | 12 +++++++ 3 files changed, 24 insertions(+), 63 deletions(-) diff --git a/src/audio/pipeline/pipeline-graph.c b/src/audio/pipeline/pipeline-graph.c index 02191a6f5..616d8349a 100644 --- a/src/audio/pipeline/pipeline-graph.c +++ b/src/audio/pipeline/pipeline-graph.c @@ -323,7 +323,6 @@ static int pipeline_comp_reset(struct comp_dev *current, { struct pipeline *p = ctx->comp_data; struct pipeline *p_current = current->pipeline; - int end_type; int is_single_ppl = comp_is_single_pipeline(current, p->source_comp); int is_same_sched = pipeline_is_same_sched_comp(p_current, p); int err; @@ -339,26 +338,11 @@ static int pipeline_comp_reset(struct comp_dev *current, if (!is_single_ppl && IPC4_MOD_ID(current->ipc_config.id)) return 0; - if (!is_single_ppl && !is_same_sched) { - /* If pipeline connected to the starting one is in improper - * direction (CAPTURE towards DAI, PLAYBACK towards HOST), - * stop propagation. Direction param of the pipeline can not be - * trusted at this point, as it might not be configured yet, - * hence checking for endpoint component type. - */ - end_type = comp_get_endpoint_type(p_current->sink_comp); - switch (dir) { - case SOF_IPC_STREAM_PLAYBACK: - if (end_type == COMP_ENDPOINT_HOST || - end_type == COMP_ENDPOINT_NODE) - return 0; - break; - case SOF_IPC_STREAM_CAPTURE: - if (end_type == COMP_ENDPOINT_DAI || - end_type == COMP_ENDPOINT_NODE) - return 0; - } - } + /* Propagate reset across pipelines only in the same direction + * and with the same scheduling behavior + */ + if (!is_single_ppl && !is_same_sched && !comp_same_dir(current, dir)) + return 0; /* two cases for a component still being active here: * 1. trigger function failed to handle stop event diff --git a/src/audio/pipeline/pipeline-params.c b/src/audio/pipeline/pipeline-params.c index ecf27bfa3..7be4abf74 100644 --- a/src/audio/pipeline/pipeline-params.c +++ b/src/audio/pipeline/pipeline-params.c @@ -80,33 +80,15 @@ static int pipeline_comp_params(struct comp_dev *current, .skip_incomplete = true, }; int stream_direction = ppl_data->params->params.direction; - int end_type; int err; pipe_dbg(current->pipeline, "pipeline_comp_params(), current->comp.id = %u, dir = %u", dev_comp_id(current), dir); - if (!comp_is_single_pipeline(current, ppl_data->start)) { - /* If pipeline connected to the starting one is in improper - * direction (CAPTURE towards DAI, PLAYBACK towards HOST), - * stop propagation of parameters not to override their config. - * Direction param of the pipeline can not be trusted at this - * point, as it might not be configured yet, hence checking - * for endpoint component type. - */ - end_type = comp_get_endpoint_type(current->pipeline->sink_comp); - if (stream_direction == SOF_IPC_STREAM_PLAYBACK) { - if (end_type == COMP_ENDPOINT_HOST || - end_type == COMP_ENDPOINT_NODE) - return 0; - } - - if (stream_direction == SOF_IPC_STREAM_CAPTURE) { - if (end_type == COMP_ENDPOINT_DAI || - end_type == COMP_ENDPOINT_NODE) - return 0; - } - } + /* Don't propagate to pipelines in the opposite direction */ + if (!comp_is_single_pipeline(current, ppl_data->start) && + !comp_same_dir(current, stream_direction)) + return 0; /* don't do any params if current is running */ if (current->state == COMP_STATE_ACTIVE) @@ -279,8 +261,6 @@ static int pipeline_comp_prepare(struct comp_dev *current, struct pipeline_walk_context *ctx, int dir) { struct pipeline_data *ppl_data = ctx->comp_data; - int stream_direction = dir; - int end_type; int err; pipe_dbg(current->pipeline, "pipeline_comp_prepare(), current->comp.id = %u, dir = %u", @@ -291,24 +271,9 @@ static int pipeline_comp_prepare(struct comp_dev *current, if (IPC4_MOD_ID(current->ipc_config.id)) return 0; - /* If pipeline connected to the starting one is in improper - * direction (CAPTURE towards DAI, PLAYBACK towards HOST), - * stop propagation. Direction param of the pipeline can not be - * trusted at this point, as it might not be configured yet, - * hence checking for endpoint component type. - */ - end_type = comp_get_endpoint_type(current->pipeline->sink_comp); - if (stream_direction == SOF_IPC_STREAM_PLAYBACK) { - if (end_type == COMP_ENDPOINT_HOST || - end_type == COMP_ENDPOINT_NODE) - return 0; - } - - if (stream_direction == SOF_IPC_STREAM_CAPTURE) { - if (end_type == COMP_ENDPOINT_DAI || - end_type == COMP_ENDPOINT_NODE) - return 0; - } + /* Propagate prepare only to pipelines in the same direction */ + if (!comp_same_dir(current, dir)) + return 0; } if (current->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) { diff --git a/src/include/sof/audio/component_ext.h b/src/include/sof/audio/component_ext.h index a3d04843b..d66854f4b 100644 --- a/src/include/sof/audio/component_ext.h +++ b/src/include/sof/audio/component_ext.h @@ -500,6 +500,18 @@ static inline uint64_t comp_get_total_data_processed(struct comp_dev *dev, uint3 return ret; } +/** Returns true if the component's pipeline matches the specified direction */ +static inline bool comp_same_dir(struct comp_dev *comp, enum sof_ipc_stream_direction dir) +{ + int end_type = comp_get_endpoint_type(comp->pipeline->sink_comp); + + if (dir == SOF_IPC_STREAM_PLAYBACK && end_type != COMP_ENDPOINT_DAI) + return false; + if (dir == SOF_IPC_STREAM_CAPTURE && end_type != COMP_ENDPOINT_HOST) + return false; + return true; +} + /** @}*/ #endif /* __SOF_AUDIO_COMPONENT_INT_H__ */