From 76a376eb0ec47ea6cc4c29d068b3f2a6a0745883 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Mon, 25 Apr 2022 14:56:18 +0200 Subject: [PATCH] zephyr: alh: add ALH zephyr driver Rename dai funcs, add zephyr alh driver, add get_stream_id to dai driver Switch to ALH zephyr driver in zephyr build Signed-off-by: Adrian Bonislawski --- src/audio/dai.c | 14 +-- src/drivers/intel/CMakeLists.txt | 2 +- src/drivers/intel/alh/CMakeLists.txt | 3 + src/drivers/intel/alh/alh-zephyr.c | 156 +++++++++++++++++++++++++++ src/drivers/intel/{ => alh}/alh.c | 8 ++ src/include/sof/lib/dai.h | 21 +++- src/ipc/ipc4/dai.c | 7 +- src/lib/dai.c | 46 +++++++- src/platform/intel/cavs/lib/dai.c | 18 ++++ zephyr/CMakeLists.txt | 8 +- 10 files changed, 261 insertions(+), 22 deletions(-) create mode 100755 src/drivers/intel/alh/CMakeLists.txt create mode 100755 src/drivers/intel/alh/alh-zephyr.c rename src/drivers/intel/{ => alh}/alh.c (95%) diff --git a/src/audio/dai.c b/src/audio/dai.c index c2a3e8eb3eff..e8210d801f72 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -95,7 +95,7 @@ static void dai_dma_cb(void *arg, enum notify_id type, void *data) /* stop dma copy for pause/stop/xrun */ if (dev->state != COMP_STATE_ACTIVE || dd->xrun) { /* stop the DAI */ - dai_trigger(dd->dai, COMP_TRIGGER_STOP, dev->direction); + dai_trigger_sof(dd->dai, COMP_TRIGGER_STOP, dev->direction); /* tell DMA not to reload */ next->status = DMA_CB_STATUS_END; @@ -730,7 +730,7 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) if (ret < 0) return ret; /* start the DAI */ - dai_trigger(dd->dai, cmd, dev->direction); + dai_trigger_sof(dd->dai, cmd, dev->direction); } else { dd->xrun = 0; } @@ -753,7 +753,7 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) return ret; /* start the DAI */ - dai_trigger(dd->dai, cmd, dev->direction); + dai_trigger_sof(dd->dai, cmd, dev->direction); ret = dma_start(dd->chan); if (ret < 0) return ret; @@ -780,16 +780,16 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) */ #if CONFIG_DMA_SUSPEND_DRAIN ret = dma_stop(dd->chan); - dai_trigger(dd->dai, cmd, dev->direction); + dai_trigger_sof(dd->dai, cmd, dev->direction); #else - dai_trigger(dd->dai, cmd, dev->direction); + dai_trigger_sof(dd->dai, cmd, dev->direction); ret = dma_stop(dd->chan); #endif break; case COMP_TRIGGER_PAUSE: comp_dbg(dev, "dai_comp_trigger_internal(), PAUSE"); ret = dma_pause(dd->chan); - dai_trigger(dd->dai, cmd, dev->direction); + dai_trigger_sof(dd->dai, cmd, dev->direction); break; case COMP_TRIGGER_PRE_START: case COMP_TRIGGER_PRE_RELEASE: @@ -797,7 +797,7 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) if (dd->xrun) dd->xrun = 0; else - dai_trigger(dd->dai, cmd, dev->direction); + dai_trigger_sof(dd->dai, cmd, dev->direction); break; } diff --git a/src/drivers/intel/CMakeLists.txt b/src/drivers/intel/CMakeLists.txt index 265369dbed72..f5c82aea7bc8 100644 --- a/src/drivers/intel/CMakeLists.txt +++ b/src/drivers/intel/CMakeLists.txt @@ -18,7 +18,7 @@ if(CONFIG_INTEL_SSP) endif() if(CONFIG_INTEL_ALH) - add_local_sources(sof alh.c) + add_subdirectory(alh) endif() if(CONFIG_INTEL_DMIC) diff --git a/src/drivers/intel/alh/CMakeLists.txt b/src/drivers/intel/alh/CMakeLists.txt new file mode 100755 index 000000000000..3bb3eb4d1ac4 --- /dev/null +++ b/src/drivers/intel/alh/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof alh.c) diff --git a/src/drivers/intel/alh/alh-zephyr.c b/src/drivers/intel/alh/alh-zephyr.c new file mode 100755 index 000000000000..eaa7af0c3779 --- /dev/null +++ b/src/drivers/intel/alh/alh-zephyr.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Adrian Bonislawski + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* zephyr dai driver */ +#include + +/* a8e4218c-e863-4c93-84e7-5c27d2504501 */ +DECLARE_SOF_UUID("alh-dai", alh_uuid, 0xa8e4218c, 0xe863, 0x4c93, + 0x84, 0xe7, 0x5c, 0x27, 0xd2, 0x50, 0x45, 0x01); + +DECLARE_TR_CTX(alh_tr, SOF_UUID(alh_uuid), LOG_LEVEL_INFO); + +static int alh_trigger_zephyr(struct dai *dai, int cmd, int direction) +{ + enum dai_trigger_cmd cmd_z; + + switch(cmd) { + case COMP_TRIGGER_STOP: + cmd_z = DAI_TRIGGER_STOP; + break; + case COMP_TRIGGER_START: + case COMP_TRIGGER_RELEASE: + cmd_z = DAI_TRIGGER_START; + break; + case COMP_TRIGGER_PAUSE: + cmd_z = DAI_TRIGGER_PAUSE; + break; + case COMP_TRIGGER_PRE_START: + case COMP_TRIGGER_PRE_RELEASE: + cmd_z = DAI_TRIGGER_PRE_START; + break; + default: + return -EINVAL; + } + + return dai_trigger(dai->z_drv, direction, cmd_z); +} + +static int alh_set_config_zephyr(struct dai *dai, struct ipc_config_dai *common_config, + void *spec_config) +{ + struct sof_ipc_dai_config *sof_cfg; + struct dai_config cfg; + + sof_cfg = (struct sof_ipc_dai_config *)spec_config; + cfg.dai_index = common_config->dai_index; + cfg.format = sof_cfg->format; + cfg.options = sof_cfg->flags; + + if(common_config->is_config_blob) { + cfg.type = DAI_INTEL_ALH_NHLT; + return dai_config_set(dai->z_drv, &cfg, spec_config); + } else { + cfg.type = DAI_INTEL_ALH; + return dai_config_set(dai->z_drv, &cfg, &sof_cfg->alh); + } +} + +static int alh_get_hw_params_zephyr(struct dai *dai, struct sof_ipc_stream_params *params, int dir) +{ + const struct dai_config *cfg; + + cfg = dai_config_get(dai->z_drv, dir); + + params->rate = cfg->rate; + params->buffer_fmt = 0; + params->channels = cfg->channels; + + switch (cfg->word_size) { + case 16: + params->frame_fmt = SOF_IPC_FRAME_S16_LE; + break; + case 24: + params->frame_fmt = SOF_IPC_FRAME_S24_4LE; + break; + case 32: + params->frame_fmt = SOF_IPC_FRAME_S32_LE; + break; + default: + dai_warn(dai,"%d not supported format", cfg->word_size); + } + + return 0; +} + +static int alh_get_handshake_zephyr(struct dai *dai, int direction, int stream_id) +{ + const struct dai_properties *props; + + props = dai_get_properties(dai->z_drv, direction, stream_id); + + return props->dma_hs_id; +} + +static int alh_get_fifo_zephyr(struct dai *dai, int direction, int stream_id) +{ + const struct dai_properties *props; + + props = dai_get_properties(dai->z_drv, direction, stream_id); + + return props->fifo_address; +} + +static int alh_get_stream_id_zephyr(struct dai *dai, int direction) +{ + const struct dai_properties *props; + + props = dai_get_properties(dai->z_drv, direction, 0); + + return props->stream_id; +} + +static int alh_probe_zephyr(struct dai *dai) +{ + return dai_probe(dai->z_drv); +} + +static int alh_remove_zephyr(struct dai *dai) +{ + return dai_remove(dai->z_drv); +} + +const struct dai_driver alh_driver = { + .type = SOF_DAI_INTEL_ALH, + .uid = SOF_UUID(alh_uuid), + .tctx = &alh_tr, + .dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP, + .dma_dev = DMA_DEV_ALH, + .ops = { + .trigger = alh_trigger_zephyr, + .set_config = alh_set_config_zephyr, + .get_hw_params = alh_get_hw_params_zephyr, + .get_handshake = alh_get_handshake_zephyr, + .get_fifo = alh_get_fifo_zephyr, + .get_stream_id = alh_get_stream_id_zephyr, + .probe = alh_probe_zephyr, + .remove = alh_remove_zephyr, + }, +}; diff --git a/src/drivers/intel/alh.c b/src/drivers/intel/alh/alh.c similarity index 95% rename from src/drivers/intel/alh.c rename to src/drivers/intel/alh/alh.c index 99d99409bbf0..295dbe59c4eb 100644 --- a/src/drivers/intel/alh.c +++ b/src/drivers/intel/alh/alh.c @@ -144,6 +144,13 @@ static int alh_get_fifo(struct dai *dai, int direction, int stream_id) return ALH_BASE + offset + ALH_STREAM_OFFSET * stream_id; } +static int alh_get_stream_id(struct dai *dai, int direction) +{ + struct alh_pdata *alh = dai_get_drvdata(dai); + + return alh->params.stream_id; +} + const struct dai_driver alh_driver = { .type = SOF_DAI_INTEL_ALH, .uid = SOF_UUID(alh_uuid), @@ -156,6 +163,7 @@ const struct dai_driver alh_driver = { .get_hw_params = alh_get_hw_params, .get_handshake = alh_get_handshake, .get_fifo = alh_get_fifo, + .get_stream_id = alh_get_stream_id, .probe = alh_probe, .remove = alh_remove, }, diff --git a/src/include/sof/lib/dai.h b/src/include/sof/lib/dai.h index 39e552648106..f1fe9a52da9d 100644 --- a/src/include/sof/lib/dai.h +++ b/src/include/sof/lib/dai.h @@ -32,6 +32,9 @@ #include #include #include +#ifdef __ZEPHYR__ +#include +#endif struct dai; struct sof_ipc_stream_params; @@ -82,6 +85,7 @@ struct dai_ops { int (*hw_params)(struct dai *dai, struct sof_ipc_stream_params *params); int (*get_handshake)(struct dai *dai, int direction, int stream_id); int (*get_fifo)(struct dai *dai, int direction, int stream_id); + int (*get_stream_id)(struct dai *dai, int direction); int (*probe)(struct dai *dai); int (*remove)(struct dai *dai); uint32_t (*get_init_delay_ms)(struct dai *dai); @@ -194,6 +198,9 @@ struct dai { int sref; /**< simple ref counter, guarded by lock */ struct dai_plat_data plat_data; const struct dai_driver *drv; +#ifdef __ZEPHYR__ + const struct device *z_drv; +#endif void *priv_data; }; @@ -376,7 +383,7 @@ static inline int dai_set_config(struct dai *dai, struct ipc_config_dai *config, /** * \brief Digital Audio interface trigger */ -static inline int dai_trigger(struct dai *dai, int cmd, int direction) +static inline int dai_trigger_sof(struct dai *dai, int cmd, int direction) { return dai->drv->ops.trigger(dai, cmd, direction); } @@ -421,10 +428,18 @@ static inline int dai_get_fifo(struct dai *dai, int direction, return dai->drv->ops.get_fifo(dai, direction, stream_id); } +static inline int dai_get_stream_id(struct dai *dai, int direction) +{ + if (dai->drv->ops.get_stream_id) + return dai->drv->ops.get_stream_id(dai, direction); + + return -1; +} + /** * \brief Digital Audio interface Probe */ -static inline int dai_probe(struct dai *dai) +static inline int dai_probe_sof(struct dai *dai) { return dai->drv->ops.probe(dai); } @@ -432,7 +447,7 @@ static inline int dai_probe(struct dai *dai) /** * \brief Digital Audio interface Remove */ -static inline int dai_remove(struct dai *dai) +static inline int dai_remove_sof(struct dai *dai) { return dai->drv->ops.remove(dai); } diff --git a/src/ipc/ipc4/dai.c b/src/ipc/ipc4/dai.c index 962606381aa1..7cfd1255bfd4 100644 --- a/src/ipc/ipc4/dai.c +++ b/src/ipc/ipc4/dai.c @@ -68,7 +68,6 @@ int ipc_dai_data_config(struct comp_dev *dev) struct ipc_config_dai *dai = &dd->ipc_config; struct ipc4_copier_module_cfg *copier_cfg; struct dai *dai_p = dd->dai; - struct alh_pdata *alh; if (!dai) { comp_err(dev, "dai_data_config(): no dai!\n"); @@ -100,20 +99,18 @@ int ipc_dai_data_config(struct comp_dev *dev) case SOF_DAI_INTEL_HDA: break; case SOF_DAI_INTEL_ALH: - alh = dai_get_drvdata(dai_p); /* SDW HW FIFO always requires 32bit MSB aligned sample data for * all formats, such as 8/16/24/32 bits. */ dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE; dd->dma_buffer->stream.frame_fmt = dev->ipc_config.frame_fmt; - dd->config.burst_elems = - dd->dai->plat_data.fifo[dai->direction].depth; + dd->config.burst_elems = ALH_GPDMA_BURST_LENGTH; /* As with HDA, the DMA channel is assigned in runtime, * not during topology parsing. */ - dd->stream_id = alh->params.stream_id; + dd->stream_id = dai_get_stream_id(dai_p, 0);//alh->params.stream_id; comp_dbg(dev, "dai_data_config() SOF_DAI_INTEL_ALH dd->dma_buffer->stream.frame_fmt %#x stream_id %d", dd->dma_buffer->stream.frame_fmt, dd->stream_id); diff --git a/src/lib/dai.c b/src/lib/dai.c index f64c60be21cd..dbc0bbc9c88c 100644 --- a/src/lib/dai.c +++ b/src/lib/dai.c @@ -134,6 +134,34 @@ static inline const struct dai_type_info *dai_find_type(uint32_t type) return NULL; } +#ifdef __ZEPHYR__ +struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) +{ + int ret = 0; + const struct dai_type_info *dti; + struct dai *d; + + dti = dai_find_type(type); + if (!dti) + return NULL; /* type not found */ + + for (d = dti->dai_array; d < dti->dai_array + dti->num_dais; d++) { + if (d->index != index) { + continue; + } + if (flags & DAI_CREAT) + ret = dai_probe_sof(d); + else + ret = -ENODEV; + + tr_info(&dai_tr, "dai_get type %d index %d", type, index); + + return !ret ? d : NULL; + } + tr_err(&dai_tr, "dai_get: type %d index %d not found", type, index); + return NULL; +} +#else struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) { int ret = 0; @@ -153,7 +181,7 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) key = k_spin_lock(&d->lock); if (d->sref == 0) { if (flags & DAI_CREAT) - ret = dai_probe(d); + ret = dai_probe_sof(d); else ret = -ENODEV; } @@ -170,7 +198,20 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) tr_err(&dai_tr, "dai_get: type %d index %d not found", type, index); return NULL; } +#endif + +#ifdef __ZEPHYR__ +void dai_put(struct dai *dai) +{ + int ret = dai_remove_sof(dai); + if (ret < 0) { + tr_err(&dai_tr, "dai_put: type %d index %d dai_remove() failed ret = %d", + dai->drv->type, dai->index, ret); + } + tr_info(&dai_tr, "dai_put type %d index %d", dai->drv->type, dai->index); +} +#else void dai_put(struct dai *dai) { int ret; @@ -178,7 +219,7 @@ void dai_put(struct dai *dai) key = k_spin_lock(&dai->lock); if (--dai->sref == 0) { - ret = dai_remove(dai); + ret = dai_remove_sof(dai); if (ret < 0) { tr_err(&dai_tr, "dai_put: type %d index %d dai_remove() failed ret = %d", dai->drv->type, dai->index, ret); @@ -188,3 +229,4 @@ void dai_put(struct dai *dai) dai->drv->type, dai->index, dai->sref); k_spin_unlock(&dai->lock, key); } +#endif diff --git a/src/platform/intel/cavs/lib/dai.c b/src/platform/intel/cavs/lib/dai.c index 9791e48b060a..309e02a1a03d 100644 --- a/src/platform/intel/cavs/lib/dai.c +++ b/src/platform/intel/cavs/lib/dai.c @@ -18,6 +18,9 @@ #include #include #include +#ifdef __ZEPHYR__ +#include +#endif #if CONFIG_INTEL_SSP @@ -212,7 +215,21 @@ int dai_init(struct sof *sof) dai[i].index = (i / DAI_NUM_ALH_BI_DIR_LINKS_GROUP) << 8 | (i % DAI_NUM_ALH_BI_DIR_LINKS_GROUP); dai[i].drv = &alh_driver; +#ifdef __ZEPHYR__ + switch (i) { + case 0: + dai[i].z_drv = device_get_binding("ALH_0"); + break; + case 1: + dai[i].z_drv = device_get_binding("ALH_1"); + break; + default: + continue; + } + if (!dai[i].z_drv) + return -EINVAL; +#else /* set burst length to align with DMAT value in the * Audio Link Hub. */ @@ -221,6 +238,7 @@ int dai_init(struct sof *sof) dai[i].plat_data.fifo[SOF_IPC_STREAM_CAPTURE].depth = ALH_GPDMA_BURST_LENGTH; k_spinlock_init(&dai[i].lock); +#endif } #endif diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 017bb7414ee3..d80bbc263f1f 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -161,7 +161,7 @@ if (CONFIG_SOC_SERIES_INTEL_CAVS_V15) ) zephyr_library_sources_ifdef(CONFIG_INTEL_ALH - ${SOF_DRIVERS_PATH}/intel/alh.c + ${SOF_DRIVERS_PATH}/intel/alh/alh.c ) zephyr_library_sources_ifdef(CONFIG_INTEL_DMIC @@ -227,7 +227,7 @@ if (CONFIG_SOC_SERIES_INTEL_CAVS_V18) ) zephyr_library_sources_ifdef(CONFIG_INTEL_ALH - ${SOF_DRIVERS_PATH}/intel/alh.c + ${SOF_DRIVERS_PATH}/intel/alh/alh.c ) zephyr_library_sources_ifdef(CONFIG_INTEL_DMIC @@ -295,7 +295,7 @@ if (CONFIG_SOC_SERIES_INTEL_CAVS_V20) ) zephyr_library_sources_ifdef(CONFIG_INTEL_ALH - ${SOF_DRIVERS_PATH}/intel/alh.c + ${SOF_DRIVERS_PATH}/intel/alh/alh.c ) zephyr_library_sources_ifdef(CONFIG_INTEL_DMIC @@ -363,7 +363,7 @@ if (CONFIG_SOC_SERIES_INTEL_CAVS_V25) ) zephyr_library_sources_ifdef(CONFIG_INTEL_ALH - ${SOF_DRIVERS_PATH}/intel/alh.c + ${SOF_DRIVERS_PATH}/intel/alh/alh-zephyr.c ) zephyr_library_sources_ifdef(CONFIG_INTEL_DMIC