summaryrefslogtreecommitdiff
path: root/sound/soc/stm/stm32_sai.h
blob: 33e4bff8c2f575d9fe92b06efcae88577463d6b7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * STM32 ALSA SoC Digital Audio Interface (SAI) driver.
 *
 * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
 * Author(s): Olivier Moysan <olivier.moysan@st.com> for STMicroelectronics.
 */

#include <linux/bitfield.h>

/******************** SAI Register Map **************************************/

/* Global configuration register */
#define STM_SAI_GCR		0x00

/* Sub-block A&B registers offsets, relative to A&B sub-block addresses */
#define STM_SAI_CR1_REGX	0x00	/* A offset: 0x04. B offset: 0x24 */
#define STM_SAI_CR2_REGX	0x04
#define STM_SAI_FRCR_REGX	0x08
#define STM_SAI_SLOTR_REGX	0x0C
#define STM_SAI_IMR_REGX	0x10
#define STM_SAI_SR_REGX		0x14
#define STM_SAI_CLRFR_REGX	0x18
#define STM_SAI_DR_REGX		0x1C

/* Sub-block A registers, relative to sub-block A address */
#define STM_SAI_PDMCR_REGX	0x40
#define STM_SAI_PDMLY_REGX	0x44

/* Hardware configuration registers */
#define STM_SAI_HWCFGR		0x3F0
#define STM_SAI_VERR		0x3F4
#define STM_SAI_IDR		0x3F8
#define STM_SAI_SIDR		0x3FC

/******************** Bit definition for SAI_GCR register *******************/
#define SAI_GCR_SYNCIN_SHIFT	0
#define SAI_GCR_SYNCIN_WDTH	2
#define SAI_GCR_SYNCIN_MASK	GENMASK(1, SAI_GCR_SYNCIN_SHIFT)
#define SAI_GCR_SYNCIN_MAX	FIELD_GET(SAI_GCR_SYNCIN_MASK,\
				SAI_GCR_SYNCIN_MASK)

#define SAI_GCR_SYNCOUT_SHIFT	4
#define SAI_GCR_SYNCOUT_MASK	GENMASK(5, SAI_GCR_SYNCOUT_SHIFT)

/******************* Bit definition for SAI_XCR1 register *******************/
#define SAI_XCR1_RX_TX_SHIFT	0
#define SAI_XCR1_RX_TX		BIT(SAI_XCR1_RX_TX_SHIFT)
#define SAI_XCR1_SLAVE_SHIFT	1
#define SAI_XCR1_SLAVE		BIT(SAI_XCR1_SLAVE_SHIFT)

#define SAI_XCR1_PRTCFG_SHIFT	2
#define SAI_XCR1_PRTCFG_MASK	GENMASK(3, SAI_XCR1_PRTCFG_SHIFT)
#define SAI_XCR1_PRTCFG_SET(x)	((x) << SAI_XCR1_PRTCFG_SHIFT)

#define SAI_XCR1_DS_SHIFT	5
#define SAI_XCR1_DS_MASK	GENMASK(7, SAI_XCR1_DS_SHIFT)
#define SAI_XCR1_DS_SET(x)	((x) << SAI_XCR1_DS_SHIFT)

#define SAI_XCR1_LSBFIRST_SHIFT	8
#define SAI_XCR1_LSBFIRST	BIT(SAI_XCR1_LSBFIRST_SHIFT)
#define SAI_XCR1_CKSTR_SHIFT	9
#define SAI_XCR1_CKSTR		BIT(SAI_XCR1_CKSTR_SHIFT)

#define SAI_XCR1_SYNCEN_SHIFT	10
#define SAI_XCR1_SYNCEN_MASK	GENMASK(11, SAI_XCR1_SYNCEN_SHIFT)
#define SAI_XCR1_SYNCEN_SET(x)	((x) << SAI_XCR1_SYNCEN_SHIFT)

#define SAI_XCR1_MONO_SHIFT	12
#define SAI_XCR1_MONO		BIT(SAI_XCR1_MONO_SHIFT)
#define SAI_XCR1_OUTDRIV_SHIFT	13
#define SAI_XCR1_OUTDRIV	BIT(SAI_XCR1_OUTDRIV_SHIFT)
#define SAI_XCR1_SAIEN_SHIFT	16
#define SAI_XCR1_SAIEN		BIT(SAI_XCR1_SAIEN_SHIFT)
#define SAI_XCR1_DMAEN_SHIFT	17
#define SAI_XCR1_DMAEN		BIT(SAI_XCR1_DMAEN_SHIFT)
#define SAI_XCR1_NODIV_SHIFT	19
#define SAI_XCR1_NODIV		BIT(SAI_XCR1_NODIV_SHIFT)

