]>
Commit | Line | Data |
---|---|---|
03e4d5d5 | 1 | /* |
2 | * STM32 ALSA SoC Digital Audio Interface (SPDIF-rx) driver. | |
3 | * | |
4 | * Copyright (C) 2017, STMicroelectronics - All Rights Reserved | |
5 | * Author(s): Olivier Moysan <olivier.moysan@st.com> for STMicroelectronics. | |
6 | * | |
7 | * License terms: GPL V2.0. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify it | |
10 | * under the terms of the GNU General Public License version 2 as published by | |
11 | * the Free Software Foundation. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | |
16 | * details. | |
17 | */ | |
18 | ||
19 | #include <linux/clk.h> | |
20 | #include <linux/completion.h> | |
21 | #include <linux/delay.h> | |
22 | #include <linux/module.h> | |
23 | #include <linux/of_platform.h> | |
24 | #include <linux/regmap.h> | |
25 | #include <linux/reset.h> | |
26 | ||
27 | #include <sound/dmaengine_pcm.h> | |
28 | #include <sound/pcm_params.h> | |
29 | ||
30 | /* SPDIF-rx Register Map */ | |
31 | #define STM32_SPDIFRX_CR 0x00 | |
32 | #define STM32_SPDIFRX_IMR 0x04 | |
33 | #define STM32_SPDIFRX_SR 0x08 | |
34 | #define STM32_SPDIFRX_IFCR 0x0C | |
35 | #define STM32_SPDIFRX_DR 0x10 | |
36 | #define STM32_SPDIFRX_CSR 0x14 | |
37 | #define STM32_SPDIFRX_DIR 0x18 | |
38 | ||
39 | /* Bit definition for SPDIF_CR register */ | |
40 | #define SPDIFRX_CR_SPDIFEN_SHIFT 0 | |
41 | #define SPDIFRX_CR_SPDIFEN_MASK GENMASK(1, SPDIFRX_CR_SPDIFEN_SHIFT) | |
42 | #define SPDIFRX_CR_SPDIFENSET(x) ((x) << SPDIFRX_CR_SPDIFEN_SHIFT) | |
43 | ||
44 | #define SPDIFRX_CR_RXDMAEN BIT(2) | |
45 | #define SPDIFRX_CR_RXSTEO BIT(3) | |
46 | ||
47 | #define SPDIFRX_CR_DRFMT_SHIFT 4 | |
48 | #define SPDIFRX_CR_DRFMT_MASK GENMASK(5, SPDIFRX_CR_DRFMT_SHIFT) | |
49 | #define SPDIFRX_CR_DRFMTSET(x) ((x) << SPDIFRX_CR_DRFMT_SHIFT) | |
50 | ||
51 | #define SPDIFRX_CR_PMSK BIT(6) | |
52 | #define SPDIFRX_CR_VMSK BIT(7) | |
53 | #define SPDIFRX_CR_CUMSK BIT(8) | |
54 | #define SPDIFRX_CR_PTMSK BIT(9) | |
55 | #define SPDIFRX_CR_CBDMAEN BIT(10) | |
56 | #define SPDIFRX_CR_CHSEL_SHIFT 11 | |
57 | #define SPDIFRX_CR_CHSEL BIT(SPDIFRX_CR_CHSEL_SHIFT) | |
58 | ||
59 | #define SPDIFRX_CR_NBTR_SHIFT 12 | |
60 | #define SPDIFRX_CR_NBTR_MASK GENMASK(13, SPDIFRX_CR_NBTR_SHIFT) | |
61 | #define SPDIFRX_CR_NBTRSET(x) ((x) << SPDIFRX_CR_NBTR_SHIFT) | |
62 | ||
63 | #define SPDIFRX_CR_WFA BIT(14) | |
64 | ||
65 | #define SPDIFRX_CR_INSEL_SHIFT 16 | |
66 | #define SPDIFRX_CR_INSEL_MASK GENMASK(18, PDIFRX_CR_INSEL_SHIFT) | |
67 | #define SPDIFRX_CR_INSELSET(x) ((x) << SPDIFRX_CR_INSEL_SHIFT) | |
68 | ||
69 | #define SPDIFRX_CR_CKSEN_SHIFT 20 | |
70 | #define SPDIFRX_CR_CKSEN BIT(20) | |
71 | #define SPDIFRX_CR_CKSBKPEN BIT(21) | |
72 | ||
73 | /* Bit definition for SPDIFRX_IMR register */ | |
74 | #define SPDIFRX_IMR_RXNEI BIT(0) | |
75 | #define SPDIFRX_IMR_CSRNEIE BIT(1) | |
76 | #define SPDIFRX_IMR_PERRIE BIT(2) | |
77 | #define SPDIFRX_IMR_OVRIE BIT(3) | |
78 | #define SPDIFRX_IMR_SBLKIE BIT(4) | |
79 | #define SPDIFRX_IMR_SYNCDIE BIT(5) | |
80 | #define SPDIFRX_IMR_IFEIE BIT(6) | |
81 | ||
82 | #define SPDIFRX_XIMR_MASK GENMASK(6, 0) | |
83 | ||
84 | /* Bit definition for SPDIFRX_SR register */ | |
85 | #define SPDIFRX_SR_RXNE BIT(0) | |
86 | #define SPDIFRX_SR_CSRNE BIT(1) | |
87 | #define SPDIFRX_SR_PERR BIT(2) | |
88 | #define SPDIFRX_SR_OVR BIT(3) | |
89 | #define SPDIFRX_SR_SBD BIT(4) | |
90 | #define SPDIFRX_SR_SYNCD BIT(5) | |
91 | #define SPDIFRX_SR_FERR BIT(6) | |
92 | #define SPDIFRX_SR_SERR BIT(7) | |
93 | #define SPDIFRX_SR_TERR BIT(8) | |
94 | ||
95 | #define SPDIFRX_SR_WIDTH5_SHIFT 16 | |
96 | #define SPDIFRX_SR_WIDTH5_MASK GENMASK(30, PDIFRX_SR_WIDTH5_SHIFT) | |
97 | #define SPDIFRX_SR_WIDTH5SET(x) ((x) << SPDIFRX_SR_WIDTH5_SHIFT) | |
98 | ||
99 | /* Bit definition for SPDIFRX_IFCR register */ | |
100 | #define SPDIFRX_IFCR_PERRCF BIT(2) | |
101 | #define SPDIFRX_IFCR_OVRCF BIT(3) | |
102 | #define SPDIFRX_IFCR_SBDCF BIT(4) | |
103 | #define SPDIFRX_IFCR_SYNCDCF BIT(5) | |
104 | ||
105 | #define SPDIFRX_XIFCR_MASK GENMASK(5, 2) | |
106 | ||
107 | /* Bit definition for SPDIFRX_DR register (DRFMT = 0b00) */ | |
108 | #define SPDIFRX_DR0_DR_SHIFT 0 | |
109 | #define SPDIFRX_DR0_DR_MASK GENMASK(23, SPDIFRX_DR0_DR_SHIFT) | |
110 | #define SPDIFRX_DR0_DRSET(x) ((x) << SPDIFRX_DR0_DR_SHIFT) | |
111 | ||
112 | #define SPDIFRX_DR0_PE BIT(24) | |
113 | ||
114 | #define SPDIFRX_DR0_V BIT(25) | |
115 | #define SPDIFRX_DR0_U BIT(26) | |
116 | #define SPDIFRX_DR0_C BIT(27) | |
117 | ||
118 | #define SPDIFRX_DR0_PT_SHIFT 28 | |
119 | #define SPDIFRX_DR0_PT_MASK GENMASK(29, SPDIFRX_DR0_PT_SHIFT) | |
120 | #define SPDIFRX_DR0_PTSET(x) ((x) << SPDIFRX_DR0_PT_SHIFT) | |
121 | ||
122 | /* Bit definition for SPDIFRX_DR register (DRFMT = 0b01) */ | |
123 | #define SPDIFRX_DR1_PE BIT(0) | |
124 | #define SPDIFRX_DR1_V BIT(1) | |
125 | #define SPDIFRX_DR1_U BIT(2) | |
126 | #define SPDIFRX_DR1_C BIT(3) | |
127 | ||
128 | #define SPDIFRX_DR1_PT_SHIFT 4 | |
129 | #define SPDIFRX_DR1_PT_MASK GENMASK(5, SPDIFRX_DR1_PT_SHIFT) | |
130 | #define SPDIFRX_DR1_PTSET(x) ((x) << SPDIFRX_DR1_PT_SHIFT) | |
131 | ||
132 | #define SPDIFRX_DR1_DR_SHIFT 8 | |
133 | #define SPDIFRX_DR1_DR_MASK GENMASK(31, SPDIFRX_DR1_DR_SHIFT) | |
134 | #define SPDIFRX_DR1_DRSET(x) ((x) << SPDIFRX_DR1_DR_SHIFT) | |
135 | ||
136 | /* Bit definition for SPDIFRX_DR register (DRFMT = 0b10) */ | |
137 | #define SPDIFRX_DR1_DRNL1_SHIFT 0 | |
138 | #define SPDIFRX_DR1_DRNL1_MASK GENMASK(15, SPDIFRX_DR1_DRNL1_SHIFT) | |
139 | #define SPDIFRX_DR1_DRNL1SET(x) ((x) << SPDIFRX_DR1_DRNL1_SHIFT) | |
140 | ||
141 | #define SPDIFRX_DR1_DRNL2_SHIFT 16 | |
142 | #define SPDIFRX_DR1_DRNL2_MASK GENMASK(31, SPDIFRX_DR1_DRNL2_SHIFT) | |
143 | #define SPDIFRX_DR1_DRNL2SET(x) ((x) << SPDIFRX_DR1_DRNL2_SHIFT) | |
144 | ||
145 | /* Bit definition for SPDIFRX_CSR register */ | |
146 | #define SPDIFRX_CSR_USR_SHIFT 0 | |
147 | #define SPDIFRX_CSR_USR_MASK GENMASK(15, SPDIFRX_CSR_USR_SHIFT) | |
148 | #define SPDIFRX_CSR_USRGET(x) (((x) & SPDIFRX_CSR_USR_MASK)\ | |
149 | >> SPDIFRX_CSR_USR_SHIFT) | |
150 | ||
151 | #define SPDIFRX_CSR_CS_SHIFT 16 | |
152 | #define SPDIFRX_CSR_CS_MASK GENMASK(23, SPDIFRX_CSR_CS_SHIFT) | |
153 | #define SPDIFRX_CSR_CSGET(x) (((x) & SPDIFRX_CSR_CS_MASK)\ | |
154 | >> SPDIFRX_CSR_CS_SHIFT) | |
155 | ||
156 | #define SPDIFRX_CSR_SOB BIT(24) | |
157 | ||
158 | /* Bit definition for SPDIFRX_DIR register */ | |
159 | #define SPDIFRX_DIR_THI_SHIFT 0 | |
160 | #define SPDIFRX_DIR_THI_MASK GENMASK(12, SPDIFRX_DIR_THI_SHIFT) | |
161 | #define SPDIFRX_DIR_THI_SET(x) ((x) << SPDIFRX_DIR_THI_SHIFT) | |
162 | ||
163 | #define SPDIFRX_DIR_TLO_SHIFT 16 | |
164 | #define SPDIFRX_DIR_TLO_MASK GENMASK(28, SPDIFRX_DIR_TLO_SHIFT) | |
165 | #define SPDIFRX_DIR_TLO_SET(x) ((x) << SPDIFRX_DIR_TLO_SHIFT) | |
166 | ||
167 | #define SPDIFRX_SPDIFEN_DISABLE 0x0 | |
168 | #define SPDIFRX_SPDIFEN_SYNC 0x1 | |
169 | #define SPDIFRX_SPDIFEN_ENABLE 0x3 | |
170 | ||
171 | #define SPDIFRX_IN1 0x1 | |
172 | #define SPDIFRX_IN2 0x2 | |
173 | #define SPDIFRX_IN3 0x3 | |
174 | #define SPDIFRX_IN4 0x4 | |
175 | #define SPDIFRX_IN5 0x5 | |
176 | #define SPDIFRX_IN6 0x6 | |
177 | #define SPDIFRX_IN7 0x7 | |
178 | #define SPDIFRX_IN8 0x8 | |
179 | ||
180 | #define SPDIFRX_NBTR_NONE 0x0 | |
181 | #define SPDIFRX_NBTR_3 0x1 | |
182 | #define SPDIFRX_NBTR_15 0x2 | |
183 | #define SPDIFRX_NBTR_63 0x3 | |
184 | ||
185 | #define SPDIFRX_DRFMT_RIGHT 0x0 | |
186 | #define SPDIFRX_DRFMT_LEFT 0x1 | |
187 | #define SPDIFRX_DRFMT_PACKED 0x2 | |
188 | ||
189 | /* 192 CS bits in S/PDIF frame. i.e 24 CS bytes */ | |
190 | #define SPDIFRX_CS_BYTES_NB 24 | |
191 | #define SPDIFRX_UB_BYTES_NB 48 | |
192 | ||
193 | /* | |
194 | * CSR register is retrieved as a 32 bits word | |
195 | * It contains 1 channel status byte and 2 user data bytes | |
196 | * 2 S/PDIF frames are acquired to get all CS/UB bits | |
197 | */ | |
198 | #define SPDIFRX_CSR_BUF_LENGTH (SPDIFRX_CS_BYTES_NB * 4 * 2) | |
199 | ||
200 | /** | |
201 | * struct stm32_spdifrx_data - private data of SPDIFRX | |
202 | * @pdev: device data pointer | |
203 | * @base: mmio register base virtual address | |
204 | * @regmap: SPDIFRX register map pointer | |
205 | * @regmap_conf: SPDIFRX register map configuration pointer | |
206 | * @cs_completion: channel status retrieving completion | |
207 | * @kclk: kernel clock feeding the SPDIFRX clock generator | |
208 | * @dma_params: dma configuration data for rx channel | |
209 | * @substream: PCM substream data pointer | |
210 | * @dmab: dma buffer info pointer | |
211 | * @ctrl_chan: dma channel for S/PDIF control bits | |
212 | * @desc:dma async transaction descriptor | |
213 | * @slave_config: dma slave channel runtime config pointer | |
214 | * @phys_addr: SPDIFRX registers physical base address | |
215 | * @lock: synchronization enabling lock | |
f063c5e0 | 216 | * @irq_lock: prevent race condition with IRQ on stream state |
03e4d5d5 | 217 | * @cs: channel status buffer |
218 | * @ub: user data buffer | |
219 | * @irq: SPDIFRX interrupt line | |
220 | * @refcount: keep count of opened DMA channels | |
221 | */ | |
222 | struct stm32_spdifrx_data { | |
223 | struct platform_device *pdev; | |
224 | void __iomem *base; | |
225 | struct regmap *regmap; | |
226 | const struct regmap_config *regmap_conf; | |
227 | struct completion cs_completion; | |
228 | struct clk *kclk; | |
229 | struct snd_dmaengine_dai_dma_data dma_params; | |
230 | struct snd_pcm_substream *substream; | |
231 | struct snd_dma_buffer *dmab; | |
232 | struct dma_chan *ctrl_chan; | |
233 | struct dma_async_tx_descriptor *desc; | |
234 | struct dma_slave_config slave_config; | |
235 | dma_addr_t phys_addr; | |
236 | spinlock_t lock; /* Sync enabling lock */ | |
f063c5e0 | 237 | spinlock_t irq_lock; /* Prevent race condition on stream state */ |
03e4d5d5 | 238 | unsigned char cs[SPDIFRX_CS_BYTES_NB]; |
239 | unsigned char ub[SPDIFRX_UB_BYTES_NB]; | |
240 | int irq; | |
241 | int refcount; | |
242 | }; | |
243 | ||
244 | static void stm32_spdifrx_dma_complete(void *data) | |
245 | { | |
246 | struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)data; | |
247 | struct platform_device *pdev = spdifrx->pdev; | |
248 | u32 *p_start = (u32 *)spdifrx->dmab->area; | |
249 | u32 *p_end = p_start + (2 * SPDIFRX_CS_BYTES_NB) - 1; | |
250 | u32 *ptr = p_start; | |
251 | u16 *ub_ptr = (short *)spdifrx->ub; | |
252 | int i = 0; | |
253 | ||
254 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
255 | SPDIFRX_CR_CBDMAEN, | |
256 | (unsigned int)~SPDIFRX_CR_CBDMAEN); | |
257 | ||
258 | if (!spdifrx->dmab->area) | |
259 | return; | |
260 | ||
261 | while (ptr <= p_end) { | |
262 | if (*ptr & SPDIFRX_CSR_SOB) | |
263 | break; | |
264 | ptr++; | |
265 | } | |
266 | ||
267 | if (ptr > p_end) { | |
268 | dev_err(&pdev->dev, "Start of S/PDIF block not found\n"); | |
269 | return; | |
270 | } | |
271 | ||
272 | while (i < SPDIFRX_CS_BYTES_NB) { | |
273 | spdifrx->cs[i] = (unsigned char)SPDIFRX_CSR_CSGET(*ptr); | |
274 | *ub_ptr++ = SPDIFRX_CSR_USRGET(*ptr++); | |
275 | if (ptr > p_end) { | |
276 | dev_err(&pdev->dev, "Failed to get channel status\n"); | |
277 | return; | |
278 | } | |
279 | i++; | |
280 | } | |
281 | ||
282 | complete(&spdifrx->cs_completion); | |
283 | } | |
284 | ||
285 | static int stm32_spdifrx_dma_ctrl_start(struct stm32_spdifrx_data *spdifrx) | |
286 | { | |
287 | dma_cookie_t cookie; | |
288 | int err; | |
289 | ||
290 | spdifrx->desc = dmaengine_prep_slave_single(spdifrx->ctrl_chan, | |
291 | spdifrx->dmab->addr, | |
292 | SPDIFRX_CSR_BUF_LENGTH, | |
293 | DMA_DEV_TO_MEM, | |
294 | DMA_CTRL_ACK); | |
295 | if (!spdifrx->desc) | |
296 | return -EINVAL; | |
297 | ||
298 | spdifrx->desc->callback = stm32_spdifrx_dma_complete; | |
299 | spdifrx->desc->callback_param = spdifrx; | |
300 | cookie = dmaengine_submit(spdifrx->desc); | |
301 | err = dma_submit_error(cookie); | |
302 | if (err) | |
303 | return -EINVAL; | |
304 | ||
305 | dma_async_issue_pending(spdifrx->ctrl_chan); | |
306 | ||
307 | return 0; | |
308 | } | |
309 | ||
310 | static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx) | |
311 | { | |
312 | dmaengine_terminate_async(spdifrx->ctrl_chan); | |
313 | } | |
314 | ||
315 | static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) | |
316 | { | |
317 | int cr, cr_mask, imr, ret; | |
6b6f099c | 318 | unsigned long flags; |
03e4d5d5 | 319 | |
320 | /* Enable IRQs */ | |
321 | imr = SPDIFRX_IMR_IFEIE | SPDIFRX_IMR_SYNCDIE | SPDIFRX_IMR_PERRIE; | |
322 | ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, imr, imr); | |
323 | if (ret) | |
324 | return ret; | |
325 | ||
6b6f099c | 326 | spin_lock_irqsave(&spdifrx->lock, flags); |
03e4d5d5 | 327 | |
328 | spdifrx->refcount++; | |
329 | ||
330 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_CR, &cr); | |
331 | ||
332 | if (!(cr & SPDIFRX_CR_SPDIFEN_MASK)) { | |
333 | /* | |
334 | * Start sync if SPDIFRX is still in idle state. | |
335 | * SPDIFRX reception enabled when sync done | |
336 | */ | |
337 | dev_dbg(&spdifrx->pdev->dev, "start synchronization\n"); | |
338 | ||
339 | /* | |
340 | * SPDIFRX configuration: | |
341 | * Wait for activity before starting sync process. This avoid | |
342 | * to issue sync errors when spdif signal is missing on input. | |
343 | * Preamble, CS, user, validity and parity error bits not copied | |
344 | * to DR register. | |
345 | */ | |
346 | cr = SPDIFRX_CR_WFA | SPDIFRX_CR_PMSK | SPDIFRX_CR_VMSK | | |
347 | SPDIFRX_CR_CUMSK | SPDIFRX_CR_PTMSK | SPDIFRX_CR_RXSTEO; | |
348 | cr_mask = cr; | |
349 | ||
350 | cr |= SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_SYNC); | |
351 | cr_mask |= SPDIFRX_CR_SPDIFEN_MASK; | |
352 | ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
353 | cr_mask, cr); | |
354 | if (ret < 0) | |
355 | dev_err(&spdifrx->pdev->dev, | |
356 | "Failed to start synchronization\n"); | |
357 | } | |
358 | ||
6b6f099c | 359 | spin_unlock_irqrestore(&spdifrx->lock, flags); |
03e4d5d5 | 360 | |
361 | return ret; | |
362 | } | |
363 | ||
364 | static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx) | |
365 | { | |
366 | int cr, cr_mask, reg; | |
6b6f099c | 367 | unsigned long flags; |
03e4d5d5 | 368 | |
6b6f099c | 369 | spin_lock_irqsave(&spdifrx->lock, flags); |
03e4d5d5 | 370 | |
371 | if (--spdifrx->refcount) { | |
6b6f099c | 372 | spin_unlock_irqrestore(&spdifrx->lock, flags); |
03e4d5d5 | 373 | return; |
374 | } | |
375 | ||
376 | cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE); | |
377 | cr_mask = SPDIFRX_CR_SPDIFEN_MASK | SPDIFRX_CR_RXDMAEN; | |
378 | ||
379 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, cr_mask, cr); | |
380 | ||
381 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, | |
382 | SPDIFRX_XIMR_MASK, 0); | |
383 | ||
384 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IFCR, | |
385 | SPDIFRX_XIFCR_MASK, SPDIFRX_XIFCR_MASK); | |
386 | ||
387 | /* dummy read to clear CSRNE and RXNE in status register */ | |
388 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_DR, ®); | |
389 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_CSR, ®); | |
390 | ||
6b6f099c | 391 | spin_unlock_irqrestore(&spdifrx->lock, flags); |
03e4d5d5 | 392 | } |
393 | ||
394 | static int stm32_spdifrx_dma_ctrl_register(struct device *dev, | |
395 | struct stm32_spdifrx_data *spdifrx) | |
396 | { | |
397 | int ret; | |
398 | ||
98c8dc2f | 399 | spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl"); |
400 | if (IS_ERR(spdifrx->ctrl_chan)) { | |
401 | dev_err(dev, "dma_request_slave_channel failed\n"); | |
402 | return PTR_ERR(spdifrx->ctrl_chan); | |
403 | } | |
404 | ||
03e4d5d5 | 405 | spdifrx->dmab = devm_kzalloc(dev, sizeof(struct snd_dma_buffer), |
406 | GFP_KERNEL); | |
407 | if (!spdifrx->dmab) | |
408 | return -ENOMEM; | |
409 | ||
410 | spdifrx->dmab->dev.type = SNDRV_DMA_TYPE_DEV_IRAM; | |
411 | spdifrx->dmab->dev.dev = dev; | |
412 | ret = snd_dma_alloc_pages(spdifrx->dmab->dev.type, dev, | |
413 | SPDIFRX_CSR_BUF_LENGTH, spdifrx->dmab); | |
414 | if (ret < 0) { | |
415 | dev_err(dev, "snd_dma_alloc_pages returned error %d\n", ret); | |
416 | return ret; | |
417 | } | |
418 | ||
03e4d5d5 | 419 | spdifrx->slave_config.direction = DMA_DEV_TO_MEM; |
420 | spdifrx->slave_config.src_addr = (dma_addr_t)(spdifrx->phys_addr + | |
421 | STM32_SPDIFRX_CSR); | |
422 | spdifrx->slave_config.dst_addr = spdifrx->dmab->addr; | |
423 | spdifrx->slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | |
424 | spdifrx->slave_config.src_maxburst = 1; | |
425 | ||
426 | ret = dmaengine_slave_config(spdifrx->ctrl_chan, | |
427 | &spdifrx->slave_config); | |
428 | if (ret < 0) { | |
429 | dev_err(dev, "dmaengine_slave_config returned error %d\n", ret); | |
03e4d5d5 | 430 | spdifrx->ctrl_chan = NULL; |
431 | } | |
432 | ||
433 | return ret; | |
434 | }; | |
435 | ||
436 | static const char * const spdifrx_enum_input[] = { | |
437 | "in0", "in1", "in2", "in3" | |
438 | }; | |
439 | ||
440 | /* By default CS bits are retrieved from channel A */ | |
441 | static const char * const spdifrx_enum_cs_channel[] = { | |
442 | "A", "B" | |
443 | }; | |
444 | ||
445 | static SOC_ENUM_SINGLE_DECL(ctrl_enum_input, | |
446 | STM32_SPDIFRX_CR, SPDIFRX_CR_INSEL_SHIFT, | |
447 | spdifrx_enum_input); | |
448 | ||
449 | static SOC_ENUM_SINGLE_DECL(ctrl_enum_cs_channel, | |
450 | STM32_SPDIFRX_CR, SPDIFRX_CR_CHSEL_SHIFT, | |
451 | spdifrx_enum_cs_channel); | |
452 | ||
453 | static int stm32_spdifrx_info(struct snd_kcontrol *kcontrol, | |
454 | struct snd_ctl_elem_info *uinfo) | |
455 | { | |
456 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | |
457 | uinfo->count = 1; | |
458 | ||
459 | return 0; | |
460 | } | |
461 | ||
462 | static int stm32_spdifrx_ub_info(struct snd_kcontrol *kcontrol, | |
463 | struct snd_ctl_elem_info *uinfo) | |
464 | { | |
465 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | |
466 | uinfo->count = 1; | |
467 | ||
468 | return 0; | |
469 | } | |
470 | ||
471 | static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx) | |
472 | { | |
473 | int ret = 0; | |
474 | ||
475 | memset(spdifrx->cs, 0, SPDIFRX_CS_BYTES_NB); | |
476 | memset(spdifrx->ub, 0, SPDIFRX_UB_BYTES_NB); | |
477 | ||
478 | ret = stm32_spdifrx_dma_ctrl_start(spdifrx); | |
479 | if (ret < 0) | |
480 | return ret; | |
481 | ||
482 | ret = clk_prepare_enable(spdifrx->kclk); | |
483 | if (ret) { | |
484 | dev_err(&spdifrx->pdev->dev, "Enable kclk failed: %d\n", ret); | |
485 | return ret; | |
486 | } | |
487 | ||
488 | ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
489 | SPDIFRX_CR_CBDMAEN, SPDIFRX_CR_CBDMAEN); | |
490 | if (ret < 0) | |
491 | goto end; | |
492 | ||
493 | ret = stm32_spdifrx_start_sync(spdifrx); | |
494 | if (ret < 0) | |
495 | goto end; | |
496 | ||
497 | if (wait_for_completion_interruptible_timeout(&spdifrx->cs_completion, | |
498 | msecs_to_jiffies(100)) | |
499 | <= 0) { | |
500 | dev_err(&spdifrx->pdev->dev, "Failed to get control data\n"); | |
501 | ret = -EAGAIN; | |
502 | } | |
503 | ||
504 | stm32_spdifrx_stop(spdifrx); | |
505 | stm32_spdifrx_dma_ctrl_stop(spdifrx); | |
506 | ||
507 | end: | |
508 | clk_disable_unprepare(spdifrx->kclk); | |
509 | ||
510 | return ret; | |
511 | } | |
512 | ||
513 | static int stm32_spdifrx_capture_get(struct snd_kcontrol *kcontrol, | |
514 | struct snd_ctl_elem_value *ucontrol) | |
515 | { | |
516 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
517 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
518 | ||
519 | stm32_spdifrx_get_ctrl_data(spdifrx); | |
520 | ||
521 | ucontrol->value.iec958.status[0] = spdifrx->cs[0]; | |
522 | ucontrol->value.iec958.status[1] = spdifrx->cs[1]; | |
523 | ucontrol->value.iec958.status[2] = spdifrx->cs[2]; | |
524 | ucontrol->value.iec958.status[3] = spdifrx->cs[3]; | |
525 | ucontrol->value.iec958.status[4] = spdifrx->cs[4]; | |
526 | ||
527 | return 0; | |
528 | } | |
529 | ||
530 | static int stm32_spdif_user_bits_get(struct snd_kcontrol *kcontrol, | |
531 | struct snd_ctl_elem_value *ucontrol) | |
532 | { | |
533 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
534 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
535 | ||
536 | stm32_spdifrx_get_ctrl_data(spdifrx); | |
537 | ||
538 | ucontrol->value.iec958.status[0] = spdifrx->ub[0]; | |
539 | ucontrol->value.iec958.status[1] = spdifrx->ub[1]; | |
540 | ucontrol->value.iec958.status[2] = spdifrx->ub[2]; | |
541 | ucontrol->value.iec958.status[3] = spdifrx->ub[3]; | |
542 | ucontrol->value.iec958.status[4] = spdifrx->ub[4]; | |
543 | ||
544 | return 0; | |
545 | } | |
546 | ||
547 | static struct snd_kcontrol_new stm32_spdifrx_iec_ctrls[] = { | |
548 | /* Channel status control */ | |
549 | { | |
550 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
551 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), | |
552 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
553 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
554 | .info = stm32_spdifrx_info, | |
555 | .get = stm32_spdifrx_capture_get, | |
556 | }, | |
557 | /* User bits control */ | |
558 | { | |
559 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
560 | .name = "IEC958 User Bit Capture Default", | |
561 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
562 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
563 | .info = stm32_spdifrx_ub_info, | |
564 | .get = stm32_spdif_user_bits_get, | |
565 | }, | |
566 | }; | |
567 | ||
568 | static struct snd_kcontrol_new stm32_spdifrx_ctrls[] = { | |
569 | SOC_ENUM("SPDIFRX input", ctrl_enum_input), | |
570 | SOC_ENUM("SPDIFRX CS channel", ctrl_enum_cs_channel), | |
571 | }; | |
572 | ||
573 | static int stm32_spdifrx_dai_register_ctrls(struct snd_soc_dai *cpu_dai) | |
574 | { | |
575 | int ret; | |
576 | ||
577 | ret = snd_soc_add_dai_controls(cpu_dai, stm32_spdifrx_iec_ctrls, | |
578 | ARRAY_SIZE(stm32_spdifrx_iec_ctrls)); | |
579 | if (ret < 0) | |
580 | return ret; | |
581 | ||
582 | return snd_soc_add_component_controls(cpu_dai->component, | |
583 | stm32_spdifrx_ctrls, | |
584 | ARRAY_SIZE(stm32_spdifrx_ctrls)); | |
585 | } | |
586 | ||
587 | static int stm32_spdifrx_dai_probe(struct snd_soc_dai *cpu_dai) | |
588 | { | |
589 | struct stm32_spdifrx_data *spdifrx = dev_get_drvdata(cpu_dai->dev); | |
590 | ||
591 | spdifrx->dma_params.addr = (dma_addr_t)(spdifrx->phys_addr + | |
592 | STM32_SPDIFRX_DR); | |
593 | spdifrx->dma_params.maxburst = 1; | |
594 | ||
595 | snd_soc_dai_init_dma_data(cpu_dai, NULL, &spdifrx->dma_params); | |
596 | ||
597 | return stm32_spdifrx_dai_register_ctrls(cpu_dai); | |
598 | } | |
599 | ||
600 | static bool stm32_spdifrx_readable_reg(struct device *dev, unsigned int reg) | |
601 | { | |
602 | switch (reg) { | |
603 | case STM32_SPDIFRX_CR: | |
604 | case STM32_SPDIFRX_IMR: | |
605 | case STM32_SPDIFRX_SR: | |
606 | case STM32_SPDIFRX_IFCR: | |
607 | case STM32_SPDIFRX_DR: | |
608 | case STM32_SPDIFRX_CSR: | |
609 | case STM32_SPDIFRX_DIR: | |
610 | return true; | |
611 | default: | |
612 | return false; | |
613 | } | |
614 | } | |
615 | ||
616 | static bool stm32_spdifrx_volatile_reg(struct device *dev, unsigned int reg) | |
617 | { | |
618 | if (reg == STM32_SPDIFRX_DR) | |
619 | return true; | |
620 | ||
621 | return false; | |
622 | } | |
623 | ||
624 | static bool stm32_spdifrx_writeable_reg(struct device *dev, unsigned int reg) | |
625 | { | |
626 | switch (reg) { | |
627 | case STM32_SPDIFRX_CR: | |
628 | case STM32_SPDIFRX_IMR: | |
629 | case STM32_SPDIFRX_IFCR: | |
630 | return true; | |
631 | default: | |
632 | return false; | |
633 | } | |
634 | } | |
635 | ||
636 | static const struct regmap_config stm32_h7_spdifrx_regmap_conf = { | |
637 | .reg_bits = 32, | |
638 | .reg_stride = 4, | |
639 | .val_bits = 32, | |
640 | .max_register = STM32_SPDIFRX_DIR, | |
641 | .readable_reg = stm32_spdifrx_readable_reg, | |
642 | .volatile_reg = stm32_spdifrx_volatile_reg, | |
643 | .writeable_reg = stm32_spdifrx_writeable_reg, | |
644 | .fast_io = true, | |
645 | }; | |
646 | ||
647 | static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) | |
648 | { | |
649 | struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid; | |
03e4d5d5 | 650 | struct platform_device *pdev = spdifrx->pdev; |
651 | unsigned int cr, mask, sr, imr; | |
652 | unsigned int flags; | |
653 | int err = 0, err_xrun = 0; | |
654 | ||
655 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_SR, &sr); | |
656 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_IMR, &imr); | |
657 | ||
658 | mask = imr & SPDIFRX_XIMR_MASK; | |
659 | /* SERR, TERR, FERR IRQs are generated if IFEIE is set */ | |
660 | if (mask & SPDIFRX_IMR_IFEIE) | |
661 | mask |= (SPDIFRX_IMR_IFEIE << 1) | (SPDIFRX_IMR_IFEIE << 2); | |
662 | ||
663 | flags = sr & mask; | |
664 | if (!flags) { | |
665 | dev_err(&pdev->dev, "Unexpected IRQ. rflags=%#x, imr=%#x\n", | |
666 | sr, imr); | |
667 | return IRQ_NONE; | |
668 | } | |
669 | ||
670 | /* Clear IRQs */ | |
671 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IFCR, | |
672 | SPDIFRX_XIFCR_MASK, flags); | |
673 | ||
674 | if (flags & SPDIFRX_SR_PERR) { | |
675 | dev_dbg(&pdev->dev, "Parity error\n"); | |
676 | err_xrun = 1; | |
677 | } | |
678 | ||
679 | if (flags & SPDIFRX_SR_OVR) { | |
680 | dev_dbg(&pdev->dev, "Overrun error\n"); | |
681 | err_xrun = 1; | |
682 | } | |
683 | ||
684 | if (flags & SPDIFRX_SR_SBD) | |
685 | dev_dbg(&pdev->dev, "Synchronization block detected\n"); | |
686 | ||
687 | if (flags & SPDIFRX_SR_SYNCD) { | |
688 | dev_dbg(&pdev->dev, "Synchronization done\n"); | |
689 | ||
690 | /* Enable spdifrx */ | |
691 | cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_ENABLE); | |
692 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
693 | SPDIFRX_CR_SPDIFEN_MASK, cr); | |
694 | } | |
695 | ||
696 | if (flags & SPDIFRX_SR_FERR) { | |
697 | dev_dbg(&pdev->dev, "Frame error\n"); | |
698 | err = 1; | |
699 | } | |
700 | ||
701 | if (flags & SPDIFRX_SR_SERR) { | |
702 | dev_dbg(&pdev->dev, "Synchronization error\n"); | |
703 | err = 1; | |
704 | } | |
705 | ||
706 | if (flags & SPDIFRX_SR_TERR) { | |
707 | dev_dbg(&pdev->dev, "Timeout error\n"); | |
708 | err = 1; | |
709 | } | |
710 | ||
711 | if (err) { | |
712 | /* SPDIFRX in STATE_STOP. Disable SPDIFRX to clear errors */ | |
713 | cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE); | |
714 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
715 | SPDIFRX_CR_SPDIFEN_MASK, cr); | |
716 | ||
f063c5e0 OM |
717 | spin_lock(&spdifrx->irq_lock); |
718 | if (spdifrx->substream) | |
719 | snd_pcm_stop(spdifrx->substream, | |
720 | SNDRV_PCM_STATE_DISCONNECTED); | |
721 | spin_unlock(&spdifrx->irq_lock); | |
03e4d5d5 | 722 | |
723 | return IRQ_HANDLED; | |
724 | } | |
725 | ||
f063c5e0 OM |
726 | spin_lock(&spdifrx->irq_lock); |
727 | if (err_xrun && spdifrx->substream) | |
728 | snd_pcm_stop_xrun(spdifrx->substream); | |
729 | spin_unlock(&spdifrx->irq_lock); | |
03e4d5d5 | 730 | |
731 | return IRQ_HANDLED; | |
732 | } | |
733 | ||
734 | static int stm32_spdifrx_startup(struct snd_pcm_substream *substream, | |
735 | struct snd_soc_dai *cpu_dai) | |
736 | { | |
737 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
f063c5e0 | 738 | unsigned long flags; |
03e4d5d5 | 739 | int ret; |
740 | ||
f063c5e0 | 741 | spin_lock_irqsave(&spdifrx->irq_lock, flags); |
03e4d5d5 | 742 | spdifrx->substream = substream; |
f063c5e0 | 743 | spin_unlock_irqrestore(&spdifrx->irq_lock, flags); |
03e4d5d5 | 744 | |
745 | ret = clk_prepare_enable(spdifrx->kclk); | |
746 | if (ret) | |
747 | dev_err(&spdifrx->pdev->dev, "Enable kclk failed: %d\n", ret); | |
748 | ||
749 | return ret; | |
750 | } | |
751 | ||
752 | static int stm32_spdifrx_hw_params(struct snd_pcm_substream *substream, | |
753 | struct snd_pcm_hw_params *params, | |
754 | struct snd_soc_dai *cpu_dai) | |
755 | { | |
756 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
757 | int data_size = params_width(params); | |
758 | int fmt; | |
759 | ||
760 | switch (data_size) { | |
761 | case 16: | |
762 | fmt = SPDIFRX_DRFMT_PACKED; | |
03e4d5d5 | 763 | break; |
764 | case 32: | |
765 | fmt = SPDIFRX_DRFMT_LEFT; | |
03e4d5d5 | 766 | break; |
767 | default: | |
768 | dev_err(&spdifrx->pdev->dev, "Unexpected data format\n"); | |
769 | return -EINVAL; | |
770 | } | |
771 | ||
9036e4ac | 772 | /* |
773 | * Set buswidth to 4 bytes for all data formats. | |
774 | * Packed format: transfer 2 x 2 bytes samples | |
775 | * Left format: transfer 1 x 3 bytes samples + 1 dummy byte | |
776 | */ | |
777 | spdifrx->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | |
03e4d5d5 | 778 | snd_soc_dai_init_dma_data(cpu_dai, NULL, &spdifrx->dma_params); |
779 | ||
780 | return regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
781 | SPDIFRX_CR_DRFMT_MASK, | |
782 | SPDIFRX_CR_DRFMTSET(fmt)); | |
783 | } | |
784 | ||
785 | static int stm32_spdifrx_trigger(struct snd_pcm_substream *substream, int cmd, | |
786 | struct snd_soc_dai *cpu_dai) | |
787 | { | |
788 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
789 | int ret = 0; | |
790 | ||
791 | switch (cmd) { | |
792 | case SNDRV_PCM_TRIGGER_START: | |
793 | case SNDRV_PCM_TRIGGER_RESUME: | |
794 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | |
795 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, | |
796 | SPDIFRX_IMR_OVRIE, SPDIFRX_IMR_OVRIE); | |
797 | ||
798 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
799 | SPDIFRX_CR_RXDMAEN, SPDIFRX_CR_RXDMAEN); | |
800 | ||
801 | ret = stm32_spdifrx_start_sync(spdifrx); | |
802 | break; | |
803 | case SNDRV_PCM_TRIGGER_SUSPEND: | |
804 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | |
805 | case SNDRV_PCM_TRIGGER_STOP: | |
806 | stm32_spdifrx_stop(spdifrx); | |
807 | break; | |
808 | default: | |
809 | return -EINVAL; | |
810 | } | |
811 | ||
812 | return ret; | |
813 | } | |
814 | ||
815 | static void stm32_spdifrx_shutdown(struct snd_pcm_substream *substream, | |
816 | struct snd_soc_dai *cpu_dai) | |
817 | { | |
818 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
f063c5e0 | 819 | unsigned long flags; |
03e4d5d5 | 820 | |
f063c5e0 | 821 | spin_lock_irqsave(&spdifrx->irq_lock, flags); |
03e4d5d5 | 822 | spdifrx->substream = NULL; |
f063c5e0 OM |
823 | spin_unlock_irqrestore(&spdifrx->irq_lock, flags); |
824 | ||
03e4d5d5 | 825 | clk_disable_unprepare(spdifrx->kclk); |
826 | } | |
827 | ||
828 | static const struct snd_soc_dai_ops stm32_spdifrx_pcm_dai_ops = { | |
829 | .startup = stm32_spdifrx_startup, | |
830 | .hw_params = stm32_spdifrx_hw_params, | |
831 | .trigger = stm32_spdifrx_trigger, | |
832 | .shutdown = stm32_spdifrx_shutdown, | |
833 | }; | |
834 | ||
835 | static struct snd_soc_dai_driver stm32_spdifrx_dai[] = { | |
836 | { | |
837 | .name = "spdifrx-capture-cpu-dai", | |
838 | .probe = stm32_spdifrx_dai_probe, | |
839 | .capture = { | |
840 | .stream_name = "CPU-Capture", | |
841 | .channels_min = 1, | |
842 | .channels_max = 2, | |
843 | .rates = SNDRV_PCM_RATE_8000_192000, | |
844 | .formats = SNDRV_PCM_FMTBIT_S32_LE | | |
845 | SNDRV_PCM_FMTBIT_S16_LE, | |
846 | }, | |
847 | .ops = &stm32_spdifrx_pcm_dai_ops, | |
848 | } | |
849 | }; | |
850 | ||
851 | static const struct snd_pcm_hardware stm32_spdifrx_pcm_hw = { | |
852 | .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP, | |
853 | .buffer_bytes_max = 8 * PAGE_SIZE, | |
854 | .period_bytes_max = 2048, /* MDMA constraint */ | |
855 | .periods_min = 2, | |
856 | .periods_max = 8, | |
857 | }; | |
858 | ||
859 | static const struct snd_soc_component_driver stm32_spdifrx_component = { | |
860 | .name = "stm32-spdifrx", | |
861 | }; | |
862 | ||
863 | static const struct snd_dmaengine_pcm_config stm32_spdifrx_pcm_config = { | |
864 | .pcm_hardware = &stm32_spdifrx_pcm_hw, | |
865 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, | |
866 | }; | |
867 | ||
868 | static const struct of_device_id stm32_spdifrx_ids[] = { | |
869 | { | |
870 | .compatible = "st,stm32h7-spdifrx", | |
871 | .data = &stm32_h7_spdifrx_regmap_conf | |
872 | }, | |
873 | {} | |
874 | }; | |
875 | ||
876 | static int stm_spdifrx_parse_of(struct platform_device *pdev, | |
877 | struct stm32_spdifrx_data *spdifrx) | |
878 | { | |
879 | struct device_node *np = pdev->dev.of_node; | |
880 | const struct of_device_id *of_id; | |
881 | struct resource *res; | |
882 | ||
883 | if (!np) | |
884 | return -ENODEV; | |
885 | ||
886 | of_id = of_match_device(stm32_spdifrx_ids, &pdev->dev); | |
887 | if (of_id) | |
888 | spdifrx->regmap_conf = | |
889 | (const struct regmap_config *)of_id->data; | |
890 | else | |
891 | return -EINVAL; | |
892 | ||
893 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
894 | spdifrx->base = devm_ioremap_resource(&pdev->dev, res); | |
895 | if (IS_ERR(spdifrx->base)) | |
896 | return PTR_ERR(spdifrx->base); | |
897 | ||
898 | spdifrx->phys_addr = res->start; | |
899 | ||
900 | spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk"); | |
901 | if (IS_ERR(spdifrx->kclk)) { | |
902 | dev_err(&pdev->dev, "Could not get kclk\n"); | |
903 | return PTR_ERR(spdifrx->kclk); | |
904 | } | |
905 | ||
906 | spdifrx->irq = platform_get_irq(pdev, 0); | |
907 | if (spdifrx->irq < 0) { | |
908 | dev_err(&pdev->dev, "No irq for node %s\n", pdev->name); | |
909 | return spdifrx->irq; | |
910 | } | |
911 | ||
912 | return 0; | |
913 | } | |
914 | ||
915 | static int stm32_spdifrx_probe(struct platform_device *pdev) | |
916 | { | |
917 | struct stm32_spdifrx_data *spdifrx; | |
918 | struct reset_control *rst; | |
919 | const struct snd_dmaengine_pcm_config *pcm_config = NULL; | |
920 | int ret; | |
921 | ||
922 | spdifrx = devm_kzalloc(&pdev->dev, sizeof(*spdifrx), GFP_KERNEL); | |
923 | if (!spdifrx) | |
924 | return -ENOMEM; | |
925 | ||
926 | spdifrx->pdev = pdev; | |
927 | init_completion(&spdifrx->cs_completion); | |
928 | spin_lock_init(&spdifrx->lock); | |
f063c5e0 | 929 | spin_lock_init(&spdifrx->irq_lock); |
03e4d5d5 | 930 | |
931 | platform_set_drvdata(pdev, spdifrx); | |
932 | ||
933 | ret = stm_spdifrx_parse_of(pdev, spdifrx); | |
934 | if (ret) | |
935 | return ret; | |
936 | ||
937 | spdifrx->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "kclk", | |
938 | spdifrx->base, | |
939 | spdifrx->regmap_conf); | |
940 | if (IS_ERR(spdifrx->regmap)) { | |
941 | dev_err(&pdev->dev, "Regmap init failed\n"); | |
942 | return PTR_ERR(spdifrx->regmap); | |
943 | } | |
944 | ||
945 | ret = devm_request_irq(&pdev->dev, spdifrx->irq, stm32_spdifrx_isr, 0, | |
946 | dev_name(&pdev->dev), spdifrx); | |
947 | if (ret) { | |
948 | dev_err(&pdev->dev, "IRQ request returned %d\n", ret); | |
949 | return ret; | |
950 | } | |
951 | ||
635eac1e | 952 | rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); |
03e4d5d5 | 953 | if (!IS_ERR(rst)) { |
954 | reset_control_assert(rst); | |
955 | udelay(2); | |
956 | reset_control_deassert(rst); | |
957 | } | |
958 | ||
959 | ret = devm_snd_soc_register_component(&pdev->dev, | |
960 | &stm32_spdifrx_component, | |
961 | stm32_spdifrx_dai, | |
962 | ARRAY_SIZE(stm32_spdifrx_dai)); | |
963 | if (ret) | |
964 | return ret; | |
965 | ||
966 | ret = stm32_spdifrx_dma_ctrl_register(&pdev->dev, spdifrx); | |
967 | if (ret) | |
968 | goto error; | |
969 | ||
970 | pcm_config = &stm32_spdifrx_pcm_config; | |
971 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); | |
972 | if (ret) { | |
973 | dev_err(&pdev->dev, "PCM DMA register returned %d\n", ret); | |
974 | goto error; | |
975 | } | |
976 | ||
977 | return 0; | |
978 | ||
979 | error: | |
98c8dc2f | 980 | if (!IS_ERR(spdifrx->ctrl_chan)) |
03e4d5d5 | 981 | dma_release_channel(spdifrx->ctrl_chan); |
982 | if (spdifrx->dmab) | |
983 | snd_dma_free_pages(spdifrx->dmab); | |
984 | ||
985 | return ret; | |
986 | } | |
987 | ||
988 | static int stm32_spdifrx_remove(struct platform_device *pdev) | |
989 | { | |
990 | struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); | |
991 | ||
992 | if (spdifrx->ctrl_chan) | |
993 | dma_release_channel(spdifrx->ctrl_chan); | |
994 | ||
995 | if (spdifrx->dmab) | |
996 | snd_dma_free_pages(spdifrx->dmab); | |
997 | ||
998 | return 0; | |
999 | } | |
1000 | ||
1001 | MODULE_DEVICE_TABLE(of, stm32_spdifrx_ids); | |
1002 | ||
1003 | static struct platform_driver stm32_spdifrx_driver = { | |
1004 | .driver = { | |
1005 | .name = "st,stm32-spdifrx", | |
1006 | .of_match_table = stm32_spdifrx_ids, | |
1007 | }, | |
1008 | .probe = stm32_spdifrx_probe, | |
1009 | .remove = stm32_spdifrx_remove, | |
1010 | }; | |
1011 | ||
1012 | module_platform_driver(stm32_spdifrx_driver); | |
1013 | ||
1014 | MODULE_DESCRIPTION("STM32 Soc spdifrx Interface"); | |
1015 | MODULE_AUTHOR("Olivier Moysan, <olivier.moysan@st.com>"); | |
1016 | MODULE_ALIAS("platform:stm32-spdifrx"); | |
1017 | MODULE_LICENSE("GPL v2"); |