Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rimage
16 changes: 10 additions & 6 deletions src/audio/copier/copier.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ static struct comp_dev *copier_new(const struct comp_driver *drv,
struct copier_data *cd;
struct comp_dev *dev;
size_t size, config_size;
int i;

comp_cl_dbg(&comp_copier, "copier_new()");

Expand All @@ -459,7 +460,9 @@ static struct comp_dev *copier_new(const struct comp_driver *drv,

size = sizeof(*copier);
mailbox_hostbox_read(&cd->config, size, 0, size);
cd->out_fmt[0] = cd->config.out_fmt;

for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++)
cd->out_fmt[i] = cd->config.out_fmt;
comp_set_drvdata(dev, cd);

list_init(&dev->bsource_list);
Expand Down Expand Up @@ -590,7 +593,7 @@ static pcm_converter_func get_converter_func(struct ipc4_audio_format *in_fmt,
static int copier_prepare(struct comp_dev *dev)
{
struct copier_data *cd = comp_get_drvdata(dev);
int ret;
int ret, i;

comp_dbg(dev, "copier_prepare()");

Expand All @@ -608,7 +611,6 @@ static int copier_prepare(struct comp_dev *dev)
return PPL_STATUS_PATH_STOP;

if (cd->endpoint_num) {
int i;

for (i = 0; i < cd->endpoint_num; i++) {
ret = cd->endpoint[i]->drv->ops.prepare(cd->endpoint[i]);
Expand All @@ -618,13 +620,15 @@ static int copier_prepare(struct comp_dev *dev)
} else {
/* set up format conversion function */
cd->converter[0] = get_converter_func(&cd->config.base.audio_fmt,
&cd->config.out_fmt, ipc4_gtw_none,
ipc4_bidirection);
&cd->config.out_fmt, ipc4_gtw_none,
ipc4_bidirection);
if (!cd->converter[0]) {
comp_err(dev, "can't support for in format %d, out format %d",
cd->config.base.audio_fmt.depth, cd->config.out_fmt.depth);

ret = -EINVAL;
} else {
for (i = 1; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++)
cd->converter[i] = cd->converter[i];
}
}

Expand Down
233 changes: 227 additions & 6 deletions src/audio/mux/mux.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@
static const struct comp_driver comp_mux;

LOG_MODULE_REGISTER(muxdemux, CONFIG_SOF_LOG_LEVEL);

#if CONFIG_IPC_MAJOR_3
/* c607ff4d-9cb6-49dc-b678-7da3c63ea557 */
DECLARE_SOF_RT_UUID("mux", mux_uuid, 0xc607ff4d, 0x9cb6, 0x49dc,
0xb6, 0x78, 0x7d, 0xa3, 0xc6, 0x3e, 0xa5, 0x57);

0xb6, 0x78, 0x7d, 0xa3, 0xc6, 0x3e, 0xa5, 0x57);
#else
Copy link
Collaborator

@marc-hb marc-hb Oct 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not just for IPC5 but also catches Kconfig problems.

Suggested change
#else
#elif CONFIG_IPC_MAJOR_4
...
#else
#error unknown IPC version
#fi

/* 64ce6e35-857a-4878-ace8-e2a2f42e3069 */
DECLARE_SOF_RT_UUID("mux", mux_uuid, 0x64ce6e35, 0x857a, 0x4878,
0xac, 0xe8, 0xe2, 0xa2, 0xf4, 0x2e, 0x30, 0x69);
#endif
DECLARE_TR_CTX(mux_tr, SOF_UUID(mux_uuid), LOG_LEVEL_INFO);

/* c4b26868-1430-470e-a089-15d1c77f851a */
Expand Down Expand Up @@ -158,6 +162,7 @@ static int mux_set_values(struct comp_dev *dev, struct comp_data *cd,
return 0;
}

#if CONFIG_IPC_MAJOR_3
static struct comp_dev *mux_new(const struct comp_driver *drv,
struct comp_ipc_config *config,
void *spec)
Expand Down Expand Up @@ -200,6 +205,200 @@ static struct comp_dev *mux_new(const struct comp_driver *drv,
dev->state = COMP_STATE_READY;
return dev;
}
#else
static int build_config(struct comp_data *cd, struct comp_dev *dev)
{
dev->ipc_config.type = SOF_COMP_MUX;
cd->config.num_streams = MUX_MAX_STREAMS;
int mask = 1;
int i;

/* clear masks */
for (i = 0; i < cd->config.num_streams; i++)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that verified somewhere that no OOB occurs when iterating over cd->config.streams[] using num_streams as the limit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think so, because the copy function takes into account only those streams/channels on which the mask is set, and this function is performed only for ipc4, where we have only two streams. The change has been tested.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still there is no clear relation between the limit of the loop and the allocation size in this function, code looks unsafe.

memset(cd->config.streams[i].mask, 0, sizeof(cd->config.streams[i].mask));

/* Setting masks for streams */
for (i = 0; i < cd->md.base_cfg.audio_fmt.channels_count; i++) {
cd->config.streams[0].mask[i] = mask;
mask <<= 1;
}

for (i = 0; i < cd->md.reference_format.channels_count; i++) {
cd->config.streams[1].mask[i] = mask;
mask <<= 1;
}

/* validation of matrix mixing */
if (mux_mix_check(&cd->config)) {
comp_cl_err(&comp_mux, "build_config(): mux component is not able to mix channels");
return -EINVAL;
}
return 0;
}

static struct comp_dev *mux_new(const struct comp_driver *drv,
struct comp_ipc_config *config,
void *spec)
{
struct mux_data *ipc_process = spec;
struct comp_dev *dev;
struct comp_data *cd;
int ret;

comp_cl_info(&comp_mux, "mux_new()");

dev = comp_alloc(drv, sizeof(*dev));
if (!dev)
return NULL;
dev->ipc_config = *config;

cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd));
if (!cd) {
rfree(dev);
return NULL;
}

comp_set_drvdata(dev, cd);

ret = memcpy_s(&cd->md, sizeof(cd->md), ipc_process, sizeof(*ipc_process));
assert(!ret);
ret = build_config(cd, dev);

if (ret < 0) {
rfree(cd);
rfree(dev);
return NULL;
}

dev->state = COMP_STATE_READY;
return dev;
}

