18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  STM32 ALSA SoC Digital Audio Interface (I2S) driver.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
68c2ecf20Sopenharmony_ci * Author(s): Olivier Moysan <olivier.moysan@st.com> for STMicroelectronics.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/bitfield.h>
108c2ecf20Sopenharmony_ci#include <linux/clk.h>
118c2ecf20Sopenharmony_ci#include <linux/delay.h>
128c2ecf20Sopenharmony_ci#include <linux/module.h>
138c2ecf20Sopenharmony_ci#include <linux/of_irq.h>
148c2ecf20Sopenharmony_ci#include <linux/of_platform.h>
158c2ecf20Sopenharmony_ci#include <linux/regmap.h>
168c2ecf20Sopenharmony_ci#include <linux/reset.h>
178c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <sound/dmaengine_pcm.h>
208c2ecf20Sopenharmony_ci#include <sound/pcm_params.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define STM32_I2S_CR1_REG	0x0
238c2ecf20Sopenharmony_ci#define STM32_I2S_CFG1_REG	0x08
248c2ecf20Sopenharmony_ci#define STM32_I2S_CFG2_REG	0x0C
258c2ecf20Sopenharmony_ci#define STM32_I2S_IER_REG	0x10
268c2ecf20Sopenharmony_ci#define STM32_I2S_SR_REG	0x14
278c2ecf20Sopenharmony_ci#define STM32_I2S_IFCR_REG	0x18
288c2ecf20Sopenharmony_ci#define STM32_I2S_TXDR_REG	0X20
298c2ecf20Sopenharmony_ci#define STM32_I2S_RXDR_REG	0x30
308c2ecf20Sopenharmony_ci#define STM32_I2S_CGFR_REG	0X50
318c2ecf20Sopenharmony_ci#define STM32_I2S_HWCFGR_REG	0x3F0
328c2ecf20Sopenharmony_ci#define STM32_I2S_VERR_REG	0x3F4
338c2ecf20Sopenharmony_ci#define STM32_I2S_IPIDR_REG	0x3F8
348c2ecf20Sopenharmony_ci#define STM32_I2S_SIDR_REG	0x3FC
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/* Bit definition for SPI2S_CR1 register */
378c2ecf20Sopenharmony_ci#define I2S_CR1_SPE		BIT(0)
388c2ecf20Sopenharmony_ci#define I2S_CR1_CSTART		BIT(9)
398c2ecf20Sopenharmony_ci#define I2S_CR1_CSUSP		BIT(10)
408c2ecf20Sopenharmony_ci#define I2S_CR1_HDDIR		BIT(11)
418c2ecf20Sopenharmony_ci#define I2S_CR1_SSI		BIT(12)
428c2ecf20Sopenharmony_ci#define I2S_CR1_CRC33_17	BIT(13)
438c2ecf20Sopenharmony_ci#define I2S_CR1_RCRCI		BIT(14)
448c2ecf20Sopenharmony_ci#define I2S_CR1_TCRCI		BIT(15)
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/* Bit definition for SPI_CFG2 register */
478c2ecf20Sopenharmony_ci#define I2S_CFG2_IOSWP_SHIFT	15
488c2ecf20Sopenharmony_ci#define I2S_CFG2_IOSWP		BIT(I2S_CFG2_IOSWP_SHIFT)
498c2ecf20Sopenharmony_ci#define I2S_CFG2_LSBFRST	BIT(23)
508c2ecf20Sopenharmony_ci#define I2S_CFG2_AFCNTR		BIT(31)
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* Bit definition for SPI_CFG1 register */
538c2ecf20Sopenharmony_ci#define I2S_CFG1_FTHVL_SHIFT	5
548c2ecf20Sopenharmony_ci#define I2S_CFG1_FTHVL_MASK	GENMASK(8, I2S_CFG1_FTHVL_SHIFT)
558c2ecf20Sopenharmony_ci#define I2S_CFG1_FTHVL_SET(x)	((x) << I2S_CFG1_FTHVL_SHIFT)
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define I2S_CFG1_TXDMAEN	BIT(15)
588c2ecf20Sopenharmony_ci#define I2S_CFG1_RXDMAEN	BIT(14)
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/* Bit definition for SPI2S_IER register */
618c2ecf20Sopenharmony_ci#define I2S_IER_RXPIE		BIT(0)
628c2ecf20Sopenharmony_ci#define I2S_IER_TXPIE		BIT(1)
638c2ecf20Sopenharmony_ci#define I2S_IER_DPXPIE		BIT(2)
648c2ecf20Sopenharmony_ci#define I2S_IER_EOTIE		BIT(3)
658c2ecf20Sopenharmony_ci#define I2S_IER_TXTFIE		BIT(4)
668c2ecf20Sopenharmony_ci#define I2S_IER_UDRIE		BIT(5)
678c2ecf20Sopenharmony_ci#define I2S_IER_OVRIE		BIT(6)
688c2ecf20Sopenharmony_ci#define I2S_IER_CRCEIE		BIT(7)
698c2ecf20Sopenharmony_ci#define I2S_IER_TIFREIE		BIT(8)
708c2ecf20Sopenharmony_ci#define I2S_IER_MODFIE		BIT(9)
718c2ecf20Sopenharmony_ci#define I2S_IER_TSERFIE		BIT(10)
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* Bit definition for SPI2S_SR register */
748c2ecf20Sopenharmony_ci#define I2S_SR_RXP		BIT(0)
758c2ecf20Sopenharmony_ci#define I2S_SR_TXP		BIT(1)
768c2ecf20Sopenharmony_ci#define I2S_SR_DPXP		BIT(2)
778c2ecf20Sopenharmony_ci#define I2S_SR_EOT		BIT(3)
788c2ecf20Sopenharmony_ci#define I2S_SR_TXTF		BIT(4)
798c2ecf20Sopenharmony_ci#define I2S_SR_UDR		BIT(5)
808c2ecf20Sopenharmony_ci#define I2S_SR_OVR		BIT(6)
818c2ecf20Sopenharmony_ci#define I2S_SR_CRCERR		BIT(7)
828c2ecf20Sopenharmony_ci#define I2S_SR_TIFRE		BIT(8)
838c2ecf20Sopenharmony_ci#define I2S_SR_MODF		BIT(9)
848c2ecf20Sopenharmony_ci#define I2S_SR_TSERF		BIT(10)
858c2ecf20Sopenharmony_ci#define I2S_SR_SUSP		BIT(11)
868c2ecf20Sopenharmony_ci#define I2S_SR_TXC		BIT(12)
878c2ecf20Sopenharmony_ci#define I2S_SR_RXPLVL		GENMASK(14, 13)
888c2ecf20Sopenharmony_ci#define I2S_SR_RXWNE		BIT(15)
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci#define I2S_SR_MASK		GENMASK(15, 0)
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci/* Bit definition for SPI_IFCR register */
938c2ecf20Sopenharmony_ci#define I2S_IFCR_EOTC		BIT(3)
948c2ecf20Sopenharmony_ci#define I2S_IFCR_TXTFC		BIT(4)
958c2ecf20Sopenharmony_ci#define I2S_IFCR_UDRC		BIT(5)
968c2ecf20Sopenharmony_ci#define I2S_IFCR_OVRC		BIT(6)
978c2ecf20Sopenharmony_ci#define I2S_IFCR_CRCEC		BIT(7)
988c2ecf20Sopenharmony_ci#define I2S_IFCR_TIFREC		BIT(8)
998c2ecf20Sopenharmony_ci#define I2S_IFCR_MODFC		BIT(9)
1008c2ecf20Sopenharmony_ci#define I2S_IFCR_TSERFC		BIT(10)
1018c2ecf20Sopenharmony_ci#define I2S_IFCR_SUSPC		BIT(11)
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci#define I2S_IFCR_MASK		GENMASK(11, 3)
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/* Bit definition for SPI_I2SCGFR register */
1068c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SMOD		BIT(0)
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SCFG_SHIFT	1
1098c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SCFG_MASK	GENMASK(3, I2S_CGFR_I2SCFG_SHIFT)
1108c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SCFG_SET(x)	((x) << I2S_CGFR_I2SCFG_SHIFT)
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SSTD_SHIFT	4
1138c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SSTD_MASK	GENMASK(5, I2S_CGFR_I2SSTD_SHIFT)
1148c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SSTD_SET(x)	((x) << I2S_CGFR_I2SSTD_SHIFT)
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci#define I2S_CGFR_PCMSYNC	BIT(7)
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci#define I2S_CGFR_DATLEN_SHIFT	8
1198c2ecf20Sopenharmony_ci#define I2S_CGFR_DATLEN_MASK	GENMASK(9, I2S_CGFR_DATLEN_SHIFT)
1208c2ecf20Sopenharmony_ci#define I2S_CGFR_DATLEN_SET(x)	((x) << I2S_CGFR_DATLEN_SHIFT)
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci#define I2S_CGFR_CHLEN_SHIFT	10
1238c2ecf20Sopenharmony_ci#define I2S_CGFR_CHLEN		BIT(I2S_CGFR_CHLEN_SHIFT)
1248c2ecf20Sopenharmony_ci#define I2S_CGFR_CKPOL		BIT(11)
1258c2ecf20Sopenharmony_ci#define I2S_CGFR_FIXCH		BIT(12)
1268c2ecf20Sopenharmony_ci#define I2S_CGFR_WSINV		BIT(13)
1278c2ecf20Sopenharmony_ci#define I2S_CGFR_DATFMT		BIT(14)
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SDIV_SHIFT	16
1308c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SDIV_BIT_H	23
1318c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SDIV_MASK	GENMASK(I2S_CGFR_I2SDIV_BIT_H,\
1328c2ecf20Sopenharmony_ci				I2S_CGFR_I2SDIV_SHIFT)
1338c2ecf20Sopenharmony_ci#define I2S_CGFR_I2SDIV_SET(x)	((x) << I2S_CGFR_I2SDIV_SHIFT)
1348c2ecf20Sopenharmony_ci#define	I2S_CGFR_I2SDIV_MAX	((1 << (I2S_CGFR_I2SDIV_BIT_H -\
1358c2ecf20Sopenharmony_ci				I2S_CGFR_I2SDIV_SHIFT)) - 1)
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci#define I2S_CGFR_ODD_SHIFT	24
1388c2ecf20Sopenharmony_ci#define I2S_CGFR_ODD		BIT(I2S_CGFR_ODD_SHIFT)
1398c2ecf20Sopenharmony_ci#define I2S_CGFR_MCKOE		BIT(25)
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci/* Registers below apply to I2S version 1.1 and more */
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci/* Bit definition for SPI_HWCFGR register */
1448c2ecf20Sopenharmony_ci#define I2S_HWCFGR_I2S_SUPPORT_MASK	GENMASK(15, 12)
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci/* Bit definition for SPI_VERR register */
1478c2ecf20Sopenharmony_ci#define I2S_VERR_MIN_MASK	GENMASK(3, 0)
1488c2ecf20Sopenharmony_ci#define I2S_VERR_MAJ_MASK	GENMASK(7, 4)
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci/* Bit definition for SPI_IPIDR register */
1518c2ecf20Sopenharmony_ci#define I2S_IPIDR_ID_MASK	GENMASK(31, 0)
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci/* Bit definition for SPI_SIDR register */
1548c2ecf20Sopenharmony_ci#define I2S_SIDR_ID_MASK	GENMASK(31, 0)
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci#define I2S_IPIDR_NUMBER	0x00130022
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cienum i2s_master_mode {
1598c2ecf20Sopenharmony_ci	I2S_MS_NOT_SET,
1608c2ecf20Sopenharmony_ci	I2S_MS_MASTER,
1618c2ecf20Sopenharmony_ci	I2S_MS_SLAVE,
1628c2ecf20Sopenharmony_ci};
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cienum i2s_mode {
1658c2ecf20Sopenharmony_ci	I2S_I2SMOD_TX_SLAVE,
1668c2ecf20Sopenharmony_ci	I2S_I2SMOD_RX_SLAVE,
1678c2ecf20Sopenharmony_ci	I2S_I2SMOD_TX_MASTER,
1688c2ecf20Sopenharmony_ci	I2S_I2SMOD_RX_MASTER,
1698c2ecf20Sopenharmony_ci	I2S_I2SMOD_FD_SLAVE,
1708c2ecf20Sopenharmony_ci	I2S_I2SMOD_FD_MASTER,
1718c2ecf20Sopenharmony_ci};
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cienum i2s_fifo_th {
1748c2ecf20Sopenharmony_ci	I2S_FIFO_TH_NONE,
1758c2ecf20Sopenharmony_ci	I2S_FIFO_TH_ONE_QUARTER,
1768c2ecf20Sopenharmony_ci	I2S_FIFO_TH_HALF,
1778c2ecf20Sopenharmony_ci	I2S_FIFO_TH_THREE_QUARTER,
1788c2ecf20Sopenharmony_ci	I2S_FIFO_TH_FULL,
1798c2ecf20Sopenharmony_ci};
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cienum i2s_std {
1828c2ecf20Sopenharmony_ci	I2S_STD_I2S,
1838c2ecf20Sopenharmony_ci	I2S_STD_LEFT_J,
1848c2ecf20Sopenharmony_ci	I2S_STD_RIGHT_J,
1858c2ecf20Sopenharmony_ci	I2S_STD_DSP,
1868c2ecf20Sopenharmony_ci};
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_cienum i2s_datlen {
1898c2ecf20Sopenharmony_ci	I2S_I2SMOD_DATLEN_16,
1908c2ecf20Sopenharmony_ci	I2S_I2SMOD_DATLEN_24,
1918c2ecf20Sopenharmony_ci	I2S_I2SMOD_DATLEN_32,
1928c2ecf20Sopenharmony_ci};
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci#define STM32_I2S_FIFO_SIZE		16
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci#define STM32_I2S_IS_MASTER(x)		((x)->ms_flg == I2S_MS_MASTER)
1978c2ecf20Sopenharmony_ci#define STM32_I2S_IS_SLAVE(x)		((x)->ms_flg == I2S_MS_SLAVE)
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci/**
2008c2ecf20Sopenharmony_ci * struct stm32_i2s_data - private data of I2S
2018c2ecf20Sopenharmony_ci * @regmap_conf: I2S register map configuration pointer
2028c2ecf20Sopenharmony_ci * @regmap: I2S register map pointer
2038c2ecf20Sopenharmony_ci * @pdev: device data pointer
2048c2ecf20Sopenharmony_ci * @dai_drv: DAI driver pointer
2058c2ecf20Sopenharmony_ci * @dma_data_tx: dma configuration data for tx channel
2068c2ecf20Sopenharmony_ci * @dma_data_rx: dma configuration data for tx channel
2078c2ecf20Sopenharmony_ci * @substream: PCM substream data pointer
2088c2ecf20Sopenharmony_ci * @i2sclk: kernel clock feeding the I2S clock generator
2098c2ecf20Sopenharmony_ci * @pclk: peripheral clock driving bus interface
2108c2ecf20Sopenharmony_ci * @x8kclk: I2S parent clock for sampling frequencies multiple of 8kHz
2118c2ecf20Sopenharmony_ci * @x11kclk: I2S parent clock for sampling frequencies multiple of 11kHz
2128c2ecf20Sopenharmony_ci * @base:  mmio register base virtual address
2138c2ecf20Sopenharmony_ci * @phys_addr: I2S registers physical base address
2148c2ecf20Sopenharmony_ci * @lock_fd: lock to manage race conditions in full duplex mode
2158c2ecf20Sopenharmony_ci * @irq_lock: prevent race condition with IRQ
2168c2ecf20Sopenharmony_ci * @mclk_rate: master clock frequency (Hz)
2178c2ecf20Sopenharmony_ci * @fmt: DAI protocol
2188c2ecf20Sopenharmony_ci * @refcount: keep count of opened streams on I2S
2198c2ecf20Sopenharmony_ci * @ms_flg: master mode flag.
2208c2ecf20Sopenharmony_ci */
2218c2ecf20Sopenharmony_cistruct stm32_i2s_data {
2228c2ecf20Sopenharmony_ci	const struct regmap_config *regmap_conf;
2238c2ecf20Sopenharmony_ci	struct regmap *regmap;
2248c2ecf20Sopenharmony_ci	struct platform_device *pdev;
2258c2ecf20Sopenharmony_ci	struct snd_soc_dai_driver *dai_drv;
2268c2ecf20Sopenharmony_ci	struct snd_dmaengine_dai_dma_data dma_data_tx;
2278c2ecf20Sopenharmony_ci	struct snd_dmaengine_dai_dma_data dma_data_rx;
2288c2ecf20Sopenharmony_ci	struct snd_pcm_substream *substream;
2298c2ecf20Sopenharmony_ci	struct clk *i2sclk;
2308c2ecf20Sopenharmony_ci	struct clk *pclk;
2318c2ecf20Sopenharmony_ci	struct clk *x8kclk;
2328c2ecf20Sopenharmony_ci	struct clk *x11kclk;
2338c2ecf20Sopenharmony_ci	void __iomem *base;
2348c2ecf20Sopenharmony_ci	dma_addr_t phys_addr;
2358c2ecf20Sopenharmony_ci	spinlock_t lock_fd; /* Manage race conditions for full duplex */
2368c2ecf20Sopenharmony_ci	spinlock_t irq_lock; /* used to prevent race condition with IRQ */
2378c2ecf20Sopenharmony_ci	unsigned int mclk_rate;
2388c2ecf20Sopenharmony_ci	unsigned int fmt;
2398c2ecf20Sopenharmony_ci	int refcount;
2408c2ecf20Sopenharmony_ci	int ms_flg;
2418c2ecf20Sopenharmony_ci};
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cistatic irqreturn_t stm32_i2s_isr(int irq, void *devid)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = (struct stm32_i2s_data *)devid;
2468c2ecf20Sopenharmony_ci	struct platform_device *pdev = i2s->pdev;
2478c2ecf20Sopenharmony_ci	u32 sr, ier;
2488c2ecf20Sopenharmony_ci	unsigned long flags;
2498c2ecf20Sopenharmony_ci	int err = 0;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	regmap_read(i2s->regmap, STM32_I2S_SR_REG, &sr);
2528c2ecf20Sopenharmony_ci	regmap_read(i2s->regmap, STM32_I2S_IER_REG, &ier);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	flags = sr & ier;
2558c2ecf20Sopenharmony_ci	if (!flags) {
2568c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "Spurious IRQ sr=0x%08x, ier=0x%08x\n",
2578c2ecf20Sopenharmony_ci			sr, ier);
2588c2ecf20Sopenharmony_ci		return IRQ_NONE;
2598c2ecf20Sopenharmony_ci	}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	regmap_write_bits(i2s->regmap, STM32_I2S_IFCR_REG,
2628c2ecf20Sopenharmony_ci			  I2S_IFCR_MASK, flags);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	if (flags & I2S_SR_OVR) {
2658c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "Overrun\n");
2668c2ecf20Sopenharmony_ci		err = 1;
2678c2ecf20Sopenharmony_ci	}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	if (flags & I2S_SR_UDR) {
2708c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "Underrun\n");
2718c2ecf20Sopenharmony_ci		err = 1;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	if (flags & I2S_SR_TIFRE)
2758c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "Frame error\n");
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	spin_lock(&i2s->irq_lock);
2788c2ecf20Sopenharmony_ci	if (err && i2s->substream)
2798c2ecf20Sopenharmony_ci		snd_pcm_stop_xrun(i2s->substream);
2808c2ecf20Sopenharmony_ci	spin_unlock(&i2s->irq_lock);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cistatic bool stm32_i2s_readable_reg(struct device *dev, unsigned int reg)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	switch (reg) {
2888c2ecf20Sopenharmony_ci	case STM32_I2S_CR1_REG:
2898c2ecf20Sopenharmony_ci	case STM32_I2S_CFG1_REG:
2908c2ecf20Sopenharmony_ci	case STM32_I2S_CFG2_REG:
2918c2ecf20Sopenharmony_ci	case STM32_I2S_IER_REG:
2928c2ecf20Sopenharmony_ci	case STM32_I2S_SR_REG:
2938c2ecf20Sopenharmony_ci	case STM32_I2S_RXDR_REG:
2948c2ecf20Sopenharmony_ci	case STM32_I2S_CGFR_REG:
2958c2ecf20Sopenharmony_ci	case STM32_I2S_HWCFGR_REG:
2968c2ecf20Sopenharmony_ci	case STM32_I2S_VERR_REG:
2978c2ecf20Sopenharmony_ci	case STM32_I2S_IPIDR_REG:
2988c2ecf20Sopenharmony_ci	case STM32_I2S_SIDR_REG:
2998c2ecf20Sopenharmony_ci		return true;
3008c2ecf20Sopenharmony_ci	default:
3018c2ecf20Sopenharmony_ci		return false;
3028c2ecf20Sopenharmony_ci	}
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic bool stm32_i2s_volatile_reg(struct device *dev, unsigned int reg)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	switch (reg) {
3088c2ecf20Sopenharmony_ci	case STM32_I2S_SR_REG:
3098c2ecf20Sopenharmony_ci	case STM32_I2S_RXDR_REG:
3108c2ecf20Sopenharmony_ci		return true;
3118c2ecf20Sopenharmony_ci	default:
3128c2ecf20Sopenharmony_ci		return false;
3138c2ecf20Sopenharmony_ci	}
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_cistatic bool stm32_i2s_writeable_reg(struct device *dev, unsigned int reg)
3178c2ecf20Sopenharmony_ci{
3188c2ecf20Sopenharmony_ci	switch (reg) {
3198c2ecf20Sopenharmony_ci	case STM32_I2S_CR1_REG:
3208c2ecf20Sopenharmony_ci	case STM32_I2S_CFG1_REG:
3218c2ecf20Sopenharmony_ci	case STM32_I2S_CFG2_REG:
3228c2ecf20Sopenharmony_ci	case STM32_I2S_IER_REG:
3238c2ecf20Sopenharmony_ci	case STM32_I2S_IFCR_REG:
3248c2ecf20Sopenharmony_ci	case STM32_I2S_TXDR_REG:
3258c2ecf20Sopenharmony_ci	case STM32_I2S_CGFR_REG:
3268c2ecf20Sopenharmony_ci		return true;
3278c2ecf20Sopenharmony_ci	default:
3288c2ecf20Sopenharmony_ci		return false;
3298c2ecf20Sopenharmony_ci	}
3308c2ecf20Sopenharmony_ci}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_cistatic int stm32_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
3358c2ecf20Sopenharmony_ci	u32 cgfr;
3368c2ecf20Sopenharmony_ci	u32 cgfr_mask =  I2S_CGFR_I2SSTD_MASK | I2S_CGFR_CKPOL |
3378c2ecf20Sopenharmony_ci			 I2S_CGFR_WSINV | I2S_CGFR_I2SCFG_MASK;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	dev_dbg(cpu_dai->dev, "fmt %x\n", fmt);
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	/*
3428c2ecf20Sopenharmony_ci	 * winv = 0 : default behavior (high/low) for all standards
3438c2ecf20Sopenharmony_ci	 * ckpol = 0 for all standards.
3448c2ecf20Sopenharmony_ci	 */
3458c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
3468c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
3478c2ecf20Sopenharmony_ci		cgfr = I2S_CGFR_I2SSTD_SET(I2S_STD_I2S);
3488c2ecf20Sopenharmony_ci		break;
3498c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_MSB:
3508c2ecf20Sopenharmony_ci		cgfr = I2S_CGFR_I2SSTD_SET(I2S_STD_LEFT_J);
3518c2ecf20Sopenharmony_ci		break;
3528c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_LSB:
3538c2ecf20Sopenharmony_ci		cgfr = I2S_CGFR_I2SSTD_SET(I2S_STD_RIGHT_J);
3548c2ecf20Sopenharmony_ci		break;
3558c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_DSP_A:
3568c2ecf20Sopenharmony_ci		cgfr = I2S_CGFR_I2SSTD_SET(I2S_STD_DSP);
3578c2ecf20Sopenharmony_ci		break;
3588c2ecf20Sopenharmony_ci	/* DSP_B not mapped on I2S PCM long format. 1 bit offset does not fit */
3598c2ecf20Sopenharmony_ci	default:
3608c2ecf20Sopenharmony_ci		dev_err(cpu_dai->dev, "Unsupported protocol %#x\n",
3618c2ecf20Sopenharmony_ci			fmt & SND_SOC_DAIFMT_FORMAT_MASK);
3628c2ecf20Sopenharmony_ci		return -EINVAL;
3638c2ecf20Sopenharmony_ci	}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	/* DAI clock strobing */
3668c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
3678c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_NB_NF:
3688c2ecf20Sopenharmony_ci		break;
3698c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_IB_NF:
3708c2ecf20Sopenharmony_ci		cgfr |= I2S_CGFR_CKPOL;
3718c2ecf20Sopenharmony_ci		break;
3728c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_NB_IF:
3738c2ecf20Sopenharmony_ci		cgfr |= I2S_CGFR_WSINV;
3748c2ecf20Sopenharmony_ci		break;
3758c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_IB_IF:
3768c2ecf20Sopenharmony_ci		cgfr |= I2S_CGFR_CKPOL;
3778c2ecf20Sopenharmony_ci		cgfr |= I2S_CGFR_WSINV;
3788c2ecf20Sopenharmony_ci		break;
3798c2ecf20Sopenharmony_ci	default:
3808c2ecf20Sopenharmony_ci		dev_err(cpu_dai->dev, "Unsupported strobing %#x\n",
3818c2ecf20Sopenharmony_ci			fmt & SND_SOC_DAIFMT_INV_MASK);
3828c2ecf20Sopenharmony_ci		return -EINVAL;
3838c2ecf20Sopenharmony_ci	}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	/* DAI clock master masks */
3868c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
3878c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBM_CFM:
3888c2ecf20Sopenharmony_ci		i2s->ms_flg = I2S_MS_SLAVE;
3898c2ecf20Sopenharmony_ci		break;
3908c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBS_CFS:
3918c2ecf20Sopenharmony_ci		i2s->ms_flg = I2S_MS_MASTER;
3928c2ecf20Sopenharmony_ci		break;
3938c2ecf20Sopenharmony_ci	default:
3948c2ecf20Sopenharmony_ci		dev_err(cpu_dai->dev, "Unsupported mode %#x\n",
3958c2ecf20Sopenharmony_ci			fmt & SND_SOC_DAIFMT_MASTER_MASK);
3968c2ecf20Sopenharmony_ci		return -EINVAL;
3978c2ecf20Sopenharmony_ci	}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	i2s->fmt = fmt;
4008c2ecf20Sopenharmony_ci	return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
4018c2ecf20Sopenharmony_ci				  cgfr_mask, cgfr);
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_cistatic int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
4058c2ecf20Sopenharmony_ci				int clk_id, unsigned int freq, int dir)
4068c2ecf20Sopenharmony_ci{
4078c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz\n", freq);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	if ((dir == SND_SOC_CLOCK_OUT) && STM32_I2S_IS_MASTER(i2s)) {
4128c2ecf20Sopenharmony_ci		i2s->mclk_rate = freq;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci		/* Enable master clock if master mode and mclk-fs are set */
4158c2ecf20Sopenharmony_ci		return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
4168c2ecf20Sopenharmony_ci					  I2S_CGFR_MCKOE, I2S_CGFR_MCKOE);
4178c2ecf20Sopenharmony_ci	}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	return 0;
4208c2ecf20Sopenharmony_ci}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_cistatic int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
4238c2ecf20Sopenharmony_ci				     struct snd_pcm_hw_params *params)
4248c2ecf20Sopenharmony_ci{
4258c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
4268c2ecf20Sopenharmony_ci	unsigned long i2s_clock_rate;
4278c2ecf20Sopenharmony_ci	unsigned int tmp, div, real_div, nb_bits, frame_len;
4288c2ecf20Sopenharmony_ci	unsigned int rate = params_rate(params);
4298c2ecf20Sopenharmony_ci	int ret;
4308c2ecf20Sopenharmony_ci	u32 cgfr, cgfr_mask;
4318c2ecf20Sopenharmony_ci	bool odd;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	if (!(rate % 11025))
4348c2ecf20Sopenharmony_ci		clk_set_parent(i2s->i2sclk, i2s->x11kclk);
4358c2ecf20Sopenharmony_ci	else
4368c2ecf20Sopenharmony_ci		clk_set_parent(i2s->i2sclk, i2s->x8kclk);
4378c2ecf20Sopenharmony_ci	i2s_clock_rate = clk_get_rate(i2s->i2sclk);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	/*
4408c2ecf20Sopenharmony_ci	 * mckl = mclk_ratio x ws
4418c2ecf20Sopenharmony_ci	 *   i2s mode : mclk_ratio = 256
4428c2ecf20Sopenharmony_ci	 *   dsp mode : mclk_ratio = 128
4438c2ecf20Sopenharmony_ci	 *
4448c2ecf20Sopenharmony_ci	 * mclk on
4458c2ecf20Sopenharmony_ci	 *   i2s mode : div = i2s_clk / (mclk_ratio * ws)
4468c2ecf20Sopenharmony_ci	 *   dsp mode : div = i2s_clk / (mclk_ratio * ws)
4478c2ecf20Sopenharmony_ci	 * mclk off
4488c2ecf20Sopenharmony_ci	 *   i2s mode : div = i2s_clk / (nb_bits x ws)
4498c2ecf20Sopenharmony_ci	 *   dsp mode : div = i2s_clk / (nb_bits x ws)
4508c2ecf20Sopenharmony_ci	 */
4518c2ecf20Sopenharmony_ci	if (i2s->mclk_rate) {
4528c2ecf20Sopenharmony_ci		tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, i2s->mclk_rate);
4538c2ecf20Sopenharmony_ci	} else {
4548c2ecf20Sopenharmony_ci		frame_len = 32;
4558c2ecf20Sopenharmony_ci		if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
4568c2ecf20Sopenharmony_ci		    SND_SOC_DAIFMT_DSP_A)
4578c2ecf20Sopenharmony_ci			frame_len = 16;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci		/* master clock not enabled */
4608c2ecf20Sopenharmony_ci		ret = regmap_read(i2s->regmap, STM32_I2S_CGFR_REG, &cgfr);
4618c2ecf20Sopenharmony_ci		if (ret < 0)
4628c2ecf20Sopenharmony_ci			return ret;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci		nb_bits = frame_len * ((cgfr & I2S_CGFR_CHLEN) + 1);
4658c2ecf20Sopenharmony_ci		tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, (nb_bits * rate));
4668c2ecf20Sopenharmony_ci	}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	/* Check the parity of the divider */
4698c2ecf20Sopenharmony_ci	odd = tmp & 0x1;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	/* Compute the div prescaler */
4728c2ecf20Sopenharmony_ci	div = tmp >> 1;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	cgfr = I2S_CGFR_I2SDIV_SET(div) | (odd << I2S_CGFR_ODD_SHIFT);
4758c2ecf20Sopenharmony_ci	cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	real_div = ((2 * div) + odd);
4788c2ecf20Sopenharmony_ci	dev_dbg(cpu_dai->dev, "I2S clk: %ld, SCLK: %d\n",
4798c2ecf20Sopenharmony_ci		i2s_clock_rate, rate);
4808c2ecf20Sopenharmony_ci	dev_dbg(cpu_dai->dev, "Divider: 2*%d(div)+%d(odd) = %d\n",
4818c2ecf20Sopenharmony_ci		div, odd, real_div);
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	if (((div == 1) && odd) || (div > I2S_CGFR_I2SDIV_MAX)) {
4848c2ecf20Sopenharmony_ci		dev_err(cpu_dai->dev, "Wrong divider setting\n");
4858c2ecf20Sopenharmony_ci		return -EINVAL;
4868c2ecf20Sopenharmony_ci	}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	if (!div && !odd)
4898c2ecf20Sopenharmony_ci		dev_warn(cpu_dai->dev, "real divider forced to 1\n");
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
4928c2ecf20Sopenharmony_ci				 cgfr_mask, cgfr);
4938c2ecf20Sopenharmony_ci	if (ret < 0)
4948c2ecf20Sopenharmony_ci		return ret;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	/* Set bitclock and frameclock to their inactive state */
4978c2ecf20Sopenharmony_ci	return regmap_update_bits(i2s->regmap, STM32_I2S_CFG2_REG,
4988c2ecf20Sopenharmony_ci				  I2S_CFG2_AFCNTR, I2S_CFG2_AFCNTR);
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic int stm32_i2s_configure(struct snd_soc_dai *cpu_dai,
5028c2ecf20Sopenharmony_ci			       struct snd_pcm_hw_params *params,
5038c2ecf20Sopenharmony_ci			       struct snd_pcm_substream *substream)
5048c2ecf20Sopenharmony_ci{
5058c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
5068c2ecf20Sopenharmony_ci	int format = params_width(params);
5078c2ecf20Sopenharmony_ci	u32 cfgr, cfgr_mask, cfg1;
5088c2ecf20Sopenharmony_ci	unsigned int fthlv;
5098c2ecf20Sopenharmony_ci	int ret;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	switch (format) {
5128c2ecf20Sopenharmony_ci	case 16:
5138c2ecf20Sopenharmony_ci		cfgr = I2S_CGFR_DATLEN_SET(I2S_I2SMOD_DATLEN_16);
5148c2ecf20Sopenharmony_ci		cfgr_mask = I2S_CGFR_DATLEN_MASK | I2S_CGFR_CHLEN;
5158c2ecf20Sopenharmony_ci		break;
5168c2ecf20Sopenharmony_ci	case 32:
5178c2ecf20Sopenharmony_ci		cfgr = I2S_CGFR_DATLEN_SET(I2S_I2SMOD_DATLEN_32) |
5188c2ecf20Sopenharmony_ci					   I2S_CGFR_CHLEN;
5198c2ecf20Sopenharmony_ci		cfgr_mask = I2S_CGFR_DATLEN_MASK | I2S_CGFR_CHLEN;
5208c2ecf20Sopenharmony_ci		break;
5218c2ecf20Sopenharmony_ci	default:
5228c2ecf20Sopenharmony_ci		dev_err(cpu_dai->dev, "Unexpected format %d", format);
5238c2ecf20Sopenharmony_ci		return -EINVAL;
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	if (STM32_I2S_IS_SLAVE(i2s)) {
5278c2ecf20Sopenharmony_ci		cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_SLAVE);
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci		/* As data length is either 16 or 32 bits, fixch always set */
5308c2ecf20Sopenharmony_ci		cfgr |= I2S_CGFR_FIXCH;
5318c2ecf20Sopenharmony_ci		cfgr_mask |= I2S_CGFR_FIXCH;
5328c2ecf20Sopenharmony_ci	} else {
5338c2ecf20Sopenharmony_ci		cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_MASTER);
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci	cfgr_mask |= I2S_CGFR_I2SCFG_MASK;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
5388c2ecf20Sopenharmony_ci				 cfgr_mask, cfgr);
5398c2ecf20Sopenharmony_ci	if (ret < 0)
5408c2ecf20Sopenharmony_ci		return ret;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	fthlv = STM32_I2S_FIFO_SIZE * I2S_FIFO_TH_ONE_QUARTER / 4;
5438c2ecf20Sopenharmony_ci	cfg1 = I2S_CFG1_FTHVL_SET(fthlv - 1);
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	return regmap_update_bits(i2s->regmap, STM32_I2S_CFG1_REG,
5468c2ecf20Sopenharmony_ci				  I2S_CFG1_FTHVL_MASK, cfg1);
5478c2ecf20Sopenharmony_ci}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_cistatic int stm32_i2s_startup(struct snd_pcm_substream *substream,
5508c2ecf20Sopenharmony_ci			     struct snd_soc_dai *cpu_dai)
5518c2ecf20Sopenharmony_ci{
5528c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
5538c2ecf20Sopenharmony_ci	unsigned long flags;
5548c2ecf20Sopenharmony_ci	int ret;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	spin_lock_irqsave(&i2s->irq_lock, flags);
5578c2ecf20Sopenharmony_ci	i2s->substream = substream;
5588c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&i2s->irq_lock, flags);
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_DSP_A)
5618c2ecf20Sopenharmony_ci		snd_pcm_hw_constraint_single(substream->runtime,
5628c2ecf20Sopenharmony_ci					     SNDRV_PCM_HW_PARAM_CHANNELS, 2);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(i2s->i2sclk);
5658c2ecf20Sopenharmony_ci	if (ret < 0) {
5668c2ecf20Sopenharmony_ci		dev_err(cpu_dai->dev, "Failed to enable clock: %d\n", ret);
5678c2ecf20Sopenharmony_ci		return ret;
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	return regmap_write_bits(i2s->regmap, STM32_I2S_IFCR_REG,
5718c2ecf20Sopenharmony_ci				 I2S_IFCR_MASK, I2S_IFCR_MASK);
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cistatic int stm32_i2s_hw_params(struct snd_pcm_substream *substream,
5758c2ecf20Sopenharmony_ci			       struct snd_pcm_hw_params *params,
5768c2ecf20Sopenharmony_ci			       struct snd_soc_dai *cpu_dai)
5778c2ecf20Sopenharmony_ci{
5788c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
5798c2ecf20Sopenharmony_ci	int ret;
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	ret = stm32_i2s_configure(cpu_dai, params, substream);
5828c2ecf20Sopenharmony_ci	if (ret < 0) {
5838c2ecf20Sopenharmony_ci		dev_err(cpu_dai->dev, "Configuration returned error %d\n", ret);
5848c2ecf20Sopenharmony_ci		return ret;
5858c2ecf20Sopenharmony_ci	}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	if (STM32_I2S_IS_MASTER(i2s))
5888c2ecf20Sopenharmony_ci		ret = stm32_i2s_configure_clock(cpu_dai, params);
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	return ret;
5918c2ecf20Sopenharmony_ci}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_cistatic int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
5948c2ecf20Sopenharmony_ci			     struct snd_soc_dai *cpu_dai)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
5978c2ecf20Sopenharmony_ci	bool playback_flg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
5988c2ecf20Sopenharmony_ci	u32 cfg1_mask, ier;
5998c2ecf20Sopenharmony_ci	int ret;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	switch (cmd) {
6028c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_START:
6038c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_RESUME:
6048c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
6058c2ecf20Sopenharmony_ci		/* Enable i2s */
6068c2ecf20Sopenharmony_ci		dev_dbg(cpu_dai->dev, "start I2S %s\n",
6078c2ecf20Sopenharmony_ci			playback_flg ? "playback" : "capture");
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci		cfg1_mask = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN;
6108c2ecf20Sopenharmony_ci		regmap_update_bits(i2s->regmap, STM32_I2S_CFG1_REG,
6118c2ecf20Sopenharmony_ci				   cfg1_mask, cfg1_mask);
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci		ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG,
6148c2ecf20Sopenharmony_ci					 I2S_CR1_SPE, I2S_CR1_SPE);
6158c2ecf20Sopenharmony_ci		if (ret < 0) {
6168c2ecf20Sopenharmony_ci			dev_err(cpu_dai->dev, "Error %d enabling I2S\n", ret);
6178c2ecf20Sopenharmony_ci			return ret;
6188c2ecf20Sopenharmony_ci		}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci		ret = regmap_write_bits(i2s->regmap, STM32_I2S_CR1_REG,
6218c2ecf20Sopenharmony_ci					I2S_CR1_CSTART, I2S_CR1_CSTART);
6228c2ecf20Sopenharmony_ci		if (ret < 0) {
6238c2ecf20Sopenharmony_ci			dev_err(cpu_dai->dev, "Error %d starting I2S\n", ret);
6248c2ecf20Sopenharmony_ci			return ret;
6258c2ecf20Sopenharmony_ci		}
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci		regmap_write_bits(i2s->regmap, STM32_I2S_IFCR_REG,
6288c2ecf20Sopenharmony_ci				  I2S_IFCR_MASK, I2S_IFCR_MASK);
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci		spin_lock(&i2s->lock_fd);
6318c2ecf20Sopenharmony_ci		i2s->refcount++;
6328c2ecf20Sopenharmony_ci		if (playback_flg) {
6338c2ecf20Sopenharmony_ci			ier = I2S_IER_UDRIE;
6348c2ecf20Sopenharmony_ci		} else {
6358c2ecf20Sopenharmony_ci			ier = I2S_IER_OVRIE;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci			if (STM32_I2S_IS_MASTER(i2s) && i2s->refcount == 1)
6388c2ecf20Sopenharmony_ci				/* dummy write to gate bus clocks */
6398c2ecf20Sopenharmony_ci				regmap_write(i2s->regmap,
6408c2ecf20Sopenharmony_ci					     STM32_I2S_TXDR_REG, 0);
6418c2ecf20Sopenharmony_ci		}
6428c2ecf20Sopenharmony_ci		spin_unlock(&i2s->lock_fd);
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci		if (STM32_I2S_IS_SLAVE(i2s))
6458c2ecf20Sopenharmony_ci			ier |= I2S_IER_TIFREIE;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci		regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, ier, ier);
6488c2ecf20Sopenharmony_ci		break;
6498c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_STOP:
6508c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_SUSPEND:
6518c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
6528c2ecf20Sopenharmony_ci		dev_dbg(cpu_dai->dev, "stop I2S %s\n",
6538c2ecf20Sopenharmony_ci			playback_flg ? "playback" : "capture");
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci		if (playback_flg)
6568c2ecf20Sopenharmony_ci			regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG,
6578c2ecf20Sopenharmony_ci					   I2S_IER_UDRIE,
6588c2ecf20Sopenharmony_ci					   (unsigned int)~I2S_IER_UDRIE);
6598c2ecf20Sopenharmony_ci		else
6608c2ecf20Sopenharmony_ci			regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG,
6618c2ecf20Sopenharmony_ci					   I2S_IER_OVRIE,
6628c2ecf20Sopenharmony_ci					   (unsigned int)~I2S_IER_OVRIE);
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci		spin_lock(&i2s->lock_fd);
6658c2ecf20Sopenharmony_ci		i2s->refcount--;
6668c2ecf20Sopenharmony_ci		if (i2s->refcount) {
6678c2ecf20Sopenharmony_ci			spin_unlock(&i2s->lock_fd);
6688c2ecf20Sopenharmony_ci			break;
6698c2ecf20Sopenharmony_ci		}
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci		ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG,
6728c2ecf20Sopenharmony_ci					 I2S_CR1_SPE, 0);
6738c2ecf20Sopenharmony_ci		if (ret < 0) {
6748c2ecf20Sopenharmony_ci			dev_err(cpu_dai->dev, "Error %d disabling I2S\n", ret);
6758c2ecf20Sopenharmony_ci			spin_unlock(&i2s->lock_fd);
6768c2ecf20Sopenharmony_ci			return ret;
6778c2ecf20Sopenharmony_ci		}
6788c2ecf20Sopenharmony_ci		spin_unlock(&i2s->lock_fd);
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci		cfg1_mask = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN;
6818c2ecf20Sopenharmony_ci		regmap_update_bits(i2s->regmap, STM32_I2S_CFG1_REG,
6828c2ecf20Sopenharmony_ci				   cfg1_mask, 0);
6838c2ecf20Sopenharmony_ci		break;
6848c2ecf20Sopenharmony_ci	default:
6858c2ecf20Sopenharmony_ci		return -EINVAL;
6868c2ecf20Sopenharmony_ci	}
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	return 0;
6898c2ecf20Sopenharmony_ci}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_cistatic void stm32_i2s_shutdown(struct snd_pcm_substream *substream,
6928c2ecf20Sopenharmony_ci			       struct snd_soc_dai *cpu_dai)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
6958c2ecf20Sopenharmony_ci	unsigned long flags;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
6988c2ecf20Sopenharmony_ci			   I2S_CGFR_MCKOE, (unsigned int)~I2S_CGFR_MCKOE);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	clk_disable_unprepare(i2s->i2sclk);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	spin_lock_irqsave(&i2s->irq_lock, flags);
7038c2ecf20Sopenharmony_ci	i2s->substream = NULL;
7048c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&i2s->irq_lock, flags);
7058c2ecf20Sopenharmony_ci}
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_cistatic int stm32_i2s_dai_probe(struct snd_soc_dai *cpu_dai)
7088c2ecf20Sopenharmony_ci{
7098c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = dev_get_drvdata(cpu_dai->dev);
7108c2ecf20Sopenharmony_ci	struct snd_dmaengine_dai_dma_data *dma_data_tx = &i2s->dma_data_tx;
7118c2ecf20Sopenharmony_ci	struct snd_dmaengine_dai_dma_data *dma_data_rx = &i2s->dma_data_rx;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	/* Buswidth will be set by framework */
7148c2ecf20Sopenharmony_ci	dma_data_tx->addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
7158c2ecf20Sopenharmony_ci	dma_data_tx->addr = (dma_addr_t)(i2s->phys_addr) + STM32_I2S_TXDR_REG;
7168c2ecf20Sopenharmony_ci	dma_data_tx->maxburst = 1;
7178c2ecf20Sopenharmony_ci	dma_data_rx->addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
7188c2ecf20Sopenharmony_ci	dma_data_rx->addr = (dma_addr_t)(i2s->phys_addr) + STM32_I2S_RXDR_REG;
7198c2ecf20Sopenharmony_ci	dma_data_rx->maxburst = 1;
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	snd_soc_dai_init_dma_data(cpu_dai, dma_data_tx, dma_data_rx);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	return 0;
7248c2ecf20Sopenharmony_ci}
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_cistatic const struct regmap_config stm32_h7_i2s_regmap_conf = {
7278c2ecf20Sopenharmony_ci	.reg_bits = 32,
7288c2ecf20Sopenharmony_ci	.reg_stride = 4,
7298c2ecf20Sopenharmony_ci	.val_bits = 32,
7308c2ecf20Sopenharmony_ci	.max_register = STM32_I2S_SIDR_REG,
7318c2ecf20Sopenharmony_ci	.readable_reg = stm32_i2s_readable_reg,
7328c2ecf20Sopenharmony_ci	.volatile_reg = stm32_i2s_volatile_reg,
7338c2ecf20Sopenharmony_ci	.writeable_reg = stm32_i2s_writeable_reg,
7348c2ecf20Sopenharmony_ci	.num_reg_defaults_raw = STM32_I2S_SIDR_REG / sizeof(u32) + 1,
7358c2ecf20Sopenharmony_ci	.fast_io = true,
7368c2ecf20Sopenharmony_ci	.cache_type = REGCACHE_FLAT,
7378c2ecf20Sopenharmony_ci};
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops stm32_i2s_pcm_dai_ops = {
7408c2ecf20Sopenharmony_ci	.set_sysclk	= stm32_i2s_set_sysclk,
7418c2ecf20Sopenharmony_ci	.set_fmt	= stm32_i2s_set_dai_fmt,
7428c2ecf20Sopenharmony_ci	.startup	= stm32_i2s_startup,
7438c2ecf20Sopenharmony_ci	.hw_params	= stm32_i2s_hw_params,
7448c2ecf20Sopenharmony_ci	.trigger	= stm32_i2s_trigger,
7458c2ecf20Sopenharmony_ci	.shutdown	= stm32_i2s_shutdown,
7468c2ecf20Sopenharmony_ci};
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_cistatic const struct snd_pcm_hardware stm32_i2s_pcm_hw = {
7498c2ecf20Sopenharmony_ci	.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP,
7508c2ecf20Sopenharmony_ci	.buffer_bytes_max = 8 * PAGE_SIZE,
7518c2ecf20Sopenharmony_ci	.period_bytes_min = 1024,
7528c2ecf20Sopenharmony_ci	.period_bytes_max = 4 * PAGE_SIZE,
7538c2ecf20Sopenharmony_ci	.periods_min = 2,
7548c2ecf20Sopenharmony_ci	.periods_max = 8,
7558c2ecf20Sopenharmony_ci};
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_cistatic const struct snd_dmaengine_pcm_config stm32_i2s_pcm_config = {
7588c2ecf20Sopenharmony_ci	.pcm_hardware	= &stm32_i2s_pcm_hw,
7598c2ecf20Sopenharmony_ci	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
7608c2ecf20Sopenharmony_ci	.prealloc_buffer_size = PAGE_SIZE * 8,
7618c2ecf20Sopenharmony_ci};
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver stm32_i2s_component = {
7648c2ecf20Sopenharmony_ci	.name = "stm32-i2s",
7658c2ecf20Sopenharmony_ci};
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_cistatic void stm32_i2s_dai_init(struct snd_soc_pcm_stream *stream,
7688c2ecf20Sopenharmony_ci			       char *stream_name)
7698c2ecf20Sopenharmony_ci{
7708c2ecf20Sopenharmony_ci	stream->stream_name = stream_name;
7718c2ecf20Sopenharmony_ci	stream->channels_min = 1;
7728c2ecf20Sopenharmony_ci	stream->channels_max = 2;
7738c2ecf20Sopenharmony_ci	stream->rates = SNDRV_PCM_RATE_8000_192000;
7748c2ecf20Sopenharmony_ci	stream->formats = SNDRV_PCM_FMTBIT_S16_LE |
7758c2ecf20Sopenharmony_ci				   SNDRV_PCM_FMTBIT_S32_LE;
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_cistatic int stm32_i2s_dais_init(struct platform_device *pdev,
7798c2ecf20Sopenharmony_ci			       struct stm32_i2s_data *i2s)
7808c2ecf20Sopenharmony_ci{
7818c2ecf20Sopenharmony_ci	struct snd_soc_dai_driver *dai_ptr;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	dai_ptr = devm_kzalloc(&pdev->dev, sizeof(struct snd_soc_dai_driver),
7848c2ecf20Sopenharmony_ci			       GFP_KERNEL);
7858c2ecf20Sopenharmony_ci	if (!dai_ptr)
7868c2ecf20Sopenharmony_ci		return -ENOMEM;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	dai_ptr->probe = stm32_i2s_dai_probe;
7898c2ecf20Sopenharmony_ci	dai_ptr->ops = &stm32_i2s_pcm_dai_ops;
7908c2ecf20Sopenharmony_ci	dai_ptr->id = 1;
7918c2ecf20Sopenharmony_ci	stm32_i2s_dai_init(&dai_ptr->playback, "playback");
7928c2ecf20Sopenharmony_ci	stm32_i2s_dai_init(&dai_ptr->capture, "capture");
7938c2ecf20Sopenharmony_ci	i2s->dai_drv = dai_ptr;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	return 0;
7968c2ecf20Sopenharmony_ci}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_cistatic const struct of_device_id stm32_i2s_ids[] = {
7998c2ecf20Sopenharmony_ci	{
8008c2ecf20Sopenharmony_ci		.compatible = "st,stm32h7-i2s",
8018c2ecf20Sopenharmony_ci		.data = &stm32_h7_i2s_regmap_conf
8028c2ecf20Sopenharmony_ci	},
8038c2ecf20Sopenharmony_ci	{},
8048c2ecf20Sopenharmony_ci};
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_cistatic int stm32_i2s_parse_dt(struct platform_device *pdev,
8078c2ecf20Sopenharmony_ci			      struct stm32_i2s_data *i2s)
8088c2ecf20Sopenharmony_ci{
8098c2ecf20Sopenharmony_ci	struct device_node *np = pdev->dev.of_node;
8108c2ecf20Sopenharmony_ci	const struct of_device_id *of_id;
8118c2ecf20Sopenharmony_ci	struct reset_control *rst;
8128c2ecf20Sopenharmony_ci	struct resource *res;
8138c2ecf20Sopenharmony_ci	int irq, ret;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	if (!np)
8168c2ecf20Sopenharmony_ci		return -ENODEV;
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	of_id = of_match_device(stm32_i2s_ids, &pdev->dev);
8198c2ecf20Sopenharmony_ci	if (of_id)
8208c2ecf20Sopenharmony_ci		i2s->regmap_conf = (const struct regmap_config *)of_id->data;
8218c2ecf20Sopenharmony_ci	else
8228c2ecf20Sopenharmony_ci		return -EINVAL;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8258c2ecf20Sopenharmony_ci	i2s->base = devm_ioremap_resource(&pdev->dev, res);
8268c2ecf20Sopenharmony_ci	if (IS_ERR(i2s->base))
8278c2ecf20Sopenharmony_ci		return PTR_ERR(i2s->base);
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	i2s->phys_addr = res->start;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	/* Get clocks */
8328c2ecf20Sopenharmony_ci	i2s->pclk = devm_clk_get(&pdev->dev, "pclk");
8338c2ecf20Sopenharmony_ci	if (IS_ERR(i2s->pclk)) {
8348c2ecf20Sopenharmony_ci		if (PTR_ERR(i2s->pclk) != -EPROBE_DEFER)
8358c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Could not get pclk: %ld\n",
8368c2ecf20Sopenharmony_ci				PTR_ERR(i2s->pclk));
8378c2ecf20Sopenharmony_ci		return PTR_ERR(i2s->pclk);
8388c2ecf20Sopenharmony_ci	}
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	i2s->i2sclk = devm_clk_get(&pdev->dev, "i2sclk");
8418c2ecf20Sopenharmony_ci	if (IS_ERR(i2s->i2sclk)) {
8428c2ecf20Sopenharmony_ci		if (PTR_ERR(i2s->i2sclk) != -EPROBE_DEFER)
8438c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Could not get i2sclk: %ld\n",
8448c2ecf20Sopenharmony_ci				PTR_ERR(i2s->i2sclk));
8458c2ecf20Sopenharmony_ci		return PTR_ERR(i2s->i2sclk);
8468c2ecf20Sopenharmony_ci	}
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k");
8498c2ecf20Sopenharmony_ci	if (IS_ERR(i2s->x8kclk)) {
8508c2ecf20Sopenharmony_ci		if (PTR_ERR(i2s->x8kclk) != -EPROBE_DEFER)
8518c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Could not get x8k parent clock: %ld\n",
8528c2ecf20Sopenharmony_ci				PTR_ERR(i2s->x8kclk));
8538c2ecf20Sopenharmony_ci		return PTR_ERR(i2s->x8kclk);
8548c2ecf20Sopenharmony_ci	}
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k");
8578c2ecf20Sopenharmony_ci	if (IS_ERR(i2s->x11kclk)) {
8588c2ecf20Sopenharmony_ci		if (PTR_ERR(i2s->x11kclk) != -EPROBE_DEFER)
8598c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Could not get x11k parent clock: %ld\n",
8608c2ecf20Sopenharmony_ci				PTR_ERR(i2s->x11kclk));
8618c2ecf20Sopenharmony_ci		return PTR_ERR(i2s->x11kclk);
8628c2ecf20Sopenharmony_ci	}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	/* Get irqs */
8658c2ecf20Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
8668c2ecf20Sopenharmony_ci	if (irq < 0)
8678c2ecf20Sopenharmony_ci		return irq;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, IRQF_ONESHOT,
8708c2ecf20Sopenharmony_ci			       dev_name(&pdev->dev), i2s);
8718c2ecf20Sopenharmony_ci	if (ret) {
8728c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "irq request returned %d\n", ret);
8738c2ecf20Sopenharmony_ci		return ret;
8748c2ecf20Sopenharmony_ci	}
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	/* Reset */
8778c2ecf20Sopenharmony_ci	rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
8788c2ecf20Sopenharmony_ci	if (IS_ERR(rst)) {
8798c2ecf20Sopenharmony_ci		if (PTR_ERR(rst) != -EPROBE_DEFER)
8808c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Reset controller error %ld\n",
8818c2ecf20Sopenharmony_ci				PTR_ERR(rst));
8828c2ecf20Sopenharmony_ci		return PTR_ERR(rst);
8838c2ecf20Sopenharmony_ci	}
8848c2ecf20Sopenharmony_ci	reset_control_assert(rst);
8858c2ecf20Sopenharmony_ci	udelay(2);
8868c2ecf20Sopenharmony_ci	reset_control_deassert(rst);
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	return 0;
8898c2ecf20Sopenharmony_ci}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_cistatic int stm32_i2s_remove(struct platform_device *pdev)
8928c2ecf20Sopenharmony_ci{
8938c2ecf20Sopenharmony_ci	snd_dmaengine_pcm_unregister(&pdev->dev);
8948c2ecf20Sopenharmony_ci	snd_soc_unregister_component(&pdev->dev);
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	return 0;
8978c2ecf20Sopenharmony_ci}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_cistatic int stm32_i2s_probe(struct platform_device *pdev)
9008c2ecf20Sopenharmony_ci{
9018c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s;
9028c2ecf20Sopenharmony_ci	u32 val;
9038c2ecf20Sopenharmony_ci	int ret;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
9068c2ecf20Sopenharmony_ci	if (!i2s)
9078c2ecf20Sopenharmony_ci		return -ENOMEM;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	ret = stm32_i2s_parse_dt(pdev, i2s);
9108c2ecf20Sopenharmony_ci	if (ret)
9118c2ecf20Sopenharmony_ci		return ret;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	i2s->pdev = pdev;
9148c2ecf20Sopenharmony_ci	i2s->ms_flg = I2S_MS_NOT_SET;
9158c2ecf20Sopenharmony_ci	spin_lock_init(&i2s->lock_fd);
9168c2ecf20Sopenharmony_ci	spin_lock_init(&i2s->irq_lock);
9178c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, i2s);
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	ret = stm32_i2s_dais_init(pdev, i2s);
9208c2ecf20Sopenharmony_ci	if (ret)
9218c2ecf20Sopenharmony_ci		return ret;
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk",
9248c2ecf20Sopenharmony_ci						i2s->base, i2s->regmap_conf);
9258c2ecf20Sopenharmony_ci	if (IS_ERR(i2s->regmap)) {
9268c2ecf20Sopenharmony_ci		if (PTR_ERR(i2s->regmap) != -EPROBE_DEFER)
9278c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Regmap init error %ld\n",
9288c2ecf20Sopenharmony_ci				PTR_ERR(i2s->regmap));
9298c2ecf20Sopenharmony_ci		return PTR_ERR(i2s->regmap);
9308c2ecf20Sopenharmony_ci	}
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	ret = snd_dmaengine_pcm_register(&pdev->dev, &stm32_i2s_pcm_config, 0);
9338c2ecf20Sopenharmony_ci	if (ret) {
9348c2ecf20Sopenharmony_ci		if (ret != -EPROBE_DEFER)
9358c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "PCM DMA register error %d\n", ret);
9368c2ecf20Sopenharmony_ci		return ret;
9378c2ecf20Sopenharmony_ci	}
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	ret = snd_soc_register_component(&pdev->dev, &stm32_i2s_component,
9408c2ecf20Sopenharmony_ci					 i2s->dai_drv, 1);
9418c2ecf20Sopenharmony_ci	if (ret) {
9428c2ecf20Sopenharmony_ci		snd_dmaengine_pcm_unregister(&pdev->dev);
9438c2ecf20Sopenharmony_ci		return ret;
9448c2ecf20Sopenharmony_ci	}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	/* Set SPI/I2S in i2s mode */
9478c2ecf20Sopenharmony_ci	ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
9488c2ecf20Sopenharmony_ci				 I2S_CGFR_I2SMOD, I2S_CGFR_I2SMOD);
9498c2ecf20Sopenharmony_ci	if (ret)
9508c2ecf20Sopenharmony_ci		goto error;
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	ret = regmap_read(i2s->regmap, STM32_I2S_IPIDR_REG, &val);
9538c2ecf20Sopenharmony_ci	if (ret)
9548c2ecf20Sopenharmony_ci		goto error;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	if (val == I2S_IPIDR_NUMBER) {
9578c2ecf20Sopenharmony_ci		ret = regmap_read(i2s->regmap, STM32_I2S_HWCFGR_REG, &val);
9588c2ecf20Sopenharmony_ci		if (ret)
9598c2ecf20Sopenharmony_ci			goto error;
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci		if (!FIELD_GET(I2S_HWCFGR_I2S_SUPPORT_MASK, val)) {
9628c2ecf20Sopenharmony_ci			dev_err(&pdev->dev,
9638c2ecf20Sopenharmony_ci				"Device does not support i2s mode\n");
9648c2ecf20Sopenharmony_ci			ret = -EPERM;
9658c2ecf20Sopenharmony_ci			goto error;
9668c2ecf20Sopenharmony_ci		}
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci		ret = regmap_read(i2s->regmap, STM32_I2S_VERR_REG, &val);
9698c2ecf20Sopenharmony_ci		if (ret)
9708c2ecf20Sopenharmony_ci			goto error;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "I2S version: %lu.%lu registered\n",
9738c2ecf20Sopenharmony_ci			FIELD_GET(I2S_VERR_MAJ_MASK, val),
9748c2ecf20Sopenharmony_ci			FIELD_GET(I2S_VERR_MIN_MASK, val));
9758c2ecf20Sopenharmony_ci	}
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci	return ret;
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_cierror:
9808c2ecf20Sopenharmony_ci	stm32_i2s_remove(pdev);
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	return ret;
9838c2ecf20Sopenharmony_ci}
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, stm32_i2s_ids);
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
9888c2ecf20Sopenharmony_cistatic int stm32_i2s_suspend(struct device *dev)
9898c2ecf20Sopenharmony_ci{
9908c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = dev_get_drvdata(dev);
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	regcache_cache_only(i2s->regmap, true);
9938c2ecf20Sopenharmony_ci	regcache_mark_dirty(i2s->regmap);
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	return 0;
9968c2ecf20Sopenharmony_ci}
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_cistatic int stm32_i2s_resume(struct device *dev)
9998c2ecf20Sopenharmony_ci{
10008c2ecf20Sopenharmony_ci	struct stm32_i2s_data *i2s = dev_get_drvdata(dev);
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	regcache_cache_only(i2s->regmap, false);
10038c2ecf20Sopenharmony_ci	return regcache_sync(i2s->regmap);
10048c2ecf20Sopenharmony_ci}
10058c2ecf20Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_cistatic const struct dev_pm_ops stm32_i2s_pm_ops = {
10088c2ecf20Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(stm32_i2s_suspend, stm32_i2s_resume)
10098c2ecf20Sopenharmony_ci};
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_cistatic struct platform_driver stm32_i2s_driver = {
10128c2ecf20Sopenharmony_ci	.driver = {
10138c2ecf20Sopenharmony_ci		.name = "st,stm32-i2s",
10148c2ecf20Sopenharmony_ci		.of_match_table = stm32_i2s_ids,
10158c2ecf20Sopenharmony_ci		.pm = &stm32_i2s_pm_ops,
10168c2ecf20Sopenharmony_ci	},
10178c2ecf20Sopenharmony_ci	.probe = stm32_i2s_probe,
10188c2ecf20Sopenharmony_ci	.remove = stm32_i2s_remove,
10198c2ecf20Sopenharmony_ci};
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_cimodule_platform_driver(stm32_i2s_driver);
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("STM32 Soc i2s Interface");
10248c2ecf20Sopenharmony_ciMODULE_AUTHOR("Olivier Moysan, <olivier.moysan@st.com>");
10258c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:stm32-i2s");
10268c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1027