-
Notifications
You must be signed in to change notification settings - Fork 363
selector: re-validate configuration on control set #10912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -231,16 +231,86 @@ static int selector_ctrl_set_data(struct comp_dev *dev, | |
| struct sof_ipc_ctrl_data *cdata) | ||
| { | ||
| struct comp_data *cd = comp_get_drvdata(dev); | ||
| struct comp_buffer *src; | ||
| struct sof_sel_config *cfg; | ||
| uint32_t src_channels; | ||
| int ret = 0; | ||
|
|
||
| switch (cdata->cmd) { | ||
| case SOF_CTRL_CMD_BINARY: | ||
| comp_dbg(dev, "SOF_CTRL_CMD_BINARY"); | ||
|
|
||
| if (cdata->data->size < sizeof(struct sof_sel_config)) { | ||
| comp_err(dev, "invalid config blob size %u", cdata->data->size); | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| cfg = (struct sof_sel_config *) | ||
| ASSUME_ALIGNED(&cdata->data->data, 4); | ||
|
|
||
| /* | ||
| * The config validated at .params() time can be replaced here at | ||
| * runtime, so re-validate the new channel counts and selected | ||
| * channel before accepting them; otherwise an out-of-range value | ||
| * later indexes past the source channels in the copy routine. | ||
| */ | ||
| switch (cfg->in_channels_count) { | ||
| case 0: | ||
| case SEL_SOURCE_1CH: | ||
| case SEL_SOURCE_2CH: | ||
| case SEL_SOURCE_4CH: | ||
| break; | ||
| default: | ||
| comp_err(dev, "invalid in_channels_count %u", | ||
| cfg->in_channels_count); | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| switch (cfg->out_channels_count) { | ||
| case 0: | ||
| case SEL_SINK_1CH: | ||
| case SEL_SINK_2CH: | ||
| case SEL_SINK_4CH: | ||
| break; | ||
| default: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also 5.1 and 7.1 sinks
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The accepted set here intentionally mirrors the existing
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lets add this as a followup PR.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The module already supports 5.1 and 7.1. I've tested it several times with test topologies. The higher channels counts are not yet in production topologies. |
||
| comp_err(dev, "invalid out_channels_count %u", | ||
| cfg->out_channels_count); | ||
| return -EINVAL; | ||
| } | ||
|
Comment on lines
+257
to
+279
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 0 isn't a "no change" sentinel here — it's a valid configuration meaning "derive the channel count from the stream at runtime". See
Comment on lines
+257
to
+279
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The two paths validate different things, which is why I didn't share code: |
||
|
|
||
| /* sel_channel indexes the source channels, so it must be below | ||
| * the source channel count, otherwise the copy routine reads | ||
| * past the end of each source frame. The copy routine strides by | ||
| * the live producer stream channel count, so when the source is | ||
| * already connected that live count is the authority for both the | ||
| * selected channel and any fixed input count; before connection | ||
| * fall back to the configured input count. Always cap by the | ||
| * maximum supported source width. | ||
| */ | ||
| src = comp_dev_get_first_data_producer(dev); | ||
| if (src) | ||
| src_channels = audio_stream_get_channels(&src->stream); | ||
| else | ||
| src_channels = cfg->in_channels_count; | ||
|
|
||
| /* A fixed (non-zero) input count must not exceed the live source | ||
| * width, otherwise sel_channel could be accepted below the | ||
| * requested count yet still index past the actual stream. | ||
| */ | ||
| if (src && cfg->in_channels_count && | ||
| cfg->in_channels_count > src_channels) { | ||
| comp_err(dev, "in_channels_count %u exceeds source channels %u", | ||
| cfg->in_channels_count, src_channels); | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| if (cfg->sel_channel >= SEL_SOURCE_4CH || | ||
| (src_channels && cfg->sel_channel >= src_channels)) { | ||
| comp_err(dev, "invalid sel_channel %u (source channels %u)", | ||
| cfg->sel_channel, src_channels); | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| /* Just set the configuration */ | ||
| cd->config.in_channels_count = cfg->in_channels_count; | ||
| cd->config.out_channels_count = cfg->out_channels_count; | ||
|
Comment on lines
314
to
316
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 0 isn't a "no change" sentinel here — it's a valid configuration meaning "derive the channel count from the stream at runtime". See |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have also 5.1 and 7.1 down-mix supported. See https://github.com/thesofproject/sof/tree/main/tools/topology/topology2/include/components/micsel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and also 1CH input is supported
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets add to follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add the SEL_SOURCE_1CH case so we don't break the existing supported mono playback case. The 5.1 and 7.1 can be added later. We don't have those in normal topologies yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Added
#define SEL_SOURCE_1CH 1in selector.h and acase SEL_SOURCE_1CH:in thein_channels_countswitch, so mono playback keeps working. 5.1/7.1 left for a later PR as discussed. Thesel_channelbound still holds for mono: with a 1-channel sourcesel_channelis required to be 0.