/* In ipc4 case param is figured out by module config so we need to first
* set up param then verify param. BTW for IPC3 path, the param is sent by
* host driver.
*/
static void set_mux_params(struct comp_dev *dev,
struct sof_ipc_stream_params *params)
{
struct comp_data *cd = comp_get_drvdata(dev);
struct comp_buffer *sink, *source;
struct comp_buffer __sparse_cache *sink_c, *source_c;
struct list_item *source_list;
int i, j, valid_bit_depth;
const uint32_t byte_align = 1;
const uint32_t frame_align_req = 1;

params->direction = dev->direction;
params->channels = cd->md.base_cfg.audio_fmt.channels_count;
params->rate = cd->md.base_cfg.audio_fmt.sampling_frequency;
params->sample_container_bytes = cd->md.base_cfg.audio_fmt.depth / 8;
params->sample_valid_bytes = cd->md.base_cfg.audio_fmt.valid_bit_depth / 8;
params->buffer_fmt = cd->md.base_cfg.audio_fmt.interleaving_style;
params->buffer.size = cd->md.base_cfg.ibs;
params->no_stream_position = 1;

/* There are two input pins and one output pin in the mux.
* For the first input we assign parameters from base_cfg,
* for the second from reference_format
* and for sink output_format.
*/

/* update sink format */
if (!list_is_empty(&dev->bsink_list)) {
sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list);
sink_c = buffer_acquire(sink);
audio_stream_init_alignment_constants(byte_align, frame_align_req,
&sink_c->stream);

if (!sink_c->hw_params_configured) {
struct ipc4_audio_format out_fmt;

out_fmt = cd->md.output_format;
sink_c->stream.channels = out_fmt.channels_count;
sink_c->stream.rate = out_fmt.sampling_frequency;
audio_stream_fmt_conversion(out_fmt.depth,
out_fmt.valid_bit_depth,
&sink_c->stream.frame_fmt,
&sink_c->stream.valid_sample_fmt,
out_fmt.s_type);

sink_c->buffer_fmt = out_fmt.interleaving_style;
params->frame_fmt = sink_c->stream.frame_fmt;

for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++)
sink_c->chmap[i] = (out_fmt.ch_map >> i * 4) & 0xf;

sink_c->hw_params_configured = true;
}
buffer_release(sink_c);
}