#define SAI_XCR1_MCKDIV_SHIFT	20
#define SAI_XCR1_MCKDIV_WIDTH(x)	(((x) == STM_SAI_STM32F4) ? 4 : 6)
#define SAI_XCR1_MCKDIV_MASK(x) GENMASK((SAI_XCR1_MCKDIV_SHIFT + (x) - 1),\
				SAI_XCR1_MCKDIV_SHIFT)
#define SAI_XCR1_MCKDIV_SET(x)	((x) << SAI_XCR1_MCKDIV_SHIFT)
#define SAI_XCR1_MCKDIV_MAX(x)	((1 << SAI_XCR1_MCKDIV_WIDTH(x)) - 1)

#define SAI_XCR1_OSR_SHIFT	26
#define SAI_XCR1_OSR		BIT(SAI_XCR1_OSR_SHIFT)

#define SAI_XCR1_MCKEN_SHIFT	27
#define SAI_XCR1_MCKEN		BIT(SAI_XCR1_MCKEN_SHIFT)

/******************* Bit definition for SAI_XCR2 register *******************/
#define SAI_XCR2_FTH_SHIFT	0
#define SAI_XCR2_FTH_MASK	GENMASK(2, SAI_XCR2_FTH_SHIFT)
#define SAI_XCR2_FTH_SET(x)	((x) << SAI_XCR2_FTH_SHIFT)

#define SAI_XCR2_FFLUSH_SHIFT	3
#define SAI_XCR2_FFLUSH		BIT(SAI_XCR2_FFLUSH_SHIFT)
#define SAI_XCR2_TRIS_SHIFT	4
#define SAI_XCR2_TRIS		BIT(SAI_XCR2_TRIS_SHIFT)
#define SAI_XCR2_MUTE_SHIFT	5
#define SAI_XCR2_MUTE		BIT(SAI_XCR2_MUTE_SHIFT)
#define SAI_XCR2_MUTEVAL_SHIFT	6
#define SAI_XCR2_MUTEVAL	BIT(SAI_XCR2_MUTEVAL_SHIFT)

#define SAI_XCR2_MUTECNT_SHIFT	7
#define SAI_XCR2_MUTECNT_MASK	GENMASK(12, SAI_XCR2_MUTECNT_SHIFT)
#define SAI_XCR2_MUTECNT_SET(x)	((x) << SAI_XCR2_MUTECNT_SHIFT)

#define SAI_XCR2_CPL_SHIFT	13
#define SAI_XCR2_CPL		BIT(SAI_XCR2_CPL_SHIFT)

#define SAI_XCR2_COMP_SHIFT	14
#define SAI_XCR2_COMP_MASK	GENMASK(15, SAI_XCR2_COMP_SHIFT)
#define SAI_XCR2_COMP_SET(x)	((x) << SAI_XCR2_COMP_SHIFT)

/****************** Bit definition for SAI_XFRCR register *******************/
#define SAI_XFRCR_FRL_SHIFT	0
#define SAI_XFRCR_FRL_MASK	GENMASK(7, SAI_XFRCR_FRL_SHIFT)
#define SAI_XFRCR_FRL_SET(x)	((x) << SAI_XFRCR_FRL_SHIFT)

#define SAI_XFRCR_FSALL_SHIFT	8
#define SAI_XFRCR_FSALL_MASK	GENMASK(14, SAI_XFRCR_FSALL_SHIFT)
#define SAI_XFRCR_FSALL_SET(x)	((x) << SAI_XFRCR_FSALL_SHIFT)

#define SAI_XFRCR_FSDEF_SHIFT	16
#define SAI_XFRCR_FSDEF		BIT(SAI_XFRCR_FSDEF_SHIFT)
#define SAI_XFRCR_FSPOL_SHIFT	17
#define SAI_XFRCR_FSPOL		BIT(SAI_XFRCR_FSPOL_SHIFT)
#define SAI_XFRCR_FSOFF_SHIFT	18
#define SAI_XFRCR_FSOFF		BIT(SAI_XFRCR_FSOFF_SHIFT)

