From 58356095a304842443f05b4edba066ed77b7fe16 Mon Sep 17 00:00:00 2001 From: Alexander Boehm Date: Wed, 24 May 2023 18:56:18 +0200 Subject: [PATCH 1/6] topology1: add imx8mp dual SAI topology, 8ch each Use btsco driver to output and capture 8ch on SAI2 and 8ch on SAI3 Signed-off-by: Alexander Boehm --- tools/topology/topology1/CMakeLists.txt | 1 + .../topology1/sof-imx8mp-btsco-dual-8ch.m4 | 124 ++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 tools/topology/topology1/sof-imx8mp-btsco-dual-8ch.m4 diff --git a/tools/topology/topology1/CMakeLists.txt b/tools/topology/topology1/CMakeLists.txt index 48e945f7737a..1991c16ba3e6 100644 --- a/tools/topology/topology1/CMakeLists.txt +++ b/tools/topology/topology1/CMakeLists.txt @@ -181,6 +181,7 @@ set(TPLGS "sof-imx8-wm8960-mixer\;sof-imx8mp-wm8960-mixer\;-DCODEC=wm8960\;-DRATE=48000\;-DSAI_INDEX=3" "sof-imx8-wm8960-mixer\;sof-imx8mp-wm8962-mixer\;-DCODEC=wm8962\;-DRATE=48000\;-DSAI_INDEX=3" "sof-imx8mp-wm8960-kwd\;sof-imx8mp-wm8960-kwd" + "sof-imx8mp-btsco-dual-8ch\;sof-imx8mp-btsco-dual-8ch" "sof-imx8-wm8960\;sof-imx8mp-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=volume\;-DSAI_INDEX=3" "sof-imx8-wm8960\;sof-imx8mp-wm8904\;-DCODEC=wm8904\;-DRATE=44100\;-DPPROC=volume\;-DSAI_INDEX=3" "sof-imx8-wm8960\;sof-imx8mp-wm8962\;-DCODEC=wm8962\;-DRATE=48000\;-DPPROC=volume\;-DSAI_INDEX=3" diff --git a/tools/topology/topology1/sof-imx8mp-btsco-dual-8ch.m4 b/tools/topology/topology1/sof-imx8mp-btsco-dual-8ch.m4 new file mode 100644 index 000000000000..6abb1e4e0755 --- /dev/null +++ b/tools/topology/topology1/sof-imx8mp-btsco-dual-8ch.m4 @@ -0,0 +1,124 @@ +# +# Topology for imx8mp using SAI2 and SAI3, 8 channels each, playback and capture +# + +# +# necessary device tree configuration: +# simple-audio-card with dai-link@0 (cpu <&dsp 1>) and dai-link@1 (cpu <&dsp 2>) +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`sai.m4') +include(`pcm.m4') +include(`buffer.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include DSP configuration +include(`platform/imx/imx8.m4') + +define(`CHANNELS', 8) +define(`DEADLINE', 1000) + +# +# Define the pipelines +# +# PCM0 <---> Volume <---> SAI2 +# PCM1 <---> Volume <---> SAI3 + +dnl PIPELINE_PCM_ADD(pipeline, +dnl pipe id, pcm, max channels, format, +dnl period, priority, core, +dnl pcm_min_rate, pcm_max_rate, pipeline_rate, +dnl time_domain, sched_comp) + +# Low Latency playback pipeline 1 on PCM 0 using max CHANNELS, s16le +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 1, 0, CHANNELS, s16le, + DEADLINE, 0, 0, + 48000, 48000, 48000) + + +# Low Latency capture pipeline 2 on PCM 0 using max CHANNELS, s16le +PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, + 2, 0, CHANNELS, s16le, + DEADLINE, 0, 0, + 48000, 48000, 48000) + + +# Low Latency playback pipeline 3 on PCM 1 using max CHANNELS, s16le +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 3, 1, CHANNELS, s16le, + DEADLINE, 0, 0, + 48000, 48000, 48000) + + +# Low Latency capture pipeline 4 on PCM 1 using max CHANNELS, s16le +PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, + 4, 1, CHANNELS, s16le, + DEADLINE, 0, 0, + 48000, 48000, 48000) + +# +# DAI configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core) + +# playback DAI SAI2 using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, + 1, SAI, 2, sai2-bt-sco-pcm-wb, + PIPELINE_SOURCE_1, 2, s16le, + DEADLINE, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +# capture DAI SAI2 using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, + 2, SAI, 2, sai2-bt-sco-pcm-wb, + PIPELINE_SINK_2, 2, s16le, + DEADLINE, 0, 0) + +# playback DAI SAI3 using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, + 3, SAI, 3, sai3-bt-sco-pcm-wb, + PIPELINE_SOURCE_3, 2, s16le, + DEADLINE, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +# capture DAI SAI3 using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, + 4, SAI, 3, sai3-bt-sco-pcm-wb, + PIPELINE_SINK_4, 2, s16le, + DEADLINE, 0, 0) + +dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +PCM_DUPLEX_ADD(Port0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) +PCM_DUPLEX_ADD(Port1, 1, PIPELINE_PCM_3, PIPELINE_PCM_4) + +dnl DAI_CONFIG(type, dai_index, link_id, name, sai_config) +dnl SAI_CLOCK: clock, freq, codec_master, polarity (optional) +dnl SAI_TDM: number of channels, word width, tx mask, rx mask: decimal channel enable bits +dnl SAI_CONFIG_DATA: index, mclk_id (optional) + +DAI_CONFIG(SAI, 2, 0, sai2-bt-sco-pcm-wb, + SAI_CONFIG(DSP_A, SAI_CLOCK(mclk, 12288000, codec_mclk_out), + SAI_CLOCK(bclk, 6144000, codec_consumer), + SAI_CLOCK(fsync, 48000, codec_consumer), + SAI_TDM(CHANNELS, 16, 255, 255), + SAI_CONFIG_DATA(SAI, 2, 0))) + +DAI_CONFIG(SAI, 3, 0, sai3-bt-sco-pcm-wb, + SAI_CONFIG(DSP_A, SAI_CLOCK(mclk, 12288000, codec_mclk_out), + SAI_CLOCK(bclk, 6144000, codec_consumer, inverted), + SAI_CLOCK(fsync, 48000, codec_consumer), + SAI_TDM(CHANNELS, 16, 255, 255), + SAI_CONFIG_DATA(SAI, 3, 0))) + From 0289127a536ad65cb9578f5c87bf8ed9dbbe95d3 Mon Sep 17 00:00:00 2001 From: Alexander Boehm Date: Wed, 24 May 2023 19:03:35 +0200 Subject: [PATCH 2/6] imx8m: add SAI2,5,6,7 Made the remaining imx8mp SAI peripherals available for use. SAI4 does not exist. Signed-off-by: Alexander Boehm --- .../imx8m/include/platform/lib/memory.h | 12 +++ src/platform/imx8m/lib/dai.c | 86 +++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/src/platform/imx8m/include/platform/lib/memory.h b/src/platform/imx8m/include/platform/lib/memory.h index 49c76897af1e..7d285dbfc463 100644 --- a/src/platform/imx8m/include/platform/lib/memory.h +++ b/src/platform/imx8m/include/platform/lib/memory.h @@ -44,9 +44,21 @@ #define SAI_1_BASE 0x30c10000 #define SAI_1_SIZE 0x00010000 +#define SAI_2_BASE 0x30c20000 +#define SAI_2_SIZE 0x00010000 + #define SAI_3_BASE 0x30c30000 #define SAI_3_SIZE 0x00010000 +#define SAI_5_BASE 0x30c50000 +#define SAI_5_SIZE 0x00010000 + +#define SAI_6_BASE 0x30c60000 +#define SAI_6_SIZE 0x00010000 + +#define SAI_7_BASE 0x30c80000 +#define SAI_7_SIZE 0x00010000 + #define UUID_ENTRY_ELF_BASE 0x1FFFA000 #define UUID_ENTRY_ELF_SIZE 0x6000 diff --git a/src/platform/imx8m/lib/dai.c b/src/platform/imx8m/lib/dai.c index 7346a47cc342..1096740e4f58 100644 --- a/src/platform/imx8m/lib/dai.c +++ b/src/platform/imx8m/lib/dai.c @@ -34,6 +34,28 @@ static SHARED_DATA struct dai sai[] = { }, .drv = &sai_driver, }, + +{ + .index = 2, + .plat_data = { + .base = SAI_2_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_2_BASE + REG_SAI_TDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + /* Handshake is SDMA hardware event */ + .handshake = 3, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_2_BASE + REG_SAI_RDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + .handshake = 2, + }, + }, + .drv = &sai_driver, +}, + { .index = 3, .plat_data = { @@ -54,6 +76,70 @@ static SHARED_DATA struct dai sai[] = { }, .drv = &sai_driver, }, + +{ + .index = 5, + .plat_data = { + .base = SAI_5_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_5_BASE + REG_SAI_TDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + /* Handshake is SDMA hardware event */ + .handshake = 9, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_5_BASE + REG_SAI_RDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + .handshake = 8, + }, + }, + .drv = &sai_driver, +}, + +{ + .index = 6, + .plat_data = { + .base = SAI_6_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_6_BASE + REG_SAI_TDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + /* Handshake is SDMA hardware event */ + .handshake = 11, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_6_BASE + REG_SAI_RDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + .handshake = 10, + }, + }, + .drv = &sai_driver, +}, + +{ + .index = 7, + .plat_data = { + .base = SAI_7_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_7_BASE + REG_SAI_TDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + /* Handshake is SDMA hardware event */ + .handshake = 13, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_7_BASE + REG_SAI_RDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + .handshake = 12, + }, + }, + .drv = &sai_driver, +}, + }; const struct dai_type_info dti[] = { From 03fb71366c1771447f01b15099fe9d4a8c878b8f Mon Sep 17 00:00:00 2001 From: Alexander Boehm Date: Wed, 24 May 2023 19:09:24 +0200 Subject: [PATCH 3/6] topology1: fix sai.m4 clock inversion A misplaced ) prevented the optional 'inverted' flag from working as intended. Signed-off-by: Alexander Boehm --- tools/topology/topology1/platform/common/sai.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/topology/topology1/platform/common/sai.m4 b/tools/topology/topology1/platform/common/sai.m4 index 9697aa374bd6..389daaaf5a5a 100644 --- a/tools/topology/topology1/platform/common/sai.m4 +++ b/tools/topology/topology1/platform/common/sai.m4 @@ -6,7 +6,7 @@ dnl SAI_CLOCK(clock, freq, codec_master, polarity) dnl polarity is optional define(`SAI_CLOCK', $1 STR($3) - $1_freq STR($2)) + $1_freq STR($2) `ifelse($4, `inverted', `$1_invert "true"',`')') dnl SAI_TDM(slots, width, tx_mask, rx_mask) From e779bce1a2bd81755c1fc9fa936611669c90abe1 Mon Sep 17 00:00:00 2001 From: Alexander Boehm Date: Thu, 25 May 2023 08:40:30 +0200 Subject: [PATCH 4/6] imx8m: increase max channels/streams Increase PLATFORM_MAX_CHANNELS and PLATFORM_MAX_STREAMS to 8 in order to enable the use of certain components (e.g. 'volume') with 8 channels. This necessitates an increased HEAP_RUNTIME_SIZE. Signed-off-by: Alexander Boehm --- src/platform/imx8m/include/platform/platform.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/platform/imx8m/include/platform/platform.h b/src/platform/imx8m/include/platform/platform.h index e0316c0796c3..e80d1441b3b6 100644 --- a/src/platform/imx8m/include/platform/platform.h +++ b/src/platform/imx8m/include/platform/platform.h @@ -35,9 +35,13 @@ struct timer; #define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 #define PLATFORM_SCHEDULE_IRQ_NAME NULL -/* Platform stream capabilities */ -#define PLATFORM_MAX_CHANNELS 4 -#define PLATFORM_MAX_STREAMS 5 +/* + * Platform stream capabilities + * MAX_CHANNELS only affects 'components' so it is, for example, + * still possible to have multiple SAI peripherals output 8 channels each. + */ +#define PLATFORM_MAX_CHANNELS 8 +#define PLATFORM_MAX_STREAMS 8 /* local buffer size of DMA tracing */ #define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE From b5ec4f630cbbe63b99ac99228d2761f5555c4fff Mon Sep 17 00:00:00 2001 From: Alexander Boehm Date: Thu, 25 May 2023 08:07:38 +0200 Subject: [PATCH 5/6] SAI: use topology params The imx SAI driver used hardcoded clock dividers, word lengths and #ifdefs to deal with differences between SOCs. Changed it to respect all the SAI_CONFIG parameters. Signed-off-by: Alexander Boehm --- src/drivers/imx/sai.c | 109 ++++++++++++++++++++++++---------- src/include/sof/drivers/sai.h | 18 +----- 2 files changed, 78 insertions(+), 49 deletions(-) diff --git a/src/drivers/imx/sai.c b/src/drivers/imx/sai.c index 303de4c7ea1a..6fcd1061f54e 100644 --- a/src/drivers/imx/sai.c +++ b/src/drivers/imx/sai.c @@ -33,8 +33,11 @@ static void sai_start(struct dai *dai, int direction) { dai_info(dai, "SAI: sai_start"); + struct sai_pdata *sai = dai_get_drvdata(dai); int chan_idx = 0; uint32_t xcsr = 0U; + int i; + int n; #ifdef CONFIG_IMX8ULP int fifo_offset = 0; #endif @@ -80,11 +83,36 @@ static void sai_start(struct dai *dai, int direction) dai_update_bits(dai, REG_SAI_XCSR(direction), REG_SAI_CSR_WSF, 1); - /* add one word to FIFO before TRCE is enabled */ - if (direction == DAI_DIR_PLAYBACK) - dai_write(dai, REG_SAI_TDR0, 0x0); - else - dai_write(dai, REG_SAI_RDR0, 0x0); + /* + * Add one frame of data to FIFO before TRCE is enabled. + * In FIFO words this equates to tdm_slots/(slots_per_32b_fifo_word). Minimum: one word. + * Not performing this 'priming' can lead to negative effects like shifted + * and / or missing slots. + * TODO: check if that works in all situations + */ + + switch (sai->params.tdm_slot_width) { + case 8: + n = sai->params.tdm_slots / 4; + break; + case 16: + n = sai->params.tdm_slots / 2; + break; + default: + n = sai->params.tdm_slots; + break; + } + + if (!n) + n = 1; + + if (direction == DAI_DIR_PLAYBACK) { + for (i = 0; i < n; i++) + dai_write(dai, REG_SAI_TDR0, 0x0); + } else { + for (i = 0; i < n; i++) + dai_write(dai, REG_SAI_RDR0, 0x0); + } /* enable DMA requests */ dai_update_bits(dai, REG_SAI_XCSR(direction), @@ -200,22 +228,28 @@ static inline int sai_set_config(struct dai *dai, struct ipc_config_dai *common_ const struct sof_ipc_dai_config *config = spec_config; uint32_t val_cr2 = 0, val_cr4 = 0, val_cr5 = 0; uint32_t mask_cr2 = 0, mask_cr4 = 0, mask_cr5 = 0; + uint32_t clk_div; struct sai_pdata *sai = dai_get_drvdata(dai); - /* TODO: this value will be provided by config */ -#ifndef CONFIG_IMX8ULP - uint32_t sywd = 32; - uint32_t twm = ~(BIT(0) | BIT(1)); - uint32_t clk_div = SAI_CLOCK_DIV; -#else - uint32_t sywd = 16; - uint32_t twm = ~BIT(0); - uint32_t clk_div = config->sai.fsync_rate == 8000 ? SAI_CLOCK_DIV : SAI_CLOCK_DIV_16K; -#endif sai->config = *config; sai->params = config->sai; - val_cr4 |= REG_SAI_CR4_MF; + /* bit width of a single slot; FIFO word always 32b */ + uint32_t sywd = sai->params.tdm_slot_width; + + /* + * Divide the audio main clock to generate the bit clock when + * configured for an internal bit clock. + * The division value is (DIV + 1) * 2. + * If mclk == bclk set the divider bypass bit, REG_SAI_CR2_BYP. + */ + + if (config->sai.mclk_rate == config->sai.bclk_rate) { + val_cr2 |= REG_SAI_CR2_BYP; + clk_div = 0; + } else { + clk_div = (config->sai.mclk_rate / config->sai.bclk_rate / 2) - 1; + } switch (config->format & SOF_DAI_FMT_FORMAT_MASK) { case SOF_DAI_FMT_I2S: @@ -299,7 +333,7 @@ static inline int sai_set_config(struct dai *dai, struct ipc_config_dai *common_ dai_info(dai, "SAI: codec is consumer"); val_cr2 |= REG_SAI_CR2_MSEL_MCLK1; val_cr2 |= REG_SAI_CR2_BCD_MSTR; - val_cr2 |= clk_div; /* TODO: determine dynamically.*/ + val_cr2 |= clk_div; val_cr4 |= REG_SAI_CR4_FSD_MSTR; break; case SOF_DAI_FMT_CBP_CFP: @@ -311,30 +345,42 @@ static inline int sai_set_config(struct dai *dai, struct ipc_config_dai *common_ break; case SOF_DAI_FMT_CBC_CFP: val_cr2 |= REG_SAI_CR2_BCD_MSTR; - val_cr2 |= clk_div; /* TODO: determine dynamically.*/ + val_cr2 |= clk_div; break; case SOF_DAI_FMT_CBP_CFC: val_cr4 |= REG_SAI_CR4_FSD_MSTR; - val_cr2 |= clk_div; /* TODO: determine dynamically.*/ + val_cr2 |= clk_div; break; default: return -EINVAL; } - /* TODO: set number of slots from config */ - val_cr4 |= REG_SAI_CR4_FRSZ(SAI_TDM_SLOTS); + switch (sai->params.tdm_slot_width) { + case 8: + val_cr4 |= REG_SAI_CR4_FPACK_8; + break; + case 16: + val_cr4 |= REG_SAI_CR4_FPACK_16; + break; + default: + break; + } + + val_cr4 |= REG_SAI_CR4_FRSZ(sai->params.tdm_slots); val_cr4 |= REG_SAI_CR4_CHMOD; + val_cr4 |= REG_SAI_CR4_MF; val_cr5 |= REG_SAI_CR5_WNW(sywd) | REG_SAI_CR5_W0W(sywd) | REG_SAI_CR5_FBT(sywd); mask_cr2 = REG_SAI_CR2_BCP | REG_SAI_CR2_BCD_MSTR | + REG_SAI_CR2_BYP_MASK | REG_SAI_CR2_MSEL_MASK | REG_SAI_CR2_DIV_MASK; mask_cr4 = REG_SAI_CR4_MF | REG_SAI_CR4_FSE | REG_SAI_CR4_FSP | REG_SAI_CR4_FSD_MSTR | REG_SAI_CR4_FRSZ_MASK | REG_SAI_CR4_SYWD_MASK | - REG_SAI_CR4_CHMOD_MASK; + REG_SAI_CR4_CHMOD_MASK | REG_SAI_CR4_FPACK_MASK; mask_cr5 = REG_SAI_CR5_WNW_MASK | REG_SAI_CR5_W0W_MASK | REG_SAI_CR5_FBT_MASK; @@ -344,8 +390,9 @@ static inline int sai_set_config(struct dai *dai, struct ipc_config_dai *common_ dai_update_bits(dai, REG_SAI_XCR2(REG_TX_DIR), mask_cr2, val_cr2); dai_update_bits(dai, REG_SAI_XCR4(REG_TX_DIR), mask_cr4, val_cr4); dai_update_bits(dai, REG_SAI_XCR5(REG_TX_DIR), mask_cr5, val_cr5); - /* turn on (set to zero) stereo slot */ - dai_update_bits(dai, REG_SAI_XMR(REG_TX_DIR), REG_SAI_XMR_MASK, twm); + /* turn on (set to zero) slots */ + dai_update_bits(dai, REG_SAI_XMR(REG_TX_DIR), REG_SAI_XMR_MASK, + ~(sai->params.tx_slots)); val_cr2 |= REG_SAI_CR2_SYNC; mask_cr2 |= REG_SAI_CR2_SYNC_MASK; @@ -355,9 +402,9 @@ static inline int sai_set_config(struct dai *dai, struct ipc_config_dai *common_ dai_update_bits(dai, REG_SAI_XCR2(REG_RX_DIR), mask_cr2, val_cr2); dai_update_bits(dai, REG_SAI_XCR4(REG_RX_DIR), mask_cr4, val_cr4); dai_update_bits(dai, REG_SAI_XCR5(REG_RX_DIR), mask_cr5, val_cr5); - /* turn on (set to zero) stereo slot */ + /* turn on (set to zero) slots */ dai_update_bits(dai, REG_SAI_XMR(REG_RX_DIR), REG_SAI_XMR_MASK, - twm); + ~(sai->params.rx_slots)); #if defined(CONFIG_IMX8M) || defined(CONFIG_IMX93_A55) /* @@ -484,14 +531,10 @@ static int sai_get_hw_params(struct dai *dai, { struct sai_pdata *sai = dai_get_drvdata(dai); - /* SAI only currently supports these parameters */ params->rate = sai->params.fsync_rate; -#ifdef CONFIG_IMX8ULP - params->channels = 1; -#else - params->channels = 2; -#endif - params->buffer_fmt = 0; + params->channels = sai->params.tdm_slots; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + /* frame_fmt always S32_LE because that is the native width of the fifo registers */ params->frame_fmt = SOF_IPC_FRAME_S32_LE; return 0; diff --git a/src/include/sof/drivers/sai.h b/src/include/sof/drivers/sai.h index 2b897943d675..10405298322d 100644 --- a/src/include/sof/drivers/sai.h +++ b/src/include/sof/drivers/sai.h @@ -147,6 +147,7 @@ #define REG_SAI_CR2_BCP BIT(25) #define REG_SAI_CR2_BCD_MSTR BIT(24) #define REG_SAI_CR2_BYP BIT(23) /* BCLK bypass */ +#define REG_SAI_CR2_BYP_MASK BIT(23) #define REG_SAI_CR2_DIV_MASK 0xff /* SAI Transmit and Receive Configuration 3 Register */ @@ -163,6 +164,7 @@ #define REG_SAI_CR4_FCOMB_MASK MASK(27, 26) #define REG_SAI_CR4_FPACK_8 (0x2 << 24) #define REG_SAI_CR4_FPACK_16 (0x3 << 24) +#define REG_SAI_CR4_FPACK_MASK MASK(25, 24) #define REG_SAI_CR4_FRSZ(x) (((x) - 1) << 16) #define REG_SAI_CR4_FRSZ_MASK MASK(20, 16) #define REG_SAI_CR4_SYWD(x) (((x) - 1) << 8) @@ -245,22 +247,6 @@ #define SAI_FIFO_WORD_SIZE 64 #endif -/* Divides down the audio main clock to generate the bit clock when - * configured for an internal bit clock. - * The division value is (DIV + 1) * 2. - */ -#ifdef CONFIG_IMX8ULP -/* frame clk is decided by sai config on 8ulp - * 8K --- 0x17, 16K --- 0xB - */ -#define SAI_CLOCK_DIV 0x17 -#define SAI_CLOCK_DIV_16K 0xB -#define SAI_TDM_SLOTS 2 -#else -#define SAI_CLOCK_DIV 0x7 -#define SAI_TDM_SLOTS 2 -#endif - extern const struct dai_driver sai_driver; /* SAI private data */ From 368853e11f09796f23421b069bcdc5c7429b035c Mon Sep 17 00:00:00 2001 From: Alexander Boehm Date: Wed, 31 May 2023 18:23:23 +0200 Subject: [PATCH 6/6] SAI: fix DSP_A/B frame sync pulse SAI can be configured for a one bclk wide frame sync pulse by setting CR4 SYWD to 0. The REG_SAI_CR4_SYWD() macro subtracts 1 from its argument which resulted in bad things happening. So use 1 as correct macro argument. Signed-off-by: Alexander Boehm --- src/drivers/imx/sai.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drivers/imx/sai.c b/src/drivers/imx/sai.c index 6fcd1061f54e..df9690eb8d7c 100644 --- a/src/drivers/imx/sai.c +++ b/src/drivers/imx/sai.c @@ -284,7 +284,7 @@ static inline int sai_set_config(struct dai *dai, struct ipc_config_dai *common_ */ val_cr2 |= REG_SAI_CR2_BCP; val_cr4 |= REG_SAI_CR4_FSE; - val_cr4 |= REG_SAI_CR4_SYWD(0U); + val_cr4 |= REG_SAI_CR4_SYWD(1U); break; case SOF_DAI_FMT_DSP_B: /* @@ -292,7 +292,7 @@ static inline int sai_set_config(struct dai *dai, struct ipc_config_dai *common_ * frame sync asserts with the first bit of the frame. */ val_cr2 |= REG_SAI_CR2_BCP; - val_cr4 |= REG_SAI_CR4_SYWD(0U); + val_cr4 |= REG_SAI_CR4_SYWD(1U); break; case SOF_DAI_FMT_PDM: val_cr2 |= REG_SAI_CR2_BCP;