diff --git a/src/arch/host/configs/library_defconfig b/src/arch/host/configs/library_defconfig index 08786d998e2f..deed943ab818 100644 --- a/src/arch/host/configs/library_defconfig +++ b/src/arch/host/configs/library_defconfig @@ -5,6 +5,7 @@ CONFIG_COMP_DRC=y CONFIG_COMP_FIR=y CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=y CONFIG_COMP_IIR=y +CONFIG_COMP_IGO_NR=y CONFIG_COMP_MFCC=y CONFIG_COMP_MODULE_ADAPTER=y CONFIG_COMP_MULTIBAND_DRC=y diff --git a/src/audio/igo_nr/igo_nr.c b/src/audio/igo_nr/igo_nr.c index 47750ba22151..9a968935e637 100644 --- a/src/audio/igo_nr/igo_nr.c +++ b/src/audio/igo_nr/igo_nr.c @@ -4,6 +4,7 @@ // // Author: Fu-Yun TSUO +#include #include #include #include @@ -30,6 +31,10 @@ #include #include +#if CONFIG_IPC_MAJOR_4 +#include +#endif + #define SOF_IGO_NR_MAX_SIZE 4096 /* Max size for coef data in bytes */ enum IGO_NR_ENUM { @@ -37,7 +42,7 @@ enum IGO_NR_ENUM { IGO_NR_ENUM_LAST, }; -static const struct comp_driver comp_igo_nr; +LOG_MODULE_REGISTER(igo_nr, CONFIG_SOF_LOG_LEVEL); /* 696ae2bc-2877-11eb-adc1-0242ac120002 */ DECLARE_SOF_RT_UUID("igo-nr", igo_nr_uuid, 0x696ae2bc, 0x2877, 0x11eb, 0xad, 0xc1, @@ -65,185 +70,315 @@ static void igo_nr_lib_process(struct comp_data *cd) } #if CONFIG_FORMAT_S16LE -static void igo_nr_capture_s16(struct comp_data *cd, - const struct audio_stream *source, - struct audio_stream *sink, - int32_t frames) +static int igo_nr_capture_s16(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink, + int32_t frames) { - int32_t nch = audio_stream_get_channels(source); - int32_t i; - int32_t j; - int32_t idx_in = 0; - int32_t idx_out = 0; - int16_t *x; - int16_t *y; + int16_t *x, *y1, *y2; + int16_t *x_start, *y_start, *x_end, *y_end; + int16_t sample; + size_t x_size, y_size; + size_t request_size = frames * source_get_frame_bytes(source); + int sink_samples_without_wrap; + int samples_without_wrap; + int samples_left; + int ret; + int nch = source_get_channels(source); + int i, j, k; + #if CONFIG_DEBUG int32_t dbg_en = cd->config.igo_params.dump_data == 1 && nch > 1; int32_t dbg_ch_idx; + + /* Under DEBUG mode, overwrite the next channel with input interleavedly. */ + if (cd->config.active_channel_idx >= nch) + dbg_ch_idx = 0; + else + dbg_ch_idx = cd->config.active_channel_idx + 1; + #endif + ret = source_get_data(source, request_size, (void const **)&x, + (void const **)&x_start, &x_size); + if (ret) + return ret; + + ret = sink_get_buffer(sink, request_size, (void **)&y1, (void **)&y_start, &y_size); + if (ret) { + source_release_data(source, 0); + return ret; + } + + y2 = y1; + x_end = x_start + x_size; + y_end = y_start + y_size; + /* Deinterleave the source buffer and keeps the active channel data as input. */ - for (i = 0; i < frames; i++) { - - /* Pass through all the other channels */ - for (j = 0; j < nch; j++) { - if (j == cd->config.active_channel_idx) - continue; - x = audio_stream_read_frag_s16(source, idx_in + j); - y = audio_stream_write_frag_s16(sink, idx_in + j); - *y = (*x); + i = 0; + samples_left = nch * frames; + while (samples_left) { + samples_without_wrap = x_end - x; + samples_without_wrap = MIN(samples_left, samples_without_wrap); + sink_samples_without_wrap = y_end - y1; + samples_without_wrap = MIN(samples_without_wrap, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + sample = *x; + if (k == cd->config.active_channel_idx) + cd->in[i] = sample; + else + *y1 = sample; + + x++; + y1++; + } + i++; } - x = audio_stream_read_frag_s16(source, idx_in + cd->config.active_channel_idx); - cd->in[i] = (*x); - - idx_in += nch; + x = cir_buf_wrap(x, x_start, x_end); + y1 = cir_buf_wrap(y1, y_start, y_end); + samples_left -= samples_without_wrap; } igo_nr_lib_process(cd); /* Interleave write the processed data into active output channel. */ - for (i = 0; i < frames; i++) { - y = audio_stream_write_frag_s16(sink, idx_out + cd->config.active_channel_idx); - *y = (cd->out[i]); - + i = 0; + samples_left = nch * frames; + while (samples_left) { + sink_samples_without_wrap = y_end - y2; + samples_without_wrap = MIN(samples_left, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + if (k == cd->config.active_channel_idx) + *y2 = cd->out[i]; #if CONFIG_DEBUG - /* Under DEBUG mode, overwrite the next channel with input interleavedly. */ - if (cd->config.active_channel_idx >= nch) - dbg_ch_idx = 0; - else - dbg_ch_idx = cd->config.active_channel_idx + 1; - if (dbg_en) { - y = audio_stream_write_frag_s16(sink, idx_out + dbg_ch_idx); - *y = (cd->in[i]); - } + if (dbg_en && k == dbg_ch_idx) + *y2 = cd->in[i]; #endif - idx_out += nch; + y2++; + } + i++; + } + + y2 = cir_buf_wrap(y2, y_start, y_end); + samples_left -= samples_without_wrap; } + + source_release_data(source, request_size); + sink_commit_buffer(sink, request_size); + return 0; } #endif #if CONFIG_FORMAT_S24LE -static void igo_nr_capture_s24(struct comp_data *cd, - const struct audio_stream *source, - struct audio_stream *sink, - int32_t frames) +static int igo_nr_capture_s24(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink, + int32_t frames) { - int32_t nch = audio_stream_get_channels(source); - int32_t i; - int32_t j; - int32_t idx_in = 0; - int32_t idx_out = 0; - int32_t *x; - int32_t *y; + int32_t *x, *y1, *y2; + int32_t *x_start, *y_start, *x_end, *y_end; + size_t x_size, y_size; + size_t request_size = frames * source_get_frame_bytes(source); + int sink_samples_without_wrap; + int samples_without_wrap; + int samples_left; + int ret; + int nch = source_get_channels(source); + int i, j, k; + #if CONFIG_DEBUG int32_t dbg_en = cd->config.igo_params.dump_data == 1 && nch > 1; int32_t dbg_ch_idx; + + /* Under DEBUG mode, overwrite the next channel with input interleavedly. */ + if (cd->config.active_channel_idx >= nch) + dbg_ch_idx = 0; + else + dbg_ch_idx = cd->config.active_channel_idx + 1; + #endif + ret = source_get_data(source, request_size, (void const **)&x, + (void const **)&x_start, &x_size); + if (ret) + return ret; + + ret = sink_get_buffer(sink, request_size, (void **)&y1, (void **)&y_start, &y_size); + if (ret) { + source_release_data(source, 0); + return ret; + } + + y2 = y1; + x_end = x_start + x_size; + y_end = y_start + y_size; + /* Deinterleave the source buffer and keeps the active channel data as input. */ - for (i = 0; i < frames; i++) { - - /* Pass through all the other channels */ - for (j = 0; j < nch; j++) { - if (j == cd->config.active_channel_idx) - continue; - x = audio_stream_read_frag_s32(source, idx_in + j); - y = audio_stream_write_frag_s32(sink, idx_in + j); - *y = (*x); + i = 0; + samples_left = nch * frames; + while (samples_left) { + samples_without_wrap = x_end - x; + samples_without_wrap = MIN(samples_left, samples_without_wrap); + sink_samples_without_wrap = y_end - y1; + samples_without_wrap = MIN(samples_without_wrap, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + if (k == cd->config.active_channel_idx) + cd->in[i] = sat_int16(Q_SHIFT_RND(*x, 23, 15)); + else + *y1 = *x; + + x++; + y1++; + } + i++; } - x = audio_stream_read_frag_s32(source, idx_in + cd->config.active_channel_idx); - cd->in[i] = Q_SHIFT_RND(*x, 24, 16); - - idx_in += nch; + x = cir_buf_wrap(x, x_start, x_end); + y1 = cir_buf_wrap(y1, y_start, y_end); + samples_left -= samples_without_wrap; } igo_nr_lib_process(cd); /* Interleave write the processed data into active output channel. */ - for (i = 0; i < frames; i++) { - y = audio_stream_write_frag_s32(sink, idx_out + cd->config.active_channel_idx); - *y = (cd->out[i]) << 8; - + i = 0; + samples_left = nch * frames; + while (samples_left) { + sink_samples_without_wrap = y_end - y2; + samples_without_wrap = MIN(samples_left, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + if (k == cd->config.active_channel_idx) + *y2 = cd->out[i] << 8; #if CONFIG_DEBUG - /* Under DEBUG mode, overwrite the next channel with input interleavedly. */ - if (cd->config.active_channel_idx >= nch) - dbg_ch_idx = 0; - else - dbg_ch_idx = cd->config.active_channel_idx + 1; - if (dbg_en) { - y = audio_stream_write_frag_s32(sink, idx_out + dbg_ch_idx); - *y = (cd->in[i]) << 8; - } + if (dbg_en && k == dbg_ch_idx) + *y2 = cd->in[i] << 8; #endif - idx_out += nch; + y2++; + } + i++; + } + + y2 = cir_buf_wrap(y2, y_start, y_end); + samples_left -= samples_without_wrap; } + + source_release_data(source, request_size); + sink_commit_buffer(sink, request_size); + return 0; } #endif #if CONFIG_FORMAT_S32LE -static void igo_nr_capture_s32(struct comp_data *cd, - const struct audio_stream *source, - struct audio_stream *sink, - int32_t frames) +static int igo_nr_capture_s32(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink, + int32_t frames) { - int32_t nch = audio_stream_get_channels(source); - int32_t i; - int32_t j; - int32_t idx_in = 0; - int32_t idx_out = 0; - int32_t *x; - int32_t *y; + int32_t *x, *y1, *y2; + int32_t *x_start, *y_start, *x_end, *y_end; + size_t x_size, y_size; + size_t request_size = frames * source_get_frame_bytes(source); + int sink_samples_without_wrap; + int samples_without_wrap; + int samples_left; + int ret; + int nch = source_get_channels(source); + int i, j, k; + #if CONFIG_DEBUG int32_t dbg_en = cd->config.igo_params.dump_data == 1 && nch > 1; int32_t dbg_ch_idx; + + /* Under DEBUG mode, overwrite the next channel with input interleavedly. */ + if (cd->config.active_channel_idx >= nch) + dbg_ch_idx = 0; + else + dbg_ch_idx = cd->config.active_channel_idx + 1; + #endif - for (i = 0; i < frames; i++) { + ret = source_get_data(source, request_size, (void const **)&x, + (void const **)&x_start, &x_size); + if (ret) + return ret; - /* Pass through all the other channels */ - for (j = 0; j < nch; j++) { - if (j == cd->config.active_channel_idx) - continue; - x = audio_stream_read_frag_s32(source, idx_in + j); - y = audio_stream_write_frag_s32(sink, idx_in + j); - *y = (*x); - } + ret = sink_get_buffer(sink, request_size, (void **)&y1, (void **)&y_start, &y_size); + if (ret) { + source_release_data(source, 0); + return ret; + } + + y2 = y1; + x_end = x_start + x_size; + y_end = y_start + y_size; - x = audio_stream_read_frag_s32(source, idx_in + cd->config.active_channel_idx); - cd->in[i] = Q_SHIFT_RND(*x, 32, 16); + /* Deinterleave the source buffer and keeps the active channel data as input. */ + i = 0; + samples_left = nch * frames; + while (samples_left) { + samples_without_wrap = x_end - x; + samples_without_wrap = MIN(samples_left, samples_without_wrap); + sink_samples_without_wrap = y_end - y1; + samples_without_wrap = MIN(samples_without_wrap, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + if (k == cd->config.active_channel_idx) + cd->in[i] = sat_int16(Q_SHIFT_RND(*x, 31, 15)); + else + *y1 = *x; + + x++; + y1++; + } + i++; + } - idx_in += nch; + x = cir_buf_wrap(x, x_start, x_end); + y1 = cir_buf_wrap(y1, y_start, y_end); + samples_left -= samples_without_wrap; } igo_nr_lib_process(cd); /* Interleave write the processed data into active output channel. */ - for (i = 0; i < frames; i++) { - y = audio_stream_write_frag_s32(sink, idx_out + cd->config.active_channel_idx); - *y = (cd->out[i]) << 16; - + i = 0; + samples_left = nch * frames; + while (samples_left) { + sink_samples_without_wrap = y_end - y2; + samples_without_wrap = MIN(samples_left, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + if (k == cd->config.active_channel_idx) + *y2 = cd->out[i] << 16; #if CONFIG_DEBUG - /* Under DEBUG mode, overwrite the next channel with input interleavedly. */ - if (cd->config.active_channel_idx >= nch) - dbg_ch_idx = 0; - else - dbg_ch_idx = cd->config.active_channel_idx + 1; - if (dbg_en) { - y = audio_stream_write_frag_s32(sink, idx_out + dbg_ch_idx); - *y = (cd->in[i]) << 16; - } + if (dbg_en && k == dbg_ch_idx) + *y2 = cd->in[i] << 16; #endif - idx_out += nch; + y2++; + } + i++; + } + + y2 = cir_buf_wrap(y2, y_start, y_end); + samples_left -= samples_without_wrap; } + + source_release_data(source, request_size); + sink_commit_buffer(sink, request_size); + return 0; } #endif -static inline int32_t set_capture_func(struct comp_dev *dev) +static inline int32_t set_capture_func(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); struct comp_buffer *sourceb; + struct comp_dev *dev = mod->dev; sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); @@ -275,166 +410,120 @@ static inline int32_t set_capture_func(struct comp_dev *dev) return 0; } -static struct comp_dev *igo_nr_new(const struct comp_driver *drv, - const struct comp_ipc_config *config, const void *spec) +static int igo_nr_init(struct processing_module *mod) { - const struct ipc_config_process *ipc_igo_nr = spec; - struct comp_dev *dev = NULL; - struct comp_data *cd = NULL; - size_t bs = ipc_igo_nr->size; + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct module_config *cfg = &md->cfg; + struct comp_data *cd; + size_t bs = cfg->size; int32_t ret; - comp_cl_info(&comp_igo_nr, "igo_nr_new()"); + comp_info(dev, "igo_nr_init()"); /* Check first that configuration blob size is sane */ if (bs > SOF_IGO_NR_MAX_SIZE) { - comp_cl_err(&comp_igo_nr, "igo_nr_new() error: configuration blob size = %u > %d", - bs, SOF_IGO_NR_MAX_SIZE); - return NULL; + comp_err(dev, "igo_nr_init() error: configuration blob size = %u > %d", + bs, SOF_IGO_NR_MAX_SIZE); + return -EINVAL; } - 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) - goto fail; + return -ENOMEM; + md->private = cd; ret = IgoLibGetInfo(&cd->igo_lib_info); if (ret != IGO_RET_OK) { - comp_cl_err(&comp_igo_nr, "igo_nr_new(): IgoLibGetInfo() Failed."); + comp_err(dev, "igo_nr_init(): IgoLibGetInfo() Failed."); + ret = -EINVAL; goto cd_fail; } cd->p_handle = rballoc(0, SOF_MEM_CAPS_RAM, cd->igo_lib_info.handle_size); if (!cd->p_handle) { - comp_cl_err(&comp_igo_nr, "igo_nr_new(): igo_handle memory rballoc error"); + comp_err(dev, "igo_nr_init(): igo_handle memory rballoc error for size %d", + cd->igo_lib_info.handle_size); + ret = -ENOMEM; goto cd_fail; } - comp_set_drvdata(dev, cd); - /* Handler for configuration data */ cd->model_handler = comp_data_blob_handler_new(dev); if (!cd->model_handler) { - comp_cl_err(&comp_igo_nr, "igo_nr_new(): comp_data_blob_handler_new() failed."); - goto cd_fail; + comp_err(dev, "igo_nr_init(): comp_data_blob_handler_new() failed."); + ret = -ENOMEM; + goto cd_fail2; } /* Get configuration data */ - ret = comp_init_data_blob(cd->model_handler, bs, ipc_igo_nr->data); + ret = comp_init_data_blob(cd->model_handler, bs, cfg->data); if (ret < 0) { - comp_cl_err(&comp_igo_nr, "igo_nr_new(): comp_init_data_blob() failed."); - goto cd_fail; + comp_err(dev, "igo_nr_init(): comp_init_data_blob() failed."); + ret = -ENOMEM; + goto cd_fail3; } - dev->state = COMP_STATE_READY; - comp_cl_info(&comp_igo_nr, "igo_nr created"); + /* update downstream (playback) or upstream (capture) buffer parameters */ + mod->verify_params_flags = BUFF_PARAMS_RATE; + comp_info(dev, "igo_nr created"); + return 0; + +cd_fail3: + comp_data_blob_handler_free(cd->model_handler); - return dev; +cd_fail2: + rfree(cd->p_handle); cd_fail: - comp_data_blob_handler_free(cd->model_handler); rfree(cd); -fail: - rfree(dev); - return NULL; + return ret; } -static void igo_nr_free(struct comp_dev *dev) +static int igo_nr_free(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); - comp_info(dev, "igo_nr_free()"); + comp_info(mod->dev, "igo_nr_free()"); comp_data_blob_handler_free(cd->model_handler); rfree(cd->p_handle); rfree(cd); - rfree(dev); -} - -static int32_t igo_nr_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - int32_t ret; - - comp_dbg(dev, "igo_nr_verify_params()"); - - /* update downstream (playback) or upstream (capture) buffer parameters - */ - ret = comp_verify_params(dev, BUFF_PARAMS_RATE, params); - if (ret < 0) - comp_err(dev, "igo_nr_verify_params(): comp_verify_params() failed."); - - return ret; + return 0; } -/* set component audio stream parameters */ -static int32_t igo_nr_params(struct comp_dev *dev, - struct sof_ipc_stream_params *pcm_params) +/* check component audio stream parameters */ +static int32_t igo_nr_check_params(struct processing_module *mod, struct sof_source *source, + struct sof_sink *sink) { - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sinkb, *sourceb; - int32_t err; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; - comp_info(dev, "igo_nr_params()"); - - err = igo_nr_verify_params(dev, pcm_params); - if (err < 0) { - comp_err(dev, "igo_nr_params(): pcm params verification failed."); - return err; - } - - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); + comp_info(dev, "igo_nr_check_params()"); /* set source/sink_frames/rate */ - cd->source_rate = audio_stream_get_rate(&sourceb->stream); - cd->sink_rate = audio_stream_get_rate(&sinkb->stream); + cd->source_rate = source_get_rate(source); + cd->sink_rate = sink_get_rate(sink); - if (audio_stream_get_channels(&sourceb->stream) != - audio_stream_get_channels(&sinkb->stream)) { - comp_err(dev, "igo_nr_params(), mismatch source/sink stream channels"); + if (source_get_channels(source) != sink_get_channels(sink)) { + comp_err(dev, "igo_nr_check_params(), mismatch source/sink stream channels"); cd->invalid_param = true; } if (!cd->sink_rate) { - comp_err(dev, "igo_nr_params(), zero sink rate"); + comp_err(dev, "igo_nr_check_params(), zero sink rate"); return -EINVAL; } - cd->sink_frames = dev->frames; - cd->source_frames = ceil_divide(dev->frames * cd->source_rate, - cd->sink_rate); - - /* Use empirical add +10 for target frames number to avoid xruns and - * distorted audio in beginning of streaming. It's slightly more than - * min. needed and does not increase much peak load and buffer memory - * consumption. The copy() function will find the limits and process - * less frames after the buffers levels stabilize. - */ - cd->source_frames_max = cd->source_frames + 10; - cd->sink_frames_max = cd->sink_frames + 10; - cd->frames = MAX(cd->source_frames_max, cd->sink_frames_max); - - comp_dbg(dev, "igo_nr_params(), source_rate=%u, sink_rate=%u, source_frames_max=%d, sink_frames_max=%d", - cd->source_rate, cd->sink_rate, - cd->source_frames_max, cd->sink_frames_max); - /* The igo_nr supports sample rate 48000 only. */ switch (cd->source_rate) { case 48000: - comp_info(dev, "igo_nr_params(), sample rate = 48000"); + comp_info(dev, "igo_nr_check_params(), sample rate = 48000"); cd->invalid_param = false; break; default: - comp_err(dev, "igo_nr_params(), invalid sample rate"); + comp_err(dev, "igo_nr_check_params(), invalid sample rate"); cd->invalid_param = true; } @@ -457,94 +546,64 @@ static int32_t igo_nr_check_config_validity(struct comp_dev *dev, } } -#if CONFIG_IPC_MAJOR_3 -static inline void igo_nr_set_chan_process(struct comp_dev *dev, int32_t chan) +static inline void igo_nr_set_chan_process(struct comp_data *cd, int32_t chan) { - struct comp_data *cd = comp_get_drvdata(dev); - if (!cd->process_enable[chan]) cd->process_enable[chan] = true; } -static inline void igo_nr_set_chan_passthrough(struct comp_dev *dev, int32_t chan) +static inline void igo_nr_set_chan_passthrough(struct comp_data *cd, int32_t chan) { - struct comp_data *cd = comp_get_drvdata(dev); - if (cd->process_enable[chan]) { cd->process_enable[chan] = false; IgoLibInit(cd->p_handle, &cd->igo_lib_config, &cd->config.igo_params); } } -static int32_t igo_nr_cmd_get_data(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata, - int32_t max_size) +static int igo_nr_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) { - struct comp_data *cd = comp_get_drvdata(dev); - int32_t ret; - - switch (cdata->cmd) { - case SOF_CTRL_CMD_BINARY: - comp_info(dev, "igo_nr_cmd_get_data(), SOF_CTRL_CMD_BINARY"); - ret = comp_data_blob_get_cmd(cd->model_handler, cdata, max_size); - break; - default: - comp_err(dev, "igo_nr_cmd_get_data() error: invalid cdata->cmd %u", cdata->cmd); - ret = -EINVAL; - break; - } - return ret; -} + struct comp_dev *dev = mod->dev; -static int32_t igo_nr_cmd_get_value(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int32_t j; - int32_t ret = 0; +#if CONFIG_IPC_MAJOR_3 + struct comp_data *cd = module_get_private_data(mod); + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + int j; switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + comp_info(dev, "igo_nr_get_config(), SOF_CTRL_CMD_BINARY"); + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); case SOF_CTRL_CMD_SWITCH: for (j = 0; j < cdata->num_elems; j++) { cdata->chanv[j].channel = j; cdata->chanv[j].value = cd->process_enable[j]; - comp_info(dev, "igo_nr_cmd_get_value(), channel = %u, value = %u", + comp_info(dev, "igo_nr_get_config(), channel = %u, value = %u", cdata->chanv[j].channel, cdata->chanv[j].value); } - break; - default: - comp_err(dev, "igo_nr_cmd_get_value() error: invalid cdata->cmd %d", cdata->cmd); - ret = -EINVAL; - break; - } - return ret; -} - -static int32_t igo_nr_cmd_set_data(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int32_t ret; - - switch (cdata->cmd) { - case SOF_CTRL_CMD_BINARY: - comp_info(dev, "igo_nr_cmd_set_data(), SOF_CTRL_CMD_BINARY"); - ret = comp_data_blob_set_cmd(cd->model_handler, cdata); - break; + return 0; default: - comp_err(dev, "igo_nr_cmd_set_data() error: invalid cdata->cmd"); - ret = -EINVAL; - break; + comp_err(dev, "igo_nr_cmd_get_config() error: invalid cdata->cmd %d", cdata->cmd); + return -EINVAL; } - if (ret >= 0) - ret = igo_nr_check_config_validity(dev, cd); - - return ret; +#elif CONFIG_IPC_MAJOR_4 + comp_err(dev, "igo_nr_cmd_get_config() error: not supported"); + return -EINVAL; +#endif } -static int32_t igo_nr_set_chan(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) +static int32_t igo_nr_set_chan(struct processing_module *mod, void *data) { +#if CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = data; +#elif CONFIG_IPC_MAJOR_4 + struct sof_ipc4_control_msg_payload *cdata = data; +#endif + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; uint32_t val; int32_t ch; int32_t j; @@ -559,85 +618,72 @@ static int32_t igo_nr_set_chan(struct comp_dev *dev, struct sof_ipc_ctrl_data *c } if (val) - igo_nr_set_chan_process(dev, ch); + igo_nr_set_chan_process(cd, ch); else - igo_nr_set_chan_passthrough(dev, ch); + igo_nr_set_chan_passthrough(cd, ch); } return 0; } -static int32_t igo_nr_cmd_set_value(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) +static int igo_nr_set_config(struct processing_module *mod, uint32_t param_id, + enum module_cfg_fragment_position pos, + uint32_t data_offset_size, const uint8_t *fragment, + size_t fragment_size, uint8_t *response, + size_t response_size) { - int32_t ret; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret; + + comp_info(dev, "igo_nr_set_config()"); + +#if CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + comp_info(dev, "igo_nr_cmd_set_config(), SOF_CTRL_CMD_BINARY"); + ret = comp_data_blob_set(cd->model_handler, pos, data_offset_size, + fragment, fragment_size); + if (ret >= 0) + ret = igo_nr_check_config_validity(dev, cd); + + return ret; case SOF_CTRL_CMD_SWITCH: - comp_dbg(dev, "igo_nr_cmd_set_value(), SOF_CTRL_CMD_SWITCH, cdata->comp_id = %u", + comp_dbg(dev, "igo_nr_cmd_set_config(), SOF_CTRL_CMD_SWITCH, cdata->comp_id = %u", cdata->comp_id); - ret = igo_nr_set_chan(dev, cdata); - break; + return igo_nr_set_chan(mod, cdata); default: - comp_err(dev, "igo_nr_cmd_set_value() error: invalid cdata->cmd"); - ret = -EINVAL; - break; + comp_err(dev, "igo_nr_cmd_set_config() error: invalid cdata->cmd"); + return -EINVAL; } - - return ret; -} - -/* used to pass standard and bespoke commands (with data) to component */ -static int32_t igo_nr_cmd(struct comp_dev *dev, - int32_t cmd, - void *data, - int32_t max_data_size) -{ - struct sof_ipc_ctrl_data *cdata = data; - - comp_info(dev, "igo_nr_cmd()"); - - switch (cmd) { - case COMP_CMD_SET_DATA: - return igo_nr_cmd_set_data(dev, cdata); - case COMP_CMD_GET_DATA: - return igo_nr_cmd_get_data(dev, cdata, max_data_size); - case COMP_CMD_SET_VALUE: - return igo_nr_cmd_set_value(dev, cdata); - case COMP_CMD_GET_VALUE: - return igo_nr_cmd_get_value(dev, cdata); - default: - comp_err(dev, "igo_nr_cmd() error: invalid command"); +#elif CONFIG_IPC_MAJOR_4 + struct sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + comp_info(dev, "igo_nr_cmd_set_config(), SOF_IPC4_SWITCH_CONTROL_PARAM_ID"); + return igo_nr_set_chan(mod, ctl); + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + comp_err(dev, "igo_nr_set_config(), illegal control."); return -EINVAL; } -} -#endif -static void igo_nr_process(struct comp_dev *dev, - struct comp_buffer *source, - struct comp_buffer *sink, - struct comp_copy_limits *cl, - int32_t frames) - -{ - struct comp_data *cd = comp_get_drvdata(dev); - uint32_t source_bytes = frames * cl->source_frame_bytes; - uint32_t sink_bytes = frames * cl->sink_frame_bytes; - - buffer_stream_invalidate(source, source_bytes); - - cd->igo_nr_func(cd, &source->stream, &sink->stream, frames); - - buffer_stream_writeback(sink, sink_bytes); + comp_info(dev, "igo_nr_cmd_set_config(), bytes"); + ret = comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, fragment_size); + if (ret >= 0) + ret = igo_nr_check_config_validity(dev, cd); - /* calc new free and available */ - comp_update_buffer_consume(source, source_bytes); - comp_update_buffer_produce(sink, sink_bytes); + return ret; +#endif } -static void igo_nr_print_config(struct comp_dev *dev) +static void igo_nr_print_config(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; comp_dbg(dev, " igo_params_ver %d", cd->config.igo_params.igo_params_ver); @@ -676,10 +722,11 @@ static void igo_nr_print_config(struct comp_dev *dev) } -static void igo_nr_set_igo_params(struct comp_dev *dev) +static void igo_nr_set_igo_params(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); struct sof_igo_nr_config *p_config = comp_get_data_blob(cd->model_handler, NULL, NULL); + struct comp_dev *dev = mod->dev; comp_info(dev, "igo_nr_set_igo_params()"); igo_nr_check_config_validity(dev, cd); @@ -687,48 +734,44 @@ static void igo_nr_set_igo_params(struct comp_dev *dev) if (p_config) { comp_info(dev, "New config detected."); cd->config = *p_config; - igo_nr_print_config(dev); + igo_nr_print_config(mod); } } /* copy and process stream data from source to sink buffers */ -static int32_t igo_nr_copy(struct comp_dev *dev) +static int igo_nr_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { - struct comp_copy_limits cl; - struct comp_buffer *sourceb, *sinkb; - struct comp_data *cd = comp_get_drvdata(dev); - int32_t src_frames; - int32_t sink_frames; + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); + struct sof_source *source = sources[0]; + struct sof_sink *sink = sinks[0]; + int ret; comp_dbg(dev, "igo_nr_copy()"); - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); + /* Process only when frames count is enough. */ + if (source_get_data_frames_available(source) < IGO_FRAME_SIZE || + sink_get_free_frames(sink) < IGO_FRAME_SIZE) { + comp_warn(dev, "No data to process."); + return 0; + } /* Check for changed configuration */ if (comp_is_new_data_blob_available(cd->model_handler)) - igo_nr_set_igo_params(dev); - - /* Get source, sink, number of frames etc. to process. */ - comp_get_copy_limits(sourceb, sinkb, &cl); - - src_frames = audio_stream_get_avail_frames(&sourceb->stream); - sink_frames = audio_stream_get_free_frames(&sinkb->stream); + igo_nr_set_igo_params(mod); - comp_dbg(dev, "src_frames = %d, sink_frames = %d.", src_frames, sink_frames); + ret = cd->igo_nr_func(cd, source, sink, IGO_FRAME_SIZE); + if (ret) + comp_err(dev, "Failed process."); - /* Process only when frames count is enough. */ - if (src_frames >= IGO_FRAME_SIZE && sink_frames >= IGO_FRAME_SIZE) - igo_nr_process(dev, sourceb, sinkb, &cl, IGO_FRAME_SIZE); - - return 0; + return ret; } -static void igo_nr_lib_init(struct comp_dev *dev) +static void igo_nr_lib_init(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); cd->igo_lib_config.algo_name = "igo_nr"; cd->igo_lib_config.in_ch_num = 1; @@ -752,97 +795,100 @@ static void igo_nr_lib_init(struct comp_dev *dev) cd->igo_stream_data_out.sampling_rate = 48000; } -static int32_t igo_nr_prepare(struct comp_dev *dev) +#if CONFIG_IPC_MAJOR_4 +static int igo_nr_ipc4_params(struct processing_module *mod, struct sof_source *source, + struct sof_sink *sink) { - struct comp_data *cd = comp_get_drvdata(dev); - int32_t ret; + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_dev *dev = mod->dev; + int ret; + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + component_set_nearest_period_frames(dev, params->rate); + ret = source_set_params(source, params, true); + if (ret) + return ret; - comp_dbg(dev, "igo_nr_prepare()"); + return sink_set_params(sink, params, true); +} +#endif /* CONFIG_IPC_MAJOR_4 */ - igo_nr_set_igo_params(dev); +static int32_t igo_nr_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); + struct sof_source *source = sources[0]; + struct sof_sink *sink = sinks[0]; + int ret; - igo_nr_lib_init(dev); + comp_dbg(dev, "igo_nr_prepare()"); - comp_dbg(dev, "post igo_nr_lib_init"); - igo_nr_print_config(dev); +#if CONFIG_IPC_MAJOR_4 + ret = igo_nr_ipc4_params(mod, source, sink); + if (ret) { + comp_err(dev, "Failed to set source or and sink parameters."); + return ret; + } +#endif - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); - if (ret < 0) + ret = igo_nr_check_params(mod, source, sink); + if (ret) return ret; - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; + source_set_alignment_constants(source, 1, IGO_FRAME_SIZE); + sink_set_alignment_constants(sink, 1, IGO_FRAME_SIZE); + + igo_nr_set_igo_params(mod); + + igo_nr_lib_init(mod); + + comp_dbg(dev, "post igo_nr_lib_init"); + igo_nr_print_config(mod); /* Clear in/out buffers */ memset(cd->in, 0, IGO_NR_IN_BUF_LENGTH * sizeof(int16_t)); memset(cd->out, 0, IGO_NR_OUT_BUF_LENGTH * sizeof(int16_t)); - /* Default NR on */ + /* Default NR on + * + * Note: There is a race condition with this switch control set and kernel set + * ALSA switch control if such is defined in topology. This set overrides kernel + * SOF driver set for control since it happens just after component init. The + * user needs to re-apply the control to get expected operation. The owner of + * this component should check if this is desired operation. A possible fix would + * be set here only if kernel has not applied the switch control. + */ cd->process_enable[cd->config.active_channel_idx] = true; - return set_capture_func(dev); + return set_capture_func(mod); } -static int32_t igo_nr_reset(struct comp_dev *dev) +static int igo_nr_reset(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); - comp_info(dev, "igo_nr_reset()"); + comp_info(mod->dev, "igo_nr_reset()"); cd->igo_nr_func = NULL; cd->source_rate = 0; cd->sink_rate = 0; - cd->source_frames = 0; - cd->sink_frames = 0; - cd->source_frames_max = 0; - cd->sink_frames_max = 0; - cd->frames = 0; cd->invalid_param = false; - comp_set_state(dev, COMP_TRIGGER_RESET); return 0; } -static int32_t igo_nr_trigger(struct comp_dev *dev, int32_t cmd) -{ - int32_t ret; - - comp_info(dev, "igo_nr_trigger(), command = %u", cmd); - - ret = comp_set_state(dev, cmd); - if (ret == COMP_STATUS_STATE_ALREADY_SET) - ret = PPL_STATUS_PATH_STOP; - - return ret; -} - -static const struct comp_driver comp_igo_nr = { - .uid = SOF_RT_UUID(igo_nr_uuid), - .tctx = &igo_nr_tr, - .ops = { - .create = igo_nr_new, - .free = igo_nr_free, - .params = igo_nr_params, -#if CONFIG_IPC_MAJOR_3 - .cmd = igo_nr_cmd, -#endif - .copy = igo_nr_copy, - .prepare = igo_nr_prepare, - .reset = igo_nr_reset, - .trigger = igo_nr_trigger, - }, -}; - -static SHARED_DATA struct comp_driver_info comp_igo_nr_info = { - .drv = &comp_igo_nr, +static const struct module_interface igo_nr_interface = { + .init = igo_nr_init, + .prepare = igo_nr_prepare, + .process = igo_nr_process, + .set_configuration = igo_nr_set_config, + .get_configuration = igo_nr_get_config, + .reset = igo_nr_reset, + .free = igo_nr_free }; -UT_STATIC void sys_comp_igo_nr_init(void) -{ - comp_register(platform_shared_get(&comp_igo_nr_info, - sizeof(comp_igo_nr_info))); -} - -DECLARE_MODULE(sys_comp_igo_nr_init); -SOF_MODULE_INIT(igo_nr, sys_comp_igo_nr_init); +DECLARE_MODULE_ADAPTER(igo_nr_interface, igo_nr_uuid, igo_nr_tr); +SOF_MODULE_INIT(igo_nr, sys_comp_module_igo_nr_interface_init); diff --git a/src/audio/igo_nr/igo_nr.toml b/src/audio/igo_nr/igo_nr.toml new file mode 100644 index 000000000000..926b3cef063f --- /dev/null +++ b/src/audio/igo_nr/igo_nr.toml @@ -0,0 +1,18 @@ + + // IGO_NR module config + [[module.entry]] + name = "IGO_NR" + uuid = "696AE2BC-2877-11EB-ADC1-0242AC120002" + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = "0" + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + // pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + // mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] + mod_cfg = [0, 0, 0, 0, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/igo_nr/igo_nr_stub.c b/src/audio/igo_nr/igo_nr_stub.c index 12882740de63..ae027f6ef7f4 100644 --- a/src/audio/igo_nr/igo_nr_stub.c +++ b/src/audio/igo_nr/igo_nr_stub.c @@ -6,8 +6,15 @@ #include +/* Set handle_size to Just something instead of 0 from rzalloc() of + * component data to avoid rballoc() in igo_nr_init() to fail. + */ +#define IGO_NR_STUB_HANDLE_SIZE 42 + enum IgoRet IgoLibGetInfo(struct IgoLibInfo *info) { + info->handle_size = IGO_NR_STUB_HANDLE_SIZE; + return IGO_RET_OK; } diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 667cd00007d6..9f427cccb6ed 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -707,6 +707,7 @@ void sys_comp_module_dts_interface_init(void); void sys_comp_module_eq_fir_interface_init(void); void sys_comp_module_eq_iir_interface_init(void); void sys_comp_module_google_rtc_audio_processing_interface_init(void); +void sys_comp_module_igo_nr_interface_init(void); void sys_comp_module_mfcc_interface_init(void); void sys_comp_module_mixer_interface_init(void); void sys_comp_module_multiband_drc_interface_init(void); diff --git a/src/include/sof/audio/igo_nr/igo_nr_comp.h b/src/include/sof/audio/igo_nr/igo_nr_comp.h index 64c663a99944..82bf9f2d3771 100644 --- a/src/include/sof/audio/igo_nr/igo_nr_comp.h +++ b/src/include/sof/audio/igo_nr/igo_nr_comp.h @@ -35,15 +35,10 @@ struct comp_data { uint32_t source_rate; /* Sample rate in Hz */ uint32_t sink_format; /* For used PCM sample format */ uint32_t source_format; /* For used PCM sample format */ - int32_t source_frames; /* Nominal # of frames to process at source */ - int32_t sink_frames; /* Nominal # of frames to process at sink */ - int32_t source_frames_max; /* Max # of frames to process at source */ - int32_t sink_frames_max; /* Max # of frames to process at sink */ - int32_t frames; /* IO buffer length */ - void (*igo_nr_func)(struct comp_data *cd, - const struct audio_stream *source, - struct audio_stream *sink, - int32_t frames); + int (*igo_nr_func)(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink, + int32_t frames); }; #endif /* __SOF_AUDIO_IGO_NR_CONFIG_H__ */ diff --git a/tools/rimage/config/lnl.toml b/tools/rimage/config/lnl.toml index 4af33a2b365f..e626adadb722 100644 --- a/tools/rimage/config/lnl.toml +++ b/tools/rimage/config/lnl.toml @@ -56,7 +56,7 @@ name = "ADSPFW" load_offset = "0x40000" [module] -count = 26 +count = 27 [[module.entry]] name = "BRNGUP" uuid = "2B79E4F3-4675-F649-89DF-3BC194A91AEB" @@ -601,3 +601,19 @@ count = 26 pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] mod_cfg = [0, 0, 0, 0, 4096, 1000000, 128, 128, 0, 0, 0] + + # IGO_NR module config + [[module.entry]] + name = "IGO_NR" + uuid = "696AE2BC-2877-11EB-ADC1-0242AC120002" + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = "0" + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] + mod_cfg = [0, 0, 0, 0, 4096, 1000000, 128, 128, 0, 0, 0] diff --git a/tools/rimage/config/mtl.toml.h b/tools/rimage/config/mtl.toml.h index efe33899e71f..d8b872ce4f8d 100644 --- a/tools/rimage/config/mtl.toml.h +++ b/tools/rimage/config/mtl.toml.h @@ -181,5 +181,9 @@ load_offset = "0x40000" #include