diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf index e97d8965fd0b..011fd69adf9f 100644 --- a/app/boards/intel_adsp_ace15_mtpm.conf +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -41,6 +41,7 @@ CONFIG_DMA_DW_LLI_POOL_SIZE=50 CONFIG_INTEL_MODULES=y CONFIG_LIBRARY_MANAGER=y CONFIG_LIBRARY_AUTH_SUPPORT=y +CONFIG_LIBRARY_PIPELINE_FORCE_MIN_LIFETIME=100 CONFIG_INTEL_ADSP_TIMER=y CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y CONFIG_AMS=y @@ -86,10 +87,7 @@ CONFIG_MEMORY_WIN_2_SIZE=12288 CONFIG_LLEXT=y CONFIG_LLEXT_STORAGE_WRITABLE=y - -# temporarily disabled to get MTL working again -# https://github.com/thesofproject/sof/issues/9308 -CONFIG_MODULES=n +CONFIG_MODULES=y # Temporary disabled options CONFIG_TRACE=n diff --git a/app/boards/intel_adsp_cavs25.conf b/app/boards/intel_adsp_cavs25.conf index ddf70ba9aa85..7cd405b492be 100644 --- a/app/boards/intel_adsp_cavs25.conf +++ b/app/boards/intel_adsp_cavs25.conf @@ -5,7 +5,7 @@ CONFIG_LP_MEMORY_BANKS=1 CONFIG_HP_MEMORY_BANKS=30 CONFIG_MM_DRV=y CONFIG_INTEL_MODULES=y -CONFIG_LIBRARY_MANAGER=y +CONFIG_LIBRARY_MANAGER=n CONFIG_RIMAGE_SIGNING_SCHEMA="tgl" CONFIG_DEBUG_COREDUMP=y diff --git a/app/boards/intel_adsp_cavs25_tgph.conf b/app/boards/intel_adsp_cavs25_tgph.conf index 58855d28183a..4379d6b50549 100644 --- a/app/boards/intel_adsp_cavs25_tgph.conf +++ b/app/boards/intel_adsp_cavs25_tgph.conf @@ -4,7 +4,7 @@ CONFIG_LP_MEMORY_BANKS=1 CONFIG_HP_MEMORY_BANKS=30 CONFIG_MM_DRV=y CONFIG_INTEL_MODULES=y -CONFIG_LIBRARY_MANAGER=y +CONFIG_LIBRARY_MANAGER=n CONFIG_RIMAGE_SIGNING_SCHEMA="tgl-h" CONFIG_DEBUG_COREDUMP=y diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 7c8d53726d20..c070152f47ae 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -164,8 +164,6 @@ static int copier_init(struct processing_module *mod) dev->direction_set = true; } else { - cd->gtw_type = ipc4_gtw_none; - /* set max sink count for module copier */ mod->max_sinks = IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; } @@ -246,7 +244,7 @@ static int copier_prepare(struct processing_module *mod, */ cd->converter[0] = get_converter_func(&cd->config.base.audio_fmt, &cd->config.out_fmt, ipc4_gtw_none, - ipc4_bidirection, DUMMY_CHMAP); + 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); @@ -661,7 +659,6 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data, const struct ipc4_copier_config_set_sink_format *sink_fmt = data; struct processing_module *mod = comp_mod(dev); struct copier_data *cd = module_get_private_data(mod); - uint32_t chmap; if (max_data_size < sizeof(*sink_fmt)) { comp_err(dev, "error: max_data_size %d should be bigger than %d", max_data_size, @@ -687,15 +684,9 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data, } cd->out_fmt[sink_fmt->sink_id] = sink_fmt->sink_fmt; - - if (cd->endpoint_num > 0 && dev->ipc_config.type == SOF_COMP_DAI) - chmap = cd->dd[0]->chmap; - else - chmap = DUMMY_CHMAP; - cd->converter[sink_fmt->sink_id] = get_converter_func(&sink_fmt->source_fmt, &sink_fmt->sink_fmt, ipc4_gtw_none, - ipc4_bidirection, chmap); + ipc4_bidirection); return 0; } @@ -735,82 +726,6 @@ static int set_attenuation(struct comp_dev *dev, uint32_t data_offset, const cha return 0; } -static int set_chmap(struct comp_dev *dev, const void *data, size_t data_size) -{ - const struct ipc4_copier_config_channel_map *chmap_cfg = data; - struct processing_module *mod = comp_mod(dev); - struct copier_data *cd = module_get_private_data(mod); - enum ipc4_direction_type dir; - struct ipc4_audio_format in_fmt = cd->config.base.audio_fmt; - struct ipc4_audio_format out_fmt = cd->config.out_fmt; - pcm_converter_func process; - pcm_converter_func converters[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT]; - int i; - uint32_t irq_flags; - - if (data_size < sizeof(*chmap_cfg)) { - comp_err(dev, "Wrong payload size: %d", data_size); - return -EINVAL; - } - - if (cd->endpoint_num == 0 || dev->ipc_config.type != SOF_COMP_DAI) { - comp_err(dev, "Only DAI gateway supports changing chmap"); - return -EINVAL; - } - - comp_info(dev, "New chmap requested: %x", chmap_cfg->channel_map); - - if (!cd->dd[0]->dma_buffer) { - /* DMA buffer not yet created. Remember the chmap, it will be used - * later in .params() handler. - * - * The assignment should be atomic as LL thread can preempt this IPC thread. - */ - cd->dd[0]->chmap = chmap_cfg->channel_map; - return 0; - } - - copier_dai_adjust_params(cd, &in_fmt, &out_fmt); - - dir = (cd->direction == SOF_IPC_STREAM_PLAYBACK) ? - ipc4_playback : ipc4_capture; - - process = get_converter_func(&in_fmt, &out_fmt, cd->gtw_type, dir, chmap_cfg->channel_map); - - if (!process) { - comp_err(dev, "No gtw converter func found!"); - return -EINVAL; - } - - /* Channel map is same for all sinks. However, as sinks allowed to have different - * sample formats, get new convert/remap function for each sink. - */ - for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++) { - if (cd->converter[i]) { - converters[i] = get_converter_func(&in_fmt, &cd->out_fmt[i], - ipc4_gtw_none, ipc4_bidirection, - chmap_cfg->channel_map); - /* Do not report an error if converter not found as sinks could be - * bound/unbound on a fly and out_fmt[i] may contain obsolete data. - */ - } else { - converters[i] = NULL; - } - } - - /* Atomically update chmap, process and converters */ - irq_local_disable(irq_flags); - - cd->dd[0]->chmap = chmap_cfg->channel_map; - cd->dd[0]->process = process; - for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++) - cd->converter[i] = converters[i]; - - irq_local_enable(irq_flags); - - return 0; -} - static int copier_set_configuration(struct processing_module *mod, uint32_t config_id, enum module_cfg_fragment_position pos, @@ -828,8 +743,6 @@ static int copier_set_configuration(struct processing_module *mod, return copier_set_sink_fmt(dev, fragment, fragment_size); case IPC4_COPIER_MODULE_CFG_ATTENUATION: return set_attenuation(dev, fragment_size, (const char *)fragment); - case IPC4_COPIER_MODULE_CFG_PARAM_CHANNEL_MAP: - return set_chmap(dev, fragment, fragment_size); default: return -EINVAL; } diff --git a/src/audio/copier/copier.h b/src/audio/copier/copier.h index 41bca7afc287..550219a2aa83 100644 --- a/src/audio/copier/copier.h +++ b/src/audio/copier/copier.h @@ -180,12 +180,7 @@ enum ipc4_copier_module_config_params { * uint32_t. Config is only allowed when output pin is set up for 32bit and * source is connected to Gateway */ - IPC4_COPIER_MODULE_CFG_ATTENUATION = 6, - /* Use LARGE_CONFIG_SET to setup new channel map, which allows to map channels - * from gateway buffer to copier with any order. - * Same mapping will be applied for all copier sinks. - */ - IPC4_COPIER_MODULE_CFG_PARAM_CHANNEL_MAP = 7 + IPC4_COPIER_MODULE_CFG_ATTENUATION = 6 }; struct ipc4_copier_config_timestamp_init_data { @@ -206,13 +201,6 @@ struct ipc4_copier_config_set_sink_format { struct ipc4_audio_format sink_fmt; } __attribute__((packed, aligned(4))); -struct ipc4_copier_config_channel_map { - /* Each half-byte of the channel map is an index of the DMA stream channel that - * should be copied to the position determined by this half-byte index. - */ - uint32_t channel_map; -} __attribute__((packed, aligned(4))); - #define IPC4_COPIER_DATA_SEGMENT_DISABLE (0 << 0) #define IPC4_COPIER_DATA_SEGMENT_ENABLE (1 << 0) #define IPC4_COPIER_DATA_SEGMENT_RESTART (1 << 1) @@ -244,7 +232,6 @@ struct copier_data { */ struct ipc4_copier_module_cfg config; void *gtw_cfg; - enum ipc4_gateway_type gtw_type; struct comp_dev *endpoint[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT]; struct comp_buffer *endpoint_buffer[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT]; uint32_t endpoint_num; @@ -280,8 +267,7 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt, const struct ipc4_audio_format *out_fmt, enum ipc4_gateway_type type, - enum ipc4_direction_type dir, - uint32_t chmap); + enum ipc4_direction_type dir); struct comp_ipc_config; int create_endpoint_buffer(struct comp_dev *dev, diff --git a/src/audio/copier/copier_dai.c b/src/audio/copier/copier_dai.c index 80866f6933c1..66e621f0eccf 100644 --- a/src/audio/copier/copier_dai.c +++ b/src/audio/copier/copier_dai.c @@ -164,7 +164,6 @@ static int copier_dai_init(struct comp_dev *dev, { struct processing_module *mod = comp_mod(dev); struct copier_data *cd = module_get_private_data(mod); - uint32_t chmap; struct dai_data *dd; int ret; @@ -179,7 +178,6 @@ static int copier_dai_init(struct comp_dev *dev, config->frame_fmt = out_frame_fmt; pipeline->sink_comp = dev; cd->bsource_buffer = true; - chmap = copier->base.audio_fmt.ch_map; } else { enum sof_ipc_frame in_frame_fmt, in_valid_fmt; @@ -189,7 +187,6 @@ static int copier_dai_init(struct comp_dev *dev, copier->base.audio_fmt.s_type); config->frame_fmt = in_frame_fmt; pipeline->source_comp = dev; - chmap = copier->out_fmt.ch_map; } /* save the channel map and count for ALH multi-gateway */ @@ -208,8 +205,6 @@ static int copier_dai_init(struct comp_dev *dev, if (ret < 0) goto free_dd; - dd->chmap = chmap; - pipeline->sched_id = config->id; cd->dd[index] = dd; @@ -239,6 +234,7 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd, struct comp_ipc_config *config = &dev->ipc_config; int dai_index[IPC4_ALH_MAX_NUMBER_OF_GTW]; union ipc4_connector_node_id node_id; + enum ipc4_gateway_type type; struct ipc_config_dai dai; int dai_count; int i, ret; @@ -259,13 +255,13 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd, case ipc4_hda_link_input_class: dai.type = SOF_DAI_INTEL_HDA; dai.is_config_blob = true; - cd->gtw_type = ipc4_gtw_link; + type = ipc4_gtw_link; break; case ipc4_i2s_link_output_class: case ipc4_i2s_link_input_class: dai.type = SOF_DAI_INTEL_SSP; dai.is_config_blob = true; - cd->gtw_type = ipc4_gtw_ssp; + type = ipc4_gtw_ssp; ret = ipc4_find_dma_config(&dai, (uint8_t *)cd->gtw_cfg, copier->gtw_cfg.config_length * 4); if (ret != 0) { @@ -279,11 +275,11 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd, #if ACE_VERSION > ACE_VERSION_1_5 dai.type = SOF_DAI_INTEL_HDA; dai.is_config_blob = true; - cd->gtw_type = ipc4_gtw_link; + type = ipc4_gtw_link; #else dai.type = SOF_DAI_INTEL_ALH; dai.is_config_blob = true; - cd->gtw_type = ipc4_gtw_alh; + type = ipc4_gtw_alh; #endif /* ACE_VERSION > ACE_VERSION_1_5 */ ret = copier_alh_assign_dai_index(dev, cd->gtw_cfg, node_id, &dai, dai_index, &dai_count); @@ -293,7 +289,7 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd, case ipc4_dmic_link_input_class: dai.type = SOF_DAI_INTEL_DMIC; dai.is_config_blob = true; - cd->gtw_type = ipc4_gtw_dmic; + type = ipc4_gtw_dmic; ret = ipc4_find_dma_config(&dai, (uint8_t *)cd->gtw_cfg, copier->gtw_cfg.config_length * 4); if (ret != 0) { @@ -308,7 +304,7 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd, for (i = 0; i < dai_count; i++) { dai.dai_index = dai_index[i]; - ret = copier_dai_init(dev, config, copier, pipeline, &dai, cd->gtw_type, i, + ret = copier_dai_init(dev, config, copier, pipeline, &dai, type, i, dai_count); if (ret) { comp_err(dev, "failed to create dai"); @@ -317,11 +313,11 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd, } cd->converter[IPC4_COPIER_GATEWAY_PIN] = - get_converter_func(&copier->base.audio_fmt, &copier->out_fmt, cd->gtw_type, - IPC4_DIRECTION(dai.direction), DUMMY_CHMAP); + get_converter_func(&copier->base.audio_fmt, &copier->out_fmt, type, + IPC4_DIRECTION(dai.direction)); if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { comp_err(dev, "failed to get converter type %d, dir %d", - cd->gtw_type, dai.direction); + type, dai.direction); return -EINVAL; } @@ -454,81 +450,40 @@ static int copy_single_channel_c32(const struct audio_stream *src, return 0; } -void copier_dai_adjust_params(const struct copier_data *cd, - struct ipc4_audio_format *in_fmt, - struct ipc4_audio_format *out_fmt) -{ - struct comp_buffer *dma_buf; - int dma_buf_channels; - int dma_buf_container_bits, dma_buf_valid_bits; - - /* Call this func only for DAI gateway with already setup DMA buffer */ - assert(cd->dd[0] && cd->dd[0]->dma_buffer); - dma_buf = cd->dd[0]->dma_buffer; - - /* Unfortunately, configuring the gateway DMA buffer format is somewhat confusing. - * The number of channels can come from hardware parameters (extracted from a blob?) - * and also appears in the copier's input/output format. In case the value returned - * by the hardware looks valid, it should take precedence over the value from the - * copier's input/output format. - * - * The frame format comes from the topology as dev->ipc_config.frame_fmt and also - * comes as the copier's input/output format. The logic is confusing: the format - * from the topology takes priority, except when the copier's format container and - * valid sample size are different. Perhaps this is to support the 16-bit valid - * in the 32-bit container format used by SSP, as such a format cannot be specified - * in the topology? - */ - dma_buf_channels = audio_stream_get_channels(&dma_buf->stream); - dma_buf_container_bits = audio_stream_sample_bytes(&dma_buf->stream) * 8; - dma_buf_valid_bits = get_sample_bitdepth(audio_stream_get_frm_fmt(&dma_buf->stream)); - - if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { - out_fmt->channels_count = dma_buf_channels; - - if (!(dma_buf_container_bits == out_fmt->depth && - out_fmt->depth != out_fmt->valid_bit_depth)) { - out_fmt->depth = dma_buf_container_bits; - out_fmt->valid_bit_depth = dma_buf_valid_bits; - } - } else { - in_fmt->channels_count = dma_buf_channels; - - if (!(dma_buf_container_bits == in_fmt->depth && - in_fmt->depth != in_fmt->valid_bit_depth)) { - in_fmt->depth = dma_buf_container_bits; - in_fmt->valid_bit_depth = dma_buf_valid_bits; - } - } -} - int copier_dai_params(struct copier_data *cd, struct comp_dev *dev, struct sof_ipc_stream_params *params, int dai_index) { struct sof_ipc_stream_params demuxed_params = *params; + const struct ipc4_audio_format *in_fmt = &cd->config.base.audio_fmt; + const struct ipc4_audio_format *out_fmt = &cd->config.out_fmt; + enum sof_ipc_frame in_bits, in_valid_bits, out_bits, out_valid_bits; int container_size; int j, ret; if (cd->endpoint_num == 1) { - struct ipc4_audio_format in_fmt = cd->config.base.audio_fmt; - struct ipc4_audio_format out_fmt = cd->config.out_fmt; - enum ipc4_direction_type dir; - ret = dai_common_params(cd->dd[0], dev, params); - if (ret < 0) - return ret; - - copier_dai_adjust_params(cd, &in_fmt, &out_fmt); - - dir = (cd->direction == SOF_IPC_STREAM_PLAYBACK) ? - ipc4_playback : ipc4_capture; - - cd->dd[0]->process = - get_converter_func(&in_fmt, &out_fmt, cd->gtw_type, dir, cd->dd[0]->chmap); + /* + * dai_zephyr_params assigns the conversion function + * based on the input/output formats but does not take + * the valid bits into account. So change the conversion + * function if the valid bits are different from the + * container size. + */ + audio_stream_fmt_conversion(in_fmt->depth, + in_fmt->valid_bit_depth, + &in_bits, &in_valid_bits, + in_fmt->s_type); + audio_stream_fmt_conversion(out_fmt->depth, + out_fmt->valid_bit_depth, + &out_bits, &out_valid_bits, + out_fmt->s_type); + + if (in_bits != in_valid_bits || out_bits != out_valid_bits) + cd->dd[0]->process = + cd->converter[IPC4_COPIER_GATEWAY_PIN]; return ret; } - /* For ALH multi-gateway case, params->channels is a total multiplexed * number of channels. Demultiplexed number of channels for each individual * gateway comes in blob's struct ipc4_alh_multi_gtw_cfg. diff --git a/src/audio/copier/copier_generic.c b/src/audio/copier/copier_generic.c index 4cb480ebe3f9..ed31fb7414e7 100644 --- a/src/audio/copier/copier_generic.c +++ b/src/audio/copier/copier_generic.c @@ -249,26 +249,10 @@ static bool use_no_container_convert_function(enum sof_ipc_frame in, return false; } -static bool is_remapping_chmap(uint32_t chmap, size_t out_channel_count) -{ - size_t i; - - assert(out_channel_count <= 8); - - for (i = 0; i < out_channel_count; i++) { - if ((chmap & 0xf) != i) - return true; - chmap >>= 4; - } - - return false; -} - pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt, const struct ipc4_audio_format *out_fmt, enum ipc4_gateway_type type, - enum ipc4_direction_type dir, - uint32_t chmap) + enum ipc4_direction_type dir) { enum sof_ipc_frame in, in_valid, out, out_valid; @@ -317,16 +301,6 @@ pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt, } } - if (in_fmt->channels_count != out_fmt->channels_count || - is_remapping_chmap(chmap, out_fmt->channels_count)) { - if (in_valid == SOF_IPC_FRAME_S16_LE && in == SOF_IPC_FRAME_S32_LE) - in = SOF_IPC_FRAME_S16_4LE; - if (out_valid == SOF_IPC_FRAME_S16_LE && out == SOF_IPC_FRAME_S32_LE) - out = SOF_IPC_FRAME_S16_4LE; - - return pcm_get_remap_function(in, out); - } - /* check container & sample size */ if (use_no_container_convert_function(in, in_valid, out, out_valid)) return pcm_get_conversion_function(in, out); diff --git a/src/audio/copier/copier_host.c b/src/audio/copier/copier_host.c index b61af44bfe0e..a7eafac04eaa 100644 --- a/src/audio/copier/copier_host.c +++ b/src/audio/copier/copier_host.c @@ -136,7 +136,6 @@ int copier_host_create(struct comp_dev *dev, struct copier_data *cd, enum sof_ipc_frame in_valid_fmt, out_valid_fmt; config->type = SOF_COMP_HOST; - cd->gtw_type = ipc4_gtw_host; audio_stream_fmt_conversion(copier_cfg->base.audio_fmt.depth, copier_cfg->base.audio_fmt.valid_bit_depth, @@ -196,7 +195,7 @@ int copier_host_create(struct comp_dev *dev, struct copier_data *cd, cd->converter[IPC4_COPIER_GATEWAY_PIN] = get_converter_func(&copier_cfg->base.audio_fmt, &copier_cfg->out_fmt, - ipc4_gtw_host, IPC4_DIRECTION(dir), DUMMY_CHMAP); + ipc4_gtw_host, IPC4_DIRECTION(dir)); if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { comp_err(dev, "failed to get converter for host, dir %d", dir); ret = -EINVAL; diff --git a/src/audio/copier/copier_ipcgtw.c b/src/audio/copier/copier_ipcgtw.c index b5dccbd12986..cdac60e98249 100644 --- a/src/audio/copier/copier_ipcgtw.c +++ b/src/audio/copier/copier_ipcgtw.c @@ -229,7 +229,6 @@ int copier_ipcgtw_create(struct comp_dev *dev, struct copier_data *cd, * IPC gateway should be handled similarly as host gateway. */ config->type = SOF_COMP_HOST; - cd->gtw_type = ipc4_gtw_host; ret = create_endpoint_buffer(dev, cd, copier, false); if (ret < 0) @@ -256,7 +255,7 @@ int copier_ipcgtw_create(struct comp_dev *dev, struct copier_data *cd, cd->converter[IPC4_COPIER_GATEWAY_PIN] = get_converter_func(&copier->base.audio_fmt, &copier->out_fmt, - ipc4_gtw_host, IPC4_DIRECTION(cd->direction), DUMMY_CHMAP); + ipc4_gtw_host, IPC4_DIRECTION(cd->direction)); if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { comp_err(dev, "failed to get converter for IPC gateway, dir %d", cd->direction); diff --git a/src/audio/copier/dai_copier.h b/src/audio/copier/dai_copier.h index a03970288b1b..4694b48ff1f2 100644 --- a/src/audio/copier/dai_copier.h +++ b/src/audio/copier/dai_copier.h @@ -83,10 +83,6 @@ void copier_dai_free(struct copier_data *cd); int copier_dai_prepare(struct comp_dev *dev, struct copier_data *cd); -void copier_dai_adjust_params(const struct copier_data *cd, - struct ipc4_audio_format *in_fmt, - struct ipc4_audio_format *out_fmt); - int copier_dai_params(struct copier_data *cd, struct comp_dev *dev, struct sof_ipc_stream_params *params, int dai_index); diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c index c289b517e8d2..745f0c7d40f7 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -269,7 +269,7 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes, if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { ret = dma_buffer_copy_to(dd->local_buffer, dd->dma_buffer, - dd->process, bytes, dd->chmap); + dd->process, bytes, DUMMY_CHMAP); } else { audio_stream_invalidate(&dd->dma_buffer->stream, bytes); /* @@ -277,7 +277,7 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes, * so no need to check the return value of dma_buffer_copy_from_no_consume(). */ ret = dma_buffer_copy_from_no_consume(dd->dma_buffer, dd->local_buffer, - dd->process, bytes, dd->chmap); + dd->process, bytes, DUMMY_CHMAP); #if CONFIG_IPC_MAJOR_4 struct list_item *sink_list; /* Skip in case of endpoint DAI devices created by the copier */ @@ -318,7 +318,7 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes, sink->hw_params_configured) ret = dma_buffer_copy_from_no_consume(dd->dma_buffer, sink, converter[j], - bytes, dd->chmap); + bytes, DUMMY_CHMAP); } } #endif @@ -468,8 +468,6 @@ static struct comp_dev *dai_new(const struct comp_driver *drv, if (ret < 0) goto error; - dd->chmap = DUMMY_CHMAP; - dev->state = COMP_STATE_READY; return dev; @@ -796,8 +794,7 @@ static int dai_set_dma_config(struct dai_data *dd, struct comp_dev *dev) } static int dai_set_dma_buffer(struct dai_data *dd, struct comp_dev *dev, - const struct sof_ipc_stream_params *params, - uint32_t *pb, uint32_t *pc) + struct sof_ipc_stream_params *params, uint32_t *pb, uint32_t *pc) { struct sof_ipc_stream_params hw_params = *params; uint32_t frame_size; @@ -919,10 +916,8 @@ static int dai_set_dma_buffer(struct dai_data *dd, struct comp_dev *dev, } int dai_common_params(struct dai_data *dd, struct comp_dev *dev, - struct sof_ipc_stream_params *base_cfg_params) + struct sof_ipc_stream_params *params) { - struct sof_ipc_stream_params params = *base_cfg_params; - struct sof_ipc_stream_params hw_params; struct dma_sg_config *config = &dd->config; uint32_t period_bytes = 0; uint32_t period_count = 0; @@ -937,30 +932,13 @@ int dai_common_params(struct dai_data *dd, struct comp_dev *dev, return err; } - /* When the hardware is able to return a valid number of DMA buffer audio channels - * (e.g., extracted from a blob), give the returned number of channels higher precedence - * over the number supplied via the base config params. - */ - memset(&hw_params, 0, sizeof(hw_params)); - err = dai_common_get_hw_params(dd, dev, &hw_params, params.direction); - if (err < 0) { - comp_err(dev, "dai_common_get_hw_params() failed: %d", err); - return err; - } - - if (hw_params.channels != 0 && hw_params.channels != params.channels) { - params.channels = hw_params.channels; - comp_info(dev, "Replacing %d base config channels with %d hw params channels.", - base_cfg_params->channels, params.channels); - } - - err = dai_verify_params(dd, dev, ¶ms); + err = dai_verify_params(dd, dev, params); if (err < 0) { comp_err(dev, "dai_zephyr_params(): pcm params verification failed."); return -EINVAL; } - err = dai_set_dma_buffer(dd, dev, ¶ms, &period_bytes, &period_count); + err = dai_set_dma_buffer(dd, dev, params, &period_bytes, &period_count); if (err < 0) { comp_err(dev, "dai_zephyr_params(): alloc dma buffer failed."); goto out; diff --git a/src/audio/pipeline/pipeline-graph.c b/src/audio/pipeline/pipeline-graph.c index 42fbdc7bae8f..0f5874a09b7d 100644 --- a/src/audio/pipeline/pipeline-graph.c +++ b/src/audio/pipeline/pipeline-graph.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -260,6 +261,11 @@ static int pipeline_comp_complete(struct comp_dev *current, /* complete component init */ current->pipeline = ppl_data->p; + + if (comp_is_llext(current)) + /* pipelines are allocated using rzalloc(), so initially .init_time = 0 */ + current->pipeline->init_time = sof_cycle_get_64(); + /* LL module has its period always eq period of the pipeline * DP period is set to 0 as sink format may not yet been set * It will be calculated during module prepare operation diff --git a/src/audio/pipeline/pipeline-stream.c b/src/audio/pipeline/pipeline-stream.c index add2dbd787b6..3e82523db5ed 100644 --- a/src/audio/pipeline/pipeline-stream.c +++ b/src/audio/pipeline/pipeline-stream.c @@ -192,7 +192,9 @@ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) return 0; } -#else + +#else /* CONFIG_LIBRARY */ + /* only collect scheduling components */ static int pipeline_comp_list(struct comp_dev *current, struct comp_buffer *calling_buf, @@ -315,77 +317,60 @@ static void pipeline_trigger_xrun(struct pipeline *p, struct comp_dev **host) } #if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL -static int pipeline_calc_cps_consumption(struct comp_dev *current, - struct comp_buffer *calling_buf, - struct pipeline_walk_context *ctx, int dir) +static struct ipc4_base_module_cfg *ipc4_get_base_cfg(struct comp_dev *comp) { - struct pipeline_data *ppl_data = ctx->comp_data; - struct ipc4_base_module_cfg *cd; - int comp_core, kcps; - - pipe_dbg(ppl_data->p, "pipeline_calc_cps_consumption(), current->comp.id = %u, dir = %u", - dev_comp_id(current), dir); + if (comp->drv->type != SOF_COMP_MODULE_ADAPTER) + return comp_get_drvdata(comp); - if (!comp_is_single_pipeline(current, ppl_data->start)) { - pipe_dbg(ppl_data->p, "pipeline_calc_cps_consumption(), current is from another pipeline"); - return 0; - } - comp_core = current->ipc_config.core; - - /* modules created through module adapter have different priv_data */ - if (current->drv->type != SOF_COMP_MODULE_ADAPTER) { - cd = comp_get_drvdata(current); - } else { - struct processing_module *mod = comp_mod(current); - struct module_data *md = &mod->priv; + struct processing_module *mod = comp_mod(comp); + struct module_data *md = &mod->priv; - cd = &md->cfg.base_cfg; - } - - if (cd->cpc == 0) { - /* Use maximum clock budget, assume 1ms chunk size */ - uint32_t core_kcps = core_kcps_get(comp_core); + return &md->cfg.base_cfg; +} - if (!current->kcps_inc[comp_core]) { - current->kcps_inc[comp_core] = core_kcps; - ppl_data->kcps[comp_core] = CLK_MAX_CPU_HZ / 1000 - core_kcps; - } else { - ppl_data->kcps[comp_core] = core_kcps - current->kcps_inc[comp_core]; - current->kcps_inc[comp_core] = 0; +static void pipeline_cps_rebalance(struct pipeline *p, bool starting) +{ + unsigned int core_kcps[CONFIG_CORE_COUNT] = {}; + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *icd; + struct list_item *clist; + const unsigned int clk_max_khz = CLK_MAX_CPU_HZ / 1000; + + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != COMP_TYPE_COMPONENT) + continue; + + struct comp_dev *comp = icd->cd; + + /* Don't add components on the pipeline, that we're shutting down */ + if (comp->state >= COMP_STATE_PREPARE && + (comp->pipeline != p || starting)) { + struct ipc4_base_module_cfg *cd = ipc4_get_base_cfg(comp); + + if (cd->cpc && core_kcps[icd->core] < clk_max_khz) + core_kcps[icd->core] += cd->cpc; + else + core_kcps[icd->core] = clk_max_khz; } - tr_warn(pipe, - "0 CPS requested for module: %#x, core: %d using safe max KCPS: %u", - current->ipc_config.id, comp_core, ppl_data->kcps[comp_core]); + } - return PPL_STATUS_PATH_STOP; - } else { - kcps = cd->cpc * 1000 / current->period; - tr_dbg(pipe, "Module: %#x KCPS consumption: %d, core: %d", - current->ipc_config.id, kcps, comp_core); + for (int i = 0; i < arch_num_cpus(); i++) { + int delta_kcps = core_kcps[i] - core_kcps_get(i); - ppl_data->kcps[comp_core] += kcps; + tr_info(pipe, "Proposed KCPS consumption: %d, core: %d, delta: %d", + core_kcps[i], i, delta_kcps); + if (delta_kcps) + core_kcps_adjust(i, delta_kcps); } - - return pipeline_for_each_comp(current, ctx, dir); } -#endif +#endif /* CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL */ /* trigger pipeline in IPC context */ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) { int ret; #if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL -/* FIXME: this must be a platform-specific parameter or a Kconfig option */ -#define DSP_MIN_KCPS 50000 - - struct pipeline_data data = { - .start = p->source_comp, - .p = p, - }; - struct pipeline_walk_context walk_ctx = { - .comp_func = pipeline_calc_cps_consumption, - .comp_data = &data, - }; bool trigger_first = false; uint32_t flags = 0; #endif @@ -418,16 +403,8 @@ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) #if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL flags = irq_lock(); /* setup walking ctx for removing consumption */ - if (!trigger_first) { - ret = walk_ctx.comp_func(p->source_comp, NULL, &walk_ctx, PPL_DIR_DOWNSTREAM); - - for (int i = 0; i < arch_num_cpus(); i++) { - if (data.kcps[i] > 0) { - core_kcps_adjust(i, data.kcps[i]); - tr_info(pipe, "Sum of KCPS consumption: %d, core: %d", core_kcps_get(i), i); - } - } - } + if (!trigger_first) + pipeline_cps_rebalance(p, true); #endif ret = pipeline_trigger_list(p, host, cmd); if (ret < 0) { @@ -437,23 +414,8 @@ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) return ret; } #if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL - if (trigger_first) { - ret = walk_ctx.comp_func(p->source_comp, NULL, &walk_ctx, PPL_DIR_DOWNSTREAM); - - for (int i = 0; i < arch_num_cpus(); i++) { - if (data.kcps[i] > 0) { - uint32_t core_kcps = core_kcps_get(i); - - /* Tests showed, that we cannot go below 40000kcps on MTL */ - if (data.kcps[i] > core_kcps - DSP_MIN_KCPS) - data.kcps[i] = core_kcps - DSP_MIN_KCPS; - - core_kcps_adjust(i, -data.kcps[i]); - tr_info(pipe, "Sum of KCPS consumption: %d, core: %d", - core_kcps, i); - } - } - } + if (trigger_first) + pipeline_cps_rebalance(p, false); irq_unlock(flags); #endif /* IPC response will be sent from the task, unless it was paused */ @@ -462,7 +424,7 @@ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) return 0; } -#endif +#endif /* CONFIG_LIBRARY */ /* Runs in IPC or in pipeline task context */ static int pipeline_comp_trigger(struct comp_dev *current, diff --git a/src/include/sof/audio/pipeline.h b/src/include/sof/audio/pipeline.h index 2410f774f00d..4291e4d1d637 100644 --- a/src/include/sof/audio/pipeline.h +++ b/src/include/sof/audio/pipeline.h @@ -94,6 +94,7 @@ struct pipeline { bool aborted; /* STOP or PAUSE failed, stay active */ bool pending; /* trigger scheduled but not executed yet */ } trigger; + uint64_t init_time; }; struct pipeline_walk_context { diff --git a/src/include/sof/lib/dai-zephyr.h b/src/include/sof/lib/dai-zephyr.h index b7f2f0f5c6f1..e909bfd40e05 100644 --- a/src/include/sof/lib/dai-zephyr.h +++ b/src/include/sof/lib/dai-zephyr.h @@ -129,7 +129,6 @@ struct dai_data { int xrun; /* true if we are doing xrun recovery */ pcm_converter_func process; /* processing function */ - uint32_t chmap; channel_copy_func channel_copy; /* channel copy func used by multi-endpoint * gateway to mux/demux stream from/to multiple diff --git a/src/include/sof/llext_manager.h b/src/include/sof/llext_manager.h index 55ca48d31755..3c4d4ade102b 100644 --- a/src/include/sof/llext_manager.h +++ b/src/include/sof/llext_manager.h @@ -6,21 +6,33 @@ #ifndef __SOF_LLEXT_MANAGER_H__ #define __SOF_LLEXT_MANAGER_H__ +#include #include +#if CONFIG_LLEXT +#include + +struct comp_dev; struct comp_driver; struct comp_ipc_config; -#if CONFIG_LLEXT +static inline bool module_is_llext(const struct sof_man_module *mod) +{ + return mod->type.load_type == SOF_MAN_MOD_TYPE_LLEXT; +} + uintptr_t llext_manager_allocate_module(struct processing_module *proc, const struct comp_ipc_config *ipc_config, const void *ipc_specific_config); int llext_manager_free_module(const uint32_t component_id); + +bool comp_is_llext(struct comp_dev *comp); #else #define llext_manager_allocate_module(proc, ipc_config, ipc_specific_config) 0 #define llext_manager_free_module(component_id) 0 #define llext_unload(ext) 0 +#define comp_is_llext(comp) false #endif #endif diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index d427643ef3ea..5a2aefa1adcc 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -331,6 +331,7 @@ static int ipc_pipeline_module_free(uint32_t pipeline_id) int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) { struct ipc_comp_dev *ipc_pipe; + uint64_t life_time; int ret; /* check whether pipeline exists */ @@ -342,6 +343,17 @@ int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) if (!cpu_is_me(ipc_pipe->core)) return ipc4_process_on_core(ipc_pipe->core, false); + if (ipc_pipe->pipeline->init_time) { + /* + * This pipeline must not be destroyed before a minimum time + * since its creation has passed + */ + life_time = k_cyc_to_ms_near64(sof_cycle_get_64() - ipc_pipe->pipeline->init_time); + pipe_dbg(ipc_pipe->pipeline, "Extend pipeline life beyond %llu", life_time); + if (life_time < CONFIG_LIBRARY_PIPELINE_FORCE_MIN_LIFETIME) + k_msleep(CONFIG_LIBRARY_PIPELINE_FORCE_MIN_LIFETIME - life_time); + } + ret = ipc_pipeline_module_free(ipc_pipe->pipeline->pipeline_id); if (ret != IPC4_SUCCESS) { tr_err(&ipc_tr, "ipc_pipeline_free(): module free () failed"); diff --git a/src/library_manager/Kconfig b/src/library_manager/Kconfig index e167f956a37a..627553790beb 100644 --- a/src/library_manager/Kconfig +++ b/src/library_manager/Kconfig @@ -33,4 +33,15 @@ config LIBRARY_AUTH_SUPPORT could be used if enabled. If unsure say N. +config LIBRARY_PIPELINE_FORCE_MIN_LIFETIME + int "Minimum pipeline life-time in ms" + default 0 + range 0 500 + help + Typically pipelines are created for streaming, which lasts for + considerable time, at least seconds. But in some test-cases pipelines + are created and quickly destroyed again with no streaming at all. In + some configurations this leads to failures. This option allows setting + a minimum pipeline life-time, which fixes those scenarios. + endmenu diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 82e9625a6a38..40dce7169daa 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -339,11 +339,6 @@ static int lib_manager_free_module_instance(uint32_t module_id, uint32_t instanc return sys_mm_drv_unmap_region((__sparse_force void *)va_base, bss_size); } -static inline bool module_is_llext(const struct sof_man_module *mod) -{ - return mod->type.load_type == SOF_MAN_MOD_TYPE_LLEXT; -} - uintptr_t lib_manager_allocate_module(struct processing_module *proc, const struct comp_ipc_config *ipc_config, const void *ipc_specific_config) diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index e4341678ba91..196d87c343df 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -363,3 +363,13 @@ int llext_manager_free_module(const uint32_t component_id) return llext_manager_unload_module(base_module_id, mod); } + +bool comp_is_llext(struct comp_dev *comp) +{ + const uint32_t module_id = IPC4_MOD_ID(comp->ipc_config.id); + const unsigned int base_module_id = LIB_MANAGER_GET_LIB_ID(module_id) << + LIB_MANAGER_LIB_ID_SHIFT; + const struct sof_man_module *mod = lib_manager_get_module_manifest(base_module_id); + + return mod && module_is_llext(mod); +}