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 <andyross@google.com>
This commit is contained in:
Andy Ross 2023-11-28 10:51:07 -08:00 committed by Kai Vehmanen
parent 68c63571fd
commit 7e5d40aaf7
3 changed files with 24 additions and 63 deletions

View File

@ -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.
/* Propagate reset across pipelines only in the same direction
* and with the same scheduling behavior
*/
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)
if (!is_single_ppl && !is_same_sched && !comp_same_dir(current, dir))
return 0;
break;
case SOF_IPC_STREAM_CAPTURE:
if (end_type == COMP_ENDPOINT_DAI ||
end_type == COMP_ENDPOINT_NODE)
return 0;
}
}
/* two cases for a component still being active here:
* 1. trigger function failed to handle stop event

View File

@ -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)
/* 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;
}
if (stream_direction == SOF_IPC_STREAM_CAPTURE) {
if (end_type == COMP_ENDPOINT_DAI ||
end_type == COMP_ENDPOINT_NODE)
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,26 +271,11 @@ 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)
/* Propagate prepare only to pipelines in the same direction */
if (!comp_same_dir(current, dir))
return 0;
}
if (stream_direction == SOF_IPC_STREAM_CAPTURE) {
if (end_type == COMP_ENDPOINT_DAI ||
end_type == COMP_ENDPOINT_NODE)
return 0;
}
}
if (current->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) {
/* init a task for LL module, DP task has been created in during init_instance */
err = pipeline_comp_ll_task_init(current->pipeline);

View File

@ -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__ */