Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions app/boards/imx8mp_evk_mimx8ml8_adsp_ipc4.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
CONFIG_IMX8M=y
CONFIG_HAVE_AGENT=n
CONFIG_FORMAT_CONVERT_HIFI3=n
CONFIG_KPB_FORCE_COPY_TYPE_NORMAL=n
CONFIG_DMA=y
CONFIG_DMA_NXP_SDMA=y
CONFIG_DAI_NXP_MICFIL=y
CONFIG_TRACE=n
CONFIG_SHARED_INTERRUPTS=y
CONFIG_ZEPHYR_NATIVE_DRIVERS=y
CONFIG_SAI_HAS_MCLK_CONFIG_OPTION=y
CONFIG_CLOCK_CONTROL_FIXED_RATE_CLOCK=y

# IPC4 overlay for i.MX8MP
CONFIG_IPC_MAJOR_4=y

# single core
CONFIG_CROSS_CORE_STREAM=n
CONFIG_COMP_PEAK_VOL=n
11 changes: 11 additions & 0 deletions app/boards/imx8qm_mek_mimx8qm6_adsp_ipc4.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# IPC4 overlay for i.MX8QM
CONFIG_IPC_MAJOR_4=y

# single core
CONFIG_CROSS_CORE_STREAM=n
CONFIG_COMP_PEAK_VOL=n

# no IPC4 trace window on i.MX
CONFIG_TRACE=n

# no SAI MCLK config here: codec MCLK comes from the SCU audio clock
11 changes: 11 additions & 0 deletions app/boards/imx8qxp_mek_mimx8qx6_adsp_ipc4.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# IPC4 overlay for i.MX8QXP
CONFIG_IPC_MAJOR_4=y

# single core
CONFIG_CROSS_CORE_STREAM=n
CONFIG_COMP_PEAK_VOL=n

# no IPC4 trace window on i.MX
CONFIG_TRACE=n

# no SAI MCLK config here: codec MCLK comes from the SCU audio clock
9 changes: 9 additions & 0 deletions app/boards/imx8ulp_evk_mimx8ud7_adsp_ipc4.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# IPC4 overlay for i.MX8ULP
CONFIG_IPC_MAJOR_4=y

# single core
CONFIG_CROSS_CORE_STREAM=n
CONFIG_COMP_PEAK_VOL=n

# no IPC4 trace window on i.MX
CONFIG_TRACE=n
9 changes: 9 additions & 0 deletions app/boards/imx95_evk_mimx9596_m7_ddr_ipc4.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# IPC4 overlay for i.MX95
CONFIG_IPC_MAJOR_4=y

# single core
CONFIG_CROSS_CORE_STREAM=n
CONFIG_COMP_PEAK_VOL=n

# no IPC4 trace window on i.MX
CONFIG_TRACE=n
54 changes: 53 additions & 1 deletion scripts/xtensa-build-zephyr.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class PlatformConfig:
RIMAGE_KEY: pathlib.Path = pathlib.Path(SOF_TOP, "keys", "otc_private_key_3k.pem")
aliases: list = dataclasses.field(default_factory=list)
ipc4: bool = False
extra_conf: pathlib.Path = None

