Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 30 additions & 5 deletions drivers/i2s/i2s_stm32_sai.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2024 ZAL Zentrum für Angewandte Luftfahrtforschung GmbH
* Copyright (c) 2024 Mario Paja
* Copyright (c) 2024-2025 ZAL Zentrum für Angewandte Luftfahrtforschung GmbH
* Copyright (c) 2024-2025 Mario Paja
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -276,17 +276,23 @@ static int i2s_stm32_sai_dma_init(const struct device *dev)
/* HACK: This field is used to inform driver that it is overridden */
dma_cfg.linked_channel = STM32_DMA_HAL_OVERRIDE;

/* Because of the STREAM OFFSET, the DMA channel given here is from 1 - */
ret = dma_config(stream->dma_dev, stream->dma_channel, &dma_cfg);
/* Because of the STREAM OFFSET, the DMA channel given here is from 1 - 8 */
ret = dma_config(stream->dma_dev, stream->dma_channel + STM32_DMA_STREAM_OFFSET, &dma_cfg);

if (ret != 0) {
LOG_ERR("Failed to configure DMA channel %d",
stream->dma_channel + STM32_DMA_STREAM_OFFSET);
return ret;
}

#if defined(CONFIG_SOC_SERIES_STM32H7X)
hdma->Instance = __LL_DMA_GET_STREAM_INSTANCE(stream->reg, stream->dma_channel);
hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma->Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma->Init.Priority = DMA_PRIORITY_HIGH;
hdma->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
#else
hdma->Instance = LL_DMA_GET_CHANNEL_INSTANCE(stream->reg, stream->dma_channel);
hdma->Init.Request = dma_cfg.dma_slot;
hdma->Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
hdma->Init.SrcDataWidth = DMA_SRC_DATAWIDTH_HALFWORD;
hdma->Init.DestDataWidth = DMA_DEST_DATAWIDTH_HALFWORD;
Expand All @@ -295,17 +301,34 @@ static int i2s_stm32_sai_dma_init(const struct device *dev)
hdma->Init.DestBurstLength = 1;
hdma->Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0 | DMA_DEST_ALLOCATED_PORT0;
hdma->Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
#endif

hdma->Init.Request = dma_cfg.dma_slot;
hdma->Init.Mode = DMA_NORMAL;

if (stream->dma_cfg.channel_direction == (enum dma_channel_direction)MEMORY_TO_PERIPHERAL) {
hdma->Init.Direction = DMA_MEMORY_TO_PERIPH;
Comment on lines 309 to 310
Copy link
Contributor

@evgeniy-paltsev evgeniy-paltsev Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't clear initially how we determine channel direction (as we don't use channel-config flags for that). But after digging a little deeper, I see that it just depends on dma-names value. I guess that is OK.

In rest - looks good.

Copy link
Contributor Author

@mariopaja mariopaja Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evgeniy-paltsev It was difficult to decide what was the best way to implement the DMA TX/RX configuration, since all configs are fixed except the direction.

Making it dependant on dma-names seemed like the best choise at the moment to keep the driver as simple as possible, but I am always open to discuss this topic and make changes :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked other (stm32) dma-capable drivers and they use same approach, so I think it should be also OK for I2S implementation.

At least it is aligned with other drivers :)


#if defined(CONFIG_SOC_SERIES_STM32H7X)
hdma->Init.PeriphInc = DMA_PINC_DISABLE;
hdma->Init.MemInc = DMA_MINC_ENABLE;
#else
hdma->Init.SrcInc = DMA_SINC_INCREMENTED;
hdma->Init.DestInc = DMA_DINC_FIXED;
#endif

__HAL_LINKDMA(hsai, hdmatx, dev_data->hdma);
} else {
hdma->Init.Direction = DMA_PERIPH_TO_MEMORY;

#if defined(CONFIG_SOC_SERIES_STM32H7X)
hdma->Init.PeriphInc = DMA_PINC_ENABLE;
hdma->Init.MemInc = DMA_MINC_DISABLE;
#else
hdma->Init.SrcInc = DMA_SINC_FIXED;
hdma->Init.DestInc = DMA_DINC_INCREMENTED;
#endif

__HAL_LINKDMA(hsai, hdmarx, dev_data->hdma);
}

Expand All @@ -314,10 +337,12 @@ static int i2s_stm32_sai_dma_init(const struct device *dev)
return -EIO;
}

#ifndef CONFIG_SOC_SERIES_STM32H7X
if (HAL_DMA_ConfigChannelAttributes(&dev_data->hdma, DMA_CHANNEL_NPRIV) != HAL_OK) {
LOG_ERR("HAL_DMA_ConfigChannelAttributes: <Failed>");
return -EIO;
}
#endif

return 0;
}
Expand Down
25 changes: 25 additions & 0 deletions dts/arm/st/h7/stm32h7.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Copyright (c) 2019 Centaur Analytics, Inc
* Copyright (c) 2020 Teslabs Engineering S.L.
* Copyright (c) 2024 STMicroelectronics
* Copyright (c) 2025 ZAL Zentrum für Angewandte Luftfahrtforschung GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -1091,6 +1092,30 @@
STM32_DMA_PRIORITY_HIGH) STM32_DMA_FIFO_1_4>;
status = "disabled";
};

sai1_a: sai1@40015804 {
compatible = "st,stm32-sai";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x40015804 0x20>;
clocks = <&rcc STM32_CLOCK(APB2, 22)>,
<&rcc STM32_SRC_PLL2_P SAI1_SEL(1)>;
dmas = <&dma1 1 87 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH |
STM32_DMA_16BITS) 0>;
status = "disabled";
};

sai1_b: sai1@40015824 {
compatible = "st,stm32-sai";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x40015824 0x20>;
clocks = <&rcc STM32_CLOCK(APB2, 22)>,
<&rcc STM32_SRC_PLL2_P SAI1_SEL(1)>;
dmas = <&dma1 0 88 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH |
STM32_DMA_16BITS) 0>;
status = "disabled";
};
};

die_temp: dietemp {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_HEAP_MEM_POOL_SIZE=4192
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2025 ZAL Zentrum für Angewandte Luftfahrtforschung GmbH
* Copyright (c) 2025 Mario Paja
*
* SPDX-License-Identifier: Apache-2.0
*/

/ {
aliases {
i2s-tx = &sai1_b;
};
};

&pll2 {
/* 44.1KHz (0.03% Error) */
div-m = <8>;
mul-n = <192>;
div-q = <2>;
div-r = <2>;
div-p = <17>;
clocks = <&clk_hse>;
status = "okay";
};

&sai1_b {
pinctrl-0 = <&sai1_mclk_b_pf7 &sai1_sd_b_pe3
&sai1_fs_b_pf9 &sai1_sck_b_pf8>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit pick: Indentation

pinctrl-names = "default";
status = "okay";
mclk-enable;
mclk-divider = "div-256";
dma-names = "tx";
};

&dmamux1{
status = "okay";
};

&dma1{
status = "okay";
};