/* update each source format */
if (!list_is_empty(&dev->bsource_list)) {
list_for_item(source_list, &dev->bsource_list)
{
source = container_of(source_list, struct comp_buffer, sink_list);
source_c = buffer_acquire(source);
audio_stream_init_alignment_constants(byte_align, frame_align_req,
&source_c->stream);
j = source_c->id;
cd->config.streams[j].pipeline_id = source_c->pipeline_id;
valid_bit_depth = cd->md.base_cfg.audio_fmt.valid_bit_depth;
if (j == BASE_CFG_QUEUED_ID) {
source_c->stream.channels =
cd->md.base_cfg.audio_fmt.channels_count;
source_c->stream.rate =
cd->md.base_cfg.audio_fmt.sampling_frequency;
audio_stream_fmt_conversion(cd->md.base_cfg.audio_fmt.depth,
valid_bit_depth,
&source_c->stream.frame_fmt,
&source_c->stream.valid_sample_fmt,
cd->md.base_cfg.audio_fmt.s_type);

source_c->buffer_fmt = cd->md.base_cfg.audio_fmt.interleaving_style;

for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++)
source_c->chmap[i] =
(cd->md.base_cfg.audio_fmt.ch_map >> i * 4) & 0xf;
} else {
/* set parameters for reference input channels */
source_c->stream.channels =
cd->md.reference_format.channels_count;
source_c->stream.rate = cd->md.reference_format.sampling_frequency;
audio_stream_fmt_conversion(cd->md.reference_format.depth,
cd->md.reference_format.valid_bit_depth,
&source_c->stream.frame_fmt,
&source_c->stream.valid_sample_fmt,
cd->md.reference_format.s_type);
source_c->buffer_fmt = cd->md.reference_format.interleaving_style;

for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++)
source_c->chmap[i] =
(cd->md.reference_format.ch_map >> i * 4) & 0xf;
}
source_c->hw_params_configured = true;
buffer_release(source_c);
}
}

mux_prepare_look_up_table(dev);
}

static int mux_get_attribute(struct comp_dev *dev, uint32_t type, void *value)
{
struct comp_data *cd = comp_get_drvdata(dev);

switch (type) {
case COMP_ATTR_BASE_CONFIG:
*(struct ipc4_base_module_cfg *)value = cd->md.base_cfg;
break;
default:
return -EINVAL;
}
return 0;
}
#endif

static void mux_free(struct comp_dev *dev)
{
Expand Down Expand Up @@ -247,7 +446,9 @@ static int mux_params(struct comp_dev *dev,
int ret;

comp_info(dev, "mux_params()");

#if CONFIG_IPC_MAJOR_4
set_mux_params(dev, params);
#endif
ret = comp_verify_params(dev, BUFF_PARAMS_CHANNELS, params);
if (ret < 0)
comp_err(dev, "mux_params(): comp_verify_params() failed.");
Expand Down Expand Up @@ -711,13 +912,30 @@ static int mux_trigger(struct comp_dev *dev, int cmd)
*/
src_n_active = mux_source_status_count(dev, COMP_STATE_ACTIVE);
src_n_paused = mux_source_status_count(dev, COMP_STATE_PAUSED);

#if CONFIG_IPC_MAJOR_4
if (dir == SOF_IPC_STREAM_PLAYBACK) {
switch (cmd) {
case COMP_TRIGGER_PRE_START:
if (src_n_active || src_n_paused)
return PPL_STATUS_PATH_STOP;
break;
case COMP_TRIGGER_PRE_RELEASE:
dev->state = COMP_STATE_PRE_ACTIVE;
break;
case COMP_TRIGGER_RELEASE:
dev->state = COMP_STATE_ACTIVE;
break;
default:
break;
}
}
#else
switch (cmd) {
case COMP_TRIGGER_PRE_START:
if (src_n_active || src_n_paused)
return PPL_STATUS_PATH_STOP;
}

#endif
ret = comp_set_state(dev, cmd);
if (ret < 0)
return ret;
Expand Down Expand Up @@ -755,6 +973,9 @@ static const struct comp_driver comp_mux = {
.prepare = mux_prepare,
.reset = mux_reset,
.trigger = mux_trigger,
#if CONFIG_IPC_MAJOR_4
.get_attribute = mux_get_attribute,
#endif
},
};

Expand Down
Loading