# These cannot be built by everyone out of the box yet.
# For instance: there's no open-source toolchain available for them yet.
Expand Down Expand Up @@ -217,18 +218,48 @@ class PlatformConfig:
"hifi4_nxp_v5_3_1_prod",
RIMAGE_KEY = "key param ignored by imx8",
),
# i.MX8QM IPC4 build. Opt-in target; the default 'imx8' stays IPC3.
"imx8-ipc4" : PlatformConfig(
"imx", "imx8qm_mek/mimx8qm6/adsp",
f"RI-2023.11{xtensa_tools_version_postfix}",
"hifi4_nxp_v5_3_1_prod",
RIMAGE_KEY = "key param ignored by imx8",
ipc4 = True,
extra_conf = pathlib.Path(SOF_TOP, "app", "boards",
"imx8qm_mek_mimx8qm6_adsp_ipc4.conf")
),
"imx8x" : PlatformConfig(
"imx", "imx8qxp_mek/mimx8qx6/adsp",
f"RI-2023.11{xtensa_tools_version_postfix}",
"hifi4_nxp_v5_3_1_prod",
RIMAGE_KEY = "key param ignored by imx8x"
),
# i.MX8QXP IPC4 build. Opt-in target; the default 'imx8x' stays IPC3.
"imx8x-ipc4" : PlatformConfig(
"imx", "imx8qxp_mek/mimx8qx6/adsp",
f"RI-2023.11{xtensa_tools_version_postfix}",
"hifi4_nxp_v5_3_1_prod",
RIMAGE_KEY = "key param ignored by imx8x",
ipc4 = True,
extra_conf = pathlib.Path(SOF_TOP, "app", "boards",
"imx8qxp_mek_mimx8qx6_adsp_ipc4.conf")
),
"imx8m" : PlatformConfig(
"imx", "imx8mp_evk/mimx8ml8/adsp",
f"RI-2023.11{xtensa_tools_version_postfix}",
"hifi4_mscale_v2_0_2_prod",
RIMAGE_KEY = "key param ignored by imx8m"
),
# i.MX8MP IPC4 build. Opt-in target; the default 'imx8m' stays IPC3.
"imx8m-ipc4" : PlatformConfig(
"imx", "imx8mp_evk/mimx8ml8/adsp",
f"RI-2023.11{xtensa_tools_version_postfix}",
"hifi4_mscale_v2_0_2_prod",
RIMAGE_KEY = "key param ignored by imx8m",
ipc4 = True,
extra_conf = pathlib.Path(SOF_TOP, "app", "boards",
"imx8mp_evk_mimx8ml8_adsp_ipc4.conf")
),
"imx8m_cm7" : PlatformConfig(
"imx", "imx8mp_evk/mimx8ml8/m7/ddr",
"", "", "", ""
Expand All @@ -239,10 +270,28 @@ class PlatformConfig:
"hifi4_nxp2_s7_v2_1a_prod",
RIMAGE_KEY = "key param ignored by imx8ulp"
),
# i.MX8ULP IPC4 build. Opt-in target; the default 'imx8ulp' stays IPC3.
"imx8ulp-ipc4" : PlatformConfig(
"imx", "imx8ulp_evk/mimx8ud7/adsp",
f"RI-2023.11{xtensa_tools_version_postfix}",
"hifi4_nxp2_s7_v2_1a_prod",
RIMAGE_KEY = "key param ignored by imx8ulp",
ipc4 = True,
extra_conf = pathlib.Path(SOF_TOP, "app", "boards",
"imx8ulp_evk_mimx8ud7_adsp_ipc4.conf")
),
"imx95" : PlatformConfig(
"imx", "imx95_evk/mimx9596/m7/ddr",
"", "", "", ""
),
# i.MX95 IPC4 build. Opt-in target; the default 'imx95' stays IPC3.
"imx95-ipc4" : PlatformConfig(
"imx", "imx95_evk/mimx9596/m7/ddr",
"", "", "", "",
ipc4 = True,
extra_conf = pathlib.Path(SOF_TOP, "app", "boards",
"imx95_evk_mimx9596_m7_ddr_ipc4.conf")
),
"qemu_xtensa" : PlatformConfig(
"zephyr", "qemu_xtensa/dc233c",
"", "", "zephyr"
Expand Down Expand Up @@ -953,6 +1002,9 @@ def build_platforms():
if platf_build_environ.get("ZEPHYR_TOOLCHAIN_VARIANT") == 'xt-clang':
extra_conf_files.append(str(pathlib.Path(SOF_TOP, "app", "llext_relocatable.conf")))

if platform_dict.get("extra_conf"):
extra_conf_files.append(str(platform_dict["extra_conf"]))

if extra_conf_files:
extra_conf_files = ";".join(extra_conf_files)
build_cmd.append(f"-DEXTRA_CONF_FILE={extra_conf_files}")
Expand Down Expand Up @@ -1350,7 +1402,7 @@ def gzip_compress(fname, gzdst=None):
# Don't run sof_ri_info and ignore silently .ri files that don't have one.
RI_INFO_UNSUPPORTED = []

RI_INFO_UNSUPPORTED += ['imx8', 'imx8x', 'imx8m', 'imx8m_cm7', 'imx8ulp', 'imx95']
RI_INFO_UNSUPPORTED += ['imx8', 'imx8-ipc4', 'imx8x', 'imx8x-ipc4', 'imx8m', 'imx8m-ipc4', 'imx8m_cm7', 'imx8ulp', 'imx8ulp-ipc4', 'imx95', 'imx95-ipc4']
RI_INFO_UNSUPPORTED += ['rn', 'acp_6_0', 'acp_7_0', 'acp_7_x']
RI_INFO_UNSUPPORTED += ['mt8186', 'mt8188', 'mt8195', 'mt8196', 'mt8365']
RI_INFO_UNSUPPORTED += ['qemu_xtensa', 'qemu_xtensa_mmu', 'native_sim']
Expand Down
2 changes: 2 additions & 0 deletions src/audio/copier/copier.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ __cold static int copier_init(struct processing_module *mod)
case ipc4_dmic_link_input_class:
case ipc4_i2s_link_output_class:
case ipc4_i2s_link_input_class:
case ipc4_sai_link_output_class:
case ipc4_sai_link_input_class:
case ipc4_alh_link_output_class:
case ipc4_alh_link_input_class:
case ipc4_alh_uaol_stream_link_output_class:
Expand Down
22 changes: 22 additions & 0 deletions src/audio/copier/copier_dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <sof/trace/trace.h>
#include <sof/audio/component_dai.h>
#include <ipc/dai.h>
#include <ipc4/gateway.h>
#include <sof/tlv.h>
#include <sof/audio/module_adapter/module/generic.h>
#include "copier.h"
#include "dai_copier.h"
Expand Down Expand Up @@ -335,6 +337,26 @@ __cold int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
return -EINVAL;
}
break;
#if CONFIG_IMX
case ipc4_sai_link_output_class:
case ipc4_sai_link_input_class:
/* take dai.format from the i.MX DAI config TLV */
{
uint32_t prefix = sizeof(struct sof_ipc4_gtw_attributes);
void *dcfg = NULL;
uint32_t dlen = 0;

if (gtw_cfg_size > prefix)
tlv_value_get(gtw_cfg_data + prefix,
gtw_cfg_size - prefix,
GTW_IMX_DAI_CONFIG_ID, &dcfg, &dlen);
if (dcfg && dlen >= sizeof(struct sof_ipc_dai_config))
dai.format = ((struct sof_ipc_dai_config *)dcfg)->format;
}
dai.type = SOF_DAI_IMX_SAI;
cd->gtw_type = ipc4_gtw_link;
break;
#endif
case ipc4_alh_link_output_class:
case ipc4_alh_link_input_class:
#if CONFIG_ACE_VERSION_2_0_OR_LATER
Expand Down
89 changes: 89 additions & 0 deletions src/audio/copier/copier_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@
#include <sof/trace/trace.h>
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/lib/mailbox.h>
#include <ipc4/gateway.h>
#include <ipc4/fw_reg.h>
#include <ipc4/notification.h>
#include "copier.h"
#include "host_copier.h"