/****************** Bit definition for SAI_XSLOTR register ******************/
#define SAI_XSLOTR_FBOFF_SHIFT	0
#define SAI_XSLOTR_FBOFF_MASK	GENMASK(4, SAI_XSLOTR_FBOFF_SHIFT)
#define SAI_XSLOTR_FBOFF_SET(x)	((x) << SAI_XSLOTR_FBOFF_SHIFT)

#define SAI_XSLOTR_SLOTSZ_SHIFT	6
#define SAI_XSLOTR_SLOTSZ_MASK	GENMASK(7, SAI_XSLOTR_SLOTSZ_SHIFT)
#define SAI_XSLOTR_SLOTSZ_SET(x)	((x) << SAI_XSLOTR_SLOTSZ_SHIFT)

#define SAI_XSLOTR_NBSLOT_SHIFT 8
#define SAI_XSLOTR_NBSLOT_MASK	GENMASK(11, SAI_XSLOTR_NBSLOT_SHIFT)
#define SAI_XSLOTR_NBSLOT_SET(x) ((x) << SAI_XSLOTR_NBSLOT_SHIFT)

#define SAI_XSLOTR_SLOTEN_SHIFT	16
#define SAI_XSLOTR_SLOTEN_WIDTH	16
#define SAI_XSLOTR_SLOTEN_MASK	GENMASK(31, SAI_XSLOTR_SLOTEN_SHIFT)
#define SAI_XSLOTR_SLOTEN_SET(x) ((x) << SAI_XSLOTR_SLOTEN_SHIFT)

/******************* Bit definition for SAI_XIMR register *******************/
#define SAI_XIMR_OVRUDRIE	BIT(0)
#define SAI_XIMR_MUTEDETIE	BIT(1)
#define SAI_XIMR_WCKCFGIE	BIT(2)
#define SAI_XIMR_FREQIE		BIT(3)
#define SAI_XIMR_CNRDYIE	BIT(4)
#define SAI_XIMR_AFSDETIE	BIT(5)
#define SAI_XIMR_LFSDETIE	BIT(6)

#define SAI_XIMR_SHIFT	0
#define SAI_XIMR_MASK		GENMASK(6, SAI_XIMR_SHIFT)

/******************** Bit definition for SAI_XSR register *******************/
#define SAI_XSR_OVRUDR		BIT(0)
#define SAI_XSR_MUTEDET		BIT(1)
#define SAI_XSR_WCKCFG		BIT(2)
#define SAI_XSR_FREQ		BIT(3)
#define SAI_XSR_CNRDY		BIT(4)
#define SAI_XSR_AFSDET		BIT(5)
#define SAI_XSR_LFSDET		BIT(6)

#define SAI_XSR_SHIFT	0
#define SAI_XSR_MASK		GENMASK(6, SAI_XSR_SHIFT)

/****************** Bit definition for SAI_XCLRFR register ******************/
#define SAI_XCLRFR_COVRUDR	BIT(0)
#define SAI_XCLRFR_CMUTEDET	BIT(1)
#define SAI_XCLRFR_CWCKCFG	BIT(2)
#define SAI_XCLRFR_CFREQ	BIT(3)
#define SAI_XCLRFR_CCNRDY	BIT(4)
#define SAI_XCLRFR_CAFSDET	BIT(5)
#define SAI_XCLRFR_CLFSDET	BIT(6)

#define SAI_XCLRFR_SHIFT	0
#define SAI_XCLRFR_MASK		GENMASK(6, SAI_XCLRFR_SHIFT)

/****************** Bit definition for SAI_PDMCR register ******************/
#define SAI_PDMCR_PDMEN		BIT(0)

#define SAI_PDMCR_MICNBR_SHIFT	4
#define SAI_PDMCR_MICNBR_MASK	GENMASK(5, SAI_PDMCR_MICNBR_SHIFT)
#define SAI_PDMCR_MICNBR_SET(x)	((x) << SAI_PDMCR_MICNBR_SHIFT)

#define SAI_PDMCR_CKEN1		BIT(8)
#define SAI_PDMCR_CKEN2		BIT(9)
#define SAI_PDMCR_CKEN3		BIT(10)
#define SAI_PDMCR_CKEN4		BIT(11)

/****************** Bit definition for (SAI_PDMDLY register ****************/
#define SAI_PDMDLY_1L_SHIFT	0
#define SAI_PDMDLY_1L_MASK	GENMASK(2, SAI_PDMDLY_1L_SHIFT)
#define SAI_PDMDLY_1L_WIDTH	3

#define SAI_PDMDLY_1R_SHIFT	4
#define SAI_PDMDLY_1R_MASK	GENMASK(6, SAI_PDMDLY_1R_SHIFT)
#define SAI_PDMDLY_1R_WIDTH	3

#define SAI_PDMDLY_2L_SHIFT	8
#define SAI_PDMDLY_2L_MASK	GENMASK(10, SAI_PDMDLY_2L_SHIFT)
#define SAI_PDMDLY_2L_WIDTH	3

#define SAI_PDMDLY_2R_SHIFT	12
#define SAI_PDMDLY_2R_MASK	GENMASK(14, SAI_PDMDLY_2R_SHIFT)
#define SAI_PDMDLY_2R_WIDTH	3

#define SAI_PDMDLY_3L_SHIFT	16
#define SAI_PDMDLY_3L_MASK	GENMASK(18, SAI_PDMDLY_3L_SHIFT)
#define SAI_PDMDLY_3L_WIDTH	3

#define SAI_PDMDLY_3R_SHIFT	20
#define SAI_PDMDLY_3R_MASK	GENMASK(22, SAI_PDMDLY_3R_SHIFT)
#define SAI_PDMDLY_3R_WIDTH	3

#define SAI_PDMDLY_4L_SHIFT	24
#define SAI_PDMDLY_4L_MASK	GENMASK(26, SAI_PDMDLY_4L_SHIFT)
#define SAI_PDMDLY_4L_WIDTH	3

#define SAI_PDMDLY_4R_SHIFT	28
#define SAI_PDMDLY_4R_MASK	GENMASK(30, SAI_PDMDLY_4R_SHIFT)
#define SAI_PDMDLY_4R_WIDTH	3

/* Registers below apply to SAI version 2.1 and more */

/* Bit definition for SAI_HWCFGR register */
#define SAI_HWCFGR_FIFO_SIZE	GENMASK(7, 0)
#define SAI_HWCFGR_SPDIF_PDM	GENMASK(11, 8)
#define SAI_HWCFGR_REGOUT	GENMASK(19, 12)

/* Bit definition for SAI_VERR register */
#define SAI_VERR_MIN_MASK	GENMASK(3, 0)
#define SAI_VERR_MAJ_MASK	GENMASK(7, 4)

/* Bit definition for SAI_IDR register */
#define SAI_IDR_ID_MASK		GENMASK(31, 0)

/* Bit definition for SAI_SIDR register */
#define SAI_SIDR_ID_MASK	GENMASK(31, 0)

#define SAI_IPIDR_NUMBER	0x00130031

/* SAI version numbers are 1.x for F4. Major version number set to 1 for F4 */
#define STM_SAI_STM32F4		BIT(4)
/* Dummy version number for H7 socs and next */
#define STM_SAI_STM32H7		0x0

#define STM_SAI_IS_F4(ip)	((ip)->conf.version == STM_SAI_STM32F4)
#define STM_SAI_HAS_SPDIF_PDM(ip)\
				((ip)->pdata->conf.has_spdif_pdm)

enum stm32_sai_syncout {
	STM_SAI_SYNC_OUT_NONE,
	STM_SAI_SYNC_OUT_A,
	STM_SAI_SYNC_OUT_B,
};

/**
 * struct stm32_sai_conf - SAI configuration
 * @version: SAI version
 * @fifo_size: SAI fifo size as words number
 * @has_spdif_pdm: SAI S/PDIF and PDM features support flag
 */
struct stm32_sai_conf {
	u32 version;
	u32 fifo_size;
	bool has_spdif_pdm;
};

/**
 * struct stm32_sai_data - private data of SAI instance driver
 * @pdev: device data pointer
 * @base: common register bank virtual base address
 * @pclk: SAI bus clock
 * @clk_x8k: SAI parent clock for sampling frequencies multiple of 8kHz
 * @clk_x11k: SAI parent clock for sampling frequencies multiple of 11kHz
 * @conf: SAI hardware capabitilites
 * @irq: SAI interrupt line
 * @set_sync: pointer to synchro mode configuration callback
 * @gcr: SAI Global Configuration Register
 */
struct stm32_sai_data {
	struct platform_device *pdev;
	void __iomem *base;
	struct clk *pclk;
	struct clk *clk_x8k;
	struct clk *clk_x11k;
	struct stm32_sai_conf conf;
	int irq;
	int (*set_sync)(struct stm32_sai_data *sai,
			struct device_node *np_provider, int synco, int synci);
	u32 gcr;
};