diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 724155380ec6..17deceb5e081 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -495,7 +495,6 @@ static struct comp_dev *copier_new(const struct comp_driver *drv, struct ipc *ipc = ipc_get(); struct copier_data *cd; struct comp_dev *dev; - size_t size, config_size; int i; comp_cl_dbg(&comp_copier, "copier_new()"); @@ -506,17 +505,17 @@ static struct comp_dev *copier_new(const struct comp_driver *drv, dev->ipc_config = *config; - config_size = copier->gtw_cfg.config_length * sizeof(uint32_t); - dcache_invalidate_region((__sparse_force char __sparse_cache *)spec + sizeof(*copier), - config_size); - - size = sizeof(*cd); - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, size); + cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); if (!cd) goto error; - size = sizeof(*copier); - mailbox_hostbox_read(&cd->config, size, 0, size); + /* + * Don't copy the config_data[] variable size array, we don't need to + * store it, it's only used during IPC processing, besides we haven't + * allocated space for it, so don't "fix" this! + */ + if (memcpy_s(&cd->config, sizeof(cd->config), copier, sizeof(*copier)) < 0) + goto error_cd; for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++) cd->out_fmt[i] = cd->config.out_fmt; diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c index b1360a6e2d88..222171ea6917 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -22,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -192,36 +192,55 @@ static int dai_get_hw_params(struct dai *dai, struct sof_ipc_stream_params *par /* called from ipc/ipc3/dai.c */ int dai_get_handshake(struct dai *dai, int direction, int stream_id) { - const struct dai_properties *props = dai_get_properties(dai->dev, direction, stream_id); + k_spinlock_key_t key = k_spin_lock(&dai->lock); + const struct dai_properties *props = dai_get_properties(dai->dev, direction, + stream_id); + int hs_id = props->dma_hs_id; + + k_spin_unlock(&dai->lock, key); - return props->dma_hs_id; + return hs_id; } /* called from ipc/ipc3/dai.c and ipc/ipc4/dai.c */ int dai_get_fifo_depth(struct dai *dai, int direction) { const struct dai_properties *props; + k_spinlock_key_t key; + int fifo_depth; if (!dai) return 0; + key = k_spin_lock(&dai->lock); props = dai_get_properties(dai->dev, direction, 0); + fifo_depth = props->fifo_depth; + k_spin_unlock(&dai->lock, key); - return props->fifo_depth; + return fifo_depth; } int dai_get_stream_id(struct dai *dai, int direction) { + k_spinlock_key_t key = k_spin_lock(&dai->lock); const struct dai_properties *props = dai_get_properties(dai->dev, direction, 0); + int stream_id = props->stream_id; + + k_spin_unlock(&dai->lock, key); - return props->stream_id; + return stream_id; } static int dai_get_fifo(struct dai *dai, int direction, int stream_id) { - const struct dai_properties *props = dai_get_properties(dai->dev, direction, stream_id); + k_spinlock_key_t key = k_spin_lock(&dai->lock); + const struct dai_properties *props = dai_get_properties(dai->dev, direction, + stream_id); + int fifo_address = props->fifo_address; - return props->fifo_address; + k_spin_unlock(&dai->lock, key); + + return fifo_address; } /* this is called by DMA driver every time descriptor has completed */ @@ -340,6 +359,8 @@ static struct comp_dev *dai_new(const struct comp_driver *drv, goto error; } + k_spinlock_init(&dd->dai->lock); + dma_sg_init(&dd->config.elem_array); dd->xrun = 0; dd->chan = NULL; @@ -1398,13 +1419,18 @@ static int dai_ts_stop_op(struct comp_dev *dev) uint32_t dai_get_init_delay_ms(struct dai *dai) { const struct dai_properties *props; + k_spinlock_key_t key; + uint32_t init_delay; if (!dai) return 0; + key = k_spin_lock(&dai->lock); props = dai_get_properties(dai->dev, 0, 0); + init_delay = props->reg_init_delay; + k_spin_unlock(&dai->lock, key); - return props->reg_init_delay; + return init_delay; } static uint64_t dai_get_processed_data(struct comp_dev *dev, uint32_t stream_no, bool input) diff --git a/src/audio/pipeline/pipeline-stream.c b/src/audio/pipeline/pipeline-stream.c index 7c26da2f3d52..d69b676201e8 100644 --- a/src/audio/pipeline/pipeline-stream.c +++ b/src/audio/pipeline/pipeline-stream.c @@ -322,9 +322,20 @@ static int pipeline_comp_trigger(struct comp_dev *current, case COMP_TRIGGER_PRE_RELEASE: case COMP_TRIGGER_PRE_START: if (comp_get_endpoint_type(current) == COMP_ENDPOINT_DAI) { - struct dai_data *dd = comp_get_drvdata(current); - - ppl_data->delay_ms = dai_get_init_delay_ms(dd->dai); + /* + * Initialization delay is only used with SSP, where we + * don't use more than one DAI per copier + */ + struct comp_dev *dai = comp_get_dai(current, 0); + + if (dai) { + struct dai_data *dd = comp_get_drvdata(dai); + + ppl_data->delay_ms = dai_get_init_delay_ms(dd->dai); + } else { + /* Chain DMA case */ + ppl_data->delay_ms = 0; + } } break; default: diff --git a/src/include/ipc4/copier.h b/src/include/ipc4/copier.h index eacab733ffea..415a5cee8427 100644 --- a/src/include/ipc4/copier.h +++ b/src/include/ipc4/copier.h @@ -327,6 +327,11 @@ typedef void (* channel_copy_func)(struct audio_stream __sparse_cache *dst, int src_channel, int frame_count); struct copier_data { + /* + * struct ipc4_copier_module_cfg actually has variable size, but we + * don't need the variable size array at the end, we won't be copying it + * from the IPC data. + */ struct ipc4_copier_module_cfg config; struct comp_dev *endpoint[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT]; struct comp_buffer *endpoint_buffer[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT]; diff --git a/src/include/sof/audio/component_ext.h b/src/include/sof/audio/component_ext.h index a45c58f348aa..a3d10941b6b2 100644 --- a/src/include/sof/audio/component_ext.h +++ b/src/include/sof/audio/component_ext.h @@ -316,6 +316,26 @@ static inline int comp_get_endpoint_type(struct comp_dev *dev) } } +#if CONFIG_IPC_MAJOR_4 +#include +static inline struct comp_dev *comp_get_dai(struct comp_dev *parent, int index) +{ + struct copier_data *cd = comp_get_drvdata(parent); + + if (index >= ARRAY_SIZE(cd->endpoint)) + return NULL; + + return cd->endpoint[index]; +} +#elif CONFIG_IPC_MAJOR_3 +static inline struct comp_dev *comp_get_dai(struct comp_dev *parent, int index) +{ + return parent; +} +#else +#error Unknown IPC major version +#endif + /** * Called to check whether component schedules its pipeline. * @param dev Component device. diff --git a/src/include/sof/lib/dai-zephyr.h b/src/include/sof/lib/dai-zephyr.h index cca91170b891..6288011cece8 100644 --- a/src/include/sof/lib/dai-zephyr.h +++ b/src/include/sof/lib/dai-zephyr.h @@ -49,6 +49,7 @@ struct dai { uint32_t dma_dev; const struct device *dev; const struct dai_data *dd; + struct k_spinlock lock; /* protect properties */ }; struct timestamp_cfg {