#include <stddef.h>

LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL);

#if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION
Expand Down Expand Up @@ -131,6 +136,43 @@ __cold static int init_pipeline_reg(struct comp_dev *dev)
return 0;
}

#if CONFIG_IMX
static int copier_host_imx_dma_setup(struct host_data *hd,
const struct ipc4_copier_module_cfg *copier_cfg)
{
uint32_t total = copier_cfg->gtw_cfg.config_length << 2;
uint32_t prefix = sizeof(struct sof_ipc4_gtw_attributes);
struct sof_ipc4_imx_host_config *host_cfg = NULL;
uint32_t host_cfg_len = 0;

if (total > prefix)
tlv_value_get((const uint8_t *)copier_cfg->gtw_cfg.config_data + prefix,
total - prefix, GTW_IMX_HOST_CONFIG_ID,
(void **)&host_cfg, &host_cfg_len);

if (host_cfg && host_cfg_len >= sizeof(*host_cfg) && host_cfg->phy_addr) {
Comment on lines +148 to +153
struct dma_sg_elem *host_elem;

host_elem = sof_heap_alloc(hd->alloc_ctx.heap, SOF_MEM_FLAG_USER,
sizeof(*host_elem), 0);
if (!host_elem)
return -ENOMEM;

host_elem->src = host_cfg->phy_addr;
host_elem->dest = host_cfg->phy_addr;
host_elem->size = host_cfg->dma_buffer_size;

hd->host.elem_array.count = 1;
hd->host.elem_array.elems = host_elem;
hd->host_period_bytes = host_cfg->host_period_bytes;
}

hd->copy_type = COMP_COPY_ONE_SHOT;

return 0;
}
#endif

/* if copier is linked to host gateway, it will manage host dma.
* Sof host component can support this case so copier reuses host
* component to support host gateway.
Expand Down Expand Up @@ -191,6 +233,20 @@ __cold int copier_host_create(struct processing_module *mod,
comp_err(dev, "copier: host new failed with exit");
goto e_data;
}

#if CONFIG_IMX
if (copier_cfg->gtw_cfg.node_id.f.v_index >= IPC4_MAX_HOST_BYTE_CNT_SLOTS) {
comp_err(dev, "host gateway id %u exceeds byte counter slots",
copier_cfg->gtw_cfg.node_id.f.v_index);
ret = -EINVAL;
goto e_conv;
}

ret = copier_host_imx_dma_setup(hd, copier_cfg);
if (ret < 0)
goto e_conv;
Comment on lines +245 to +247
#endif

#if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION
/* Size of a configuration without optional parameters. */
const uint32_t basic_size = sizeof(*copier_cfg) +
Expand Down Expand Up @@ -275,6 +331,28 @@ __cold void copier_host_free(struct processing_module *mod)
mod_free(mod, cd->hd);
}

#if CONFIG_IMX
/* publish the host byte count for the PCM pointer, notify once per ALSA period */
static void copier_host_imx_update_pos(struct copier_data *cd, size_t bytes)
{
uint32_t gtw_id = cd->config.gtw_cfg.node_id.f.v_index;
uint32_t off = offsetof(struct ipc4_fw_registers, host_byte_cnt) +
gtw_id * sizeof(uint64_t);

mailbox_sw_regs_write(off, &cd->hd->total_data_processed,
sizeof(cd->hd->total_data_processed));

if (!cd->hd->host_period_bytes)
return;

cd->hd->report_pos += bytes;
if (cd->hd->report_pos >= cd->hd->host_period_bytes) {
cd->hd->report_pos -= cd->hd->host_period_bytes;
send_host_period_elapsed_notif_msg(gtw_id);
}
}
#endif

/* This is called by DMA driver every time when DMA completes its current
* transfer between host and DSP.
*/
Expand All @@ -289,6 +367,10 @@ void copier_host_dma_cb(struct comp_dev *dev, size_t bytes)
/* update position */
host_common_update(cd->hd, dev, bytes);

#if CONFIG_IMX
copier_host_imx_update_pos(cd, bytes);
#endif

/* callback for one shot copy */
if (cd->hd->copy_type == COMP_COPY_ONE_SHOT)
host_common_one_shot(cd->hd, bytes);
Expand Down Expand Up @@ -323,11 +405,18 @@ static void copier_notifier_cb(void *arg, enum notify_id type, void *data)
int copier_host_params(struct copier_data *cd, struct comp_dev *dev,
struct sof_ipc_stream_params *params)
{
#if CONFIG_IMX
/* keep host_period_bytes from the TLV; IPC4 params lack it */
uint32_t host_period_bytes = cd->hd->host_period_bytes;
#endif
int ret;

component_set_nearest_period_frames(dev, params->rate);
ret = host_common_params(cd->hd, dev, params,
copier_notifier_cb);
#if CONFIG_IMX
cd->hd->host_period_bytes = host_period_bytes;
#endif

cd->hd->process = cd->converter[IPC4_COPIER_GATEWAY_PIN];

Expand Down
4 changes: 3 additions & 1 deletion src/audio/copier/host_copier.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,10 @@ struct host_data {

/* stream info */
struct sof_ipc_stream_posn posn; /* TODO: update this */
#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES
#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES || CONFIG_IMX
uint32_t report_pos; /**< Position in current report period */
#endif
#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES
struct ipc_msg *msg; /**< host notification */
#endif
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
Expand Down
9 changes: 6 additions & 3 deletions src/audio/host-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1027,8 +1027,11 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev,

/* TODO: should be taken from DMA */
if (hd->host.elem_array.count) {
period_bytes *= period_count;
period_count = 1;
/* i.MX software DMA copies one element per LL tick; keep the ring */
if (!(IS_ENABLED(CONFIG_IMX) && hd->host.elem_array.count == 1)) {
period_bytes *= period_count;
period_count = 1;
}
}

/* calculate DMA buffer size */
Expand Down Expand Up @@ -1290,7 +1293,7 @@ void host_common_reset(struct host_data *hd, uint16_t state)

/* reset buffer pointers */
hd->local_pos = 0;
#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES
#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES || CONFIG_IMX
hd->report_pos = 0;
#endif
hd->total_data_processed = 0;
Expand Down
Loading
Loading