]>
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 | |
216 | * @cs: channel status buffer | |
217 | * @ub: user data buffer | |
218 | * @irq: SPDIFRX interrupt line | |
219 | * @refcount: keep count of opened DMA channels | |
220 | */ | |
221 | struct stm32_spdifrx_data { | |
222 | struct platform_device *pdev; | |
223 | void __iomem *base; | |
224 | struct regmap *regmap; | |
225 | const struct regmap_config *regmap_conf; | |
226 | struct completion cs_completion; | |
227 | struct clk *kclk; | |
228 | struct snd_dmaengine_dai_dma_data dma_params; | |
229 | struct snd_pcm_substream *substream; | |
230 | struct snd_dma_buffer *dmab; | |
231 | struct dma_chan *ctrl_chan; | |
232 | struct dma_async_tx_descriptor *desc; | |
233 | struct dma_slave_config slave_config; | |
234 | dma_addr_t phys_addr; | |
235 | spinlock_t lock; /* Sync enabling lock */ | |
236 | unsigned char cs[SPDIFRX_CS_BYTES_NB]; | |
237 | unsigned char ub[SPDIFRX_UB_BYTES_NB]; | |
238 | int irq; | |
239 | int refcount; | |
240 | }; | |
241 | ||
242 | static void stm32_spdifrx_dma_complete(void *data) | |
243 | { | |
244 | struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)data; | |
245 | struct platform_device *pdev = spdifrx->pdev; | |
246 | u32 *p_start = (u32 *)spdifrx->dmab->area; | |
247 | u32 *p_end = p_start + (2 * SPDIFRX_CS_BYTES_NB) - 1; | |
248 | u32 *ptr = p_start; | |
249 | u16 *ub_ptr = (short *)spdifrx->ub; | |
250 | int i = 0; | |
251 | ||
252 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
253 | SPDIFRX_CR_CBDMAEN, | |
254 | (unsigned int)~SPDIFRX_CR_CBDMAEN); | |
255 | ||
256 | if (!spdifrx->dmab->area) | |
257 | return; | |
258 | ||
259 | while (ptr <= p_end) { | |
260 | if (*ptr & SPDIFRX_CSR_SOB) | |
261 | break; | |
262 | ptr++; | |
263 | } | |
264 | ||
265 | if (ptr > p_end) { | |
266 | dev_err(&pdev->dev, "Start of S/PDIF block not found\n"); | |
267 | return; | |
268 | } | |
269 | ||
270 | while (i < SPDIFRX_CS_BYTES_NB) { | |
271 | spdifrx->cs[i] = (unsigned char)SPDIFRX_CSR_CSGET(*ptr); | |
272 | *ub_ptr++ = SPDIFRX_CSR_USRGET(*ptr++); | |
273 | if (ptr > p_end) { | |
274 | dev_err(&pdev->dev, "Failed to get channel status\n"); | |
275 | return; | |
276 | } | |
277 | i++; | |
278 | } | |
279 | ||
280 | complete(&spdifrx->cs_completion); | |
281 | } | |
282 | ||
283 | static int stm32_spdifrx_dma_ctrl_start(struct stm32_spdifrx_data *spdifrx) | |
284 | { | |
285 | dma_cookie_t cookie; | |
286 | int err; | |
287 | ||
288 | spdifrx->desc = dmaengine_prep_slave_single(spdifrx->ctrl_chan, | |
289 | spdifrx->dmab->addr, | |
290 | SPDIFRX_CSR_BUF_LENGTH, | |
291 | DMA_DEV_TO_MEM, | |
292 | DMA_CTRL_ACK); | |
293 | if (!spdifrx->desc) | |
294 | return -EINVAL; | |
295 | ||
296 | spdifrx->desc->callback = stm32_spdifrx_dma_complete; | |
297 | spdifrx->desc->callback_param = spdifrx; | |
298 | cookie = dmaengine_submit(spdifrx->desc); | |
299 | err = dma_submit_error(cookie); | |
300 | if (err) | |
301 | return -EINVAL; | |
302 | ||
303 | dma_async_issue_pending(spdifrx->ctrl_chan); | |
304 | ||
305 | return 0; | |
306 | } | |
307 | ||
308 | static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx) | |
309 | { | |
310 | dmaengine_terminate_async(spdifrx->ctrl_chan); | |
311 | } | |
312 | ||
313 | static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) | |
314 | { | |
315 | int cr, cr_mask, imr, ret; | |
6b6f099c | 316 | unsigned long flags; |
03e4d5d5 | 317 | |
318 | /* Enable IRQs */ | |
319 | imr = SPDIFRX_IMR_IFEIE | SPDIFRX_IMR_SYNCDIE | SPDIFRX_IMR_PERRIE; | |
320 | ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, imr, imr); | |
321 | if (ret) | |
322 | return ret; | |
323 | ||
6b6f099c | 324 | spin_lock_irqsave(&spdifrx->lock, flags); |
03e4d5d5 | 325 | |
326 | spdifrx->refcount++; | |
327 | ||
328 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_CR, &cr); | |
329 | ||
330 | if (!(cr & SPDIFRX_CR_SPDIFEN_MASK)) { | |
331 | /* | |
332 | * Start sync if SPDIFRX is still in idle state. | |
333 | * SPDIFRX reception enabled when sync done | |
334 | */ | |
335 | dev_dbg(&spdifrx->pdev->dev, "start synchronization\n"); | |
336 | ||
337 | /* | |
338 | * SPDIFRX configuration: | |
339 | * Wait for activity before starting sync process. This avoid | |
340 | * to issue sync errors when spdif signal is missing on input. | |
341 | * Preamble, CS, user, validity and parity error bits not copied | |
342 | * to DR register. | |
343 | */ | |
344 | cr = SPDIFRX_CR_WFA | SPDIFRX_CR_PMSK | SPDIFRX_CR_VMSK | | |
345 | SPDIFRX_CR_CUMSK | SPDIFRX_CR_PTMSK | SPDIFRX_CR_RXSTEO; | |
346 | cr_mask = cr; | |
347 | ||
348 | cr |= SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_SYNC); | |
349 | cr_mask |= SPDIFRX_CR_SPDIFEN_MASK; | |
350 | ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
351 | cr_mask, cr); | |
352 | if (ret < 0) | |
353 | dev_err(&spdifrx->pdev->dev, | |
354 | "Failed to start synchronization\n"); | |
355 | } | |
356 | ||
6b6f099c | 357 | spin_unlock_irqrestore(&spdifrx->lock, flags); |
03e4d5d5 | 358 | |
359 | return ret; | |
360 | } | |
361 | ||
362 | static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx) | |
363 | { | |
364 | int cr, cr_mask, reg; | |
6b6f099c | 365 | unsigned long flags; |
03e4d5d5 | 366 | |
6b6f099c | 367 | spin_lock_irqsave(&spdifrx->lock, flags); |
03e4d5d5 | 368 | |
369 | if (--spdifrx->refcount) { | |
6b6f099c | 370 | spin_unlock_irqrestore(&spdifrx->lock, flags); |
03e4d5d5 | 371 | return; |
372 | } | |
373 | ||
374 | cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE); | |
375 | cr_mask = SPDIFRX_CR_SPDIFEN_MASK | SPDIFRX_CR_RXDMAEN; | |
376 | ||
377 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, cr_mask, cr); | |
378 | ||
379 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, | |
380 | SPDIFRX_XIMR_MASK, 0); | |
381 | ||
382 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IFCR, | |
383 | SPDIFRX_XIFCR_MASK, SPDIFRX_XIFCR_MASK); | |
384 | ||
385 | /* dummy read to clear CSRNE and RXNE in status register */ | |
386 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_DR, ®); | |
387 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_CSR, ®); | |
388 | ||
6b6f099c | 389 | spin_unlock_irqrestore(&spdifrx->lock, flags); |
03e4d5d5 | 390 | } |
391 | ||
392 | static int stm32_spdifrx_dma_ctrl_register(struct device *dev, | |
393 | struct stm32_spdifrx_data *spdifrx) | |
394 | { | |
395 | int ret; | |
396 | ||
98c8dc2f | 397 | spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl"); |
398 | if (IS_ERR(spdifrx->ctrl_chan)) { | |
399 | dev_err(dev, "dma_request_slave_channel failed\n"); | |
400 | return PTR_ERR(spdifrx->ctrl_chan); | |
401 | } | |
402 | ||
03e4d5d5 | 403 | spdifrx->dmab = devm_kzalloc(dev, sizeof(struct snd_dma_buffer), |
404 | GFP_KERNEL); | |
405 | if (!spdifrx->dmab) | |
406 | return -ENOMEM; | |
407 | ||
408 | spdifrx->dmab->dev.type = SNDRV_DMA_TYPE_DEV_IRAM; | |
409 | spdifrx->dmab->dev.dev = dev; | |
410 | ret = snd_dma_alloc_pages(spdifrx->dmab->dev.type, dev, | |
411 | SPDIFRX_CSR_BUF_LENGTH, spdifrx->dmab); | |
412 | if (ret < 0) { | |
413 | dev_err(dev, "snd_dma_alloc_pages returned error %d\n", ret); | |
414 | return ret; | |
415 | } | |
416 | ||
03e4d5d5 | 417 | spdifrx->slave_config.direction = DMA_DEV_TO_MEM; |
418 | spdifrx->slave_config.src_addr = (dma_addr_t)(spdifrx->phys_addr + | |
419 | STM32_SPDIFRX_CSR); | |
420 | spdifrx->slave_config.dst_addr = spdifrx->dmab->addr; | |
421 | spdifrx->slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | |
422 | spdifrx->slave_config.src_maxburst = 1; | |
423 | ||
424 | ret = dmaengine_slave_config(spdifrx->ctrl_chan, | |
425 | &spdifrx->slave_config); | |
426 | if (ret < 0) { | |
427 | dev_err(dev, "dmaengine_slave_config returned error %d\n", ret); | |
03e4d5d5 | 428 | spdifrx->ctrl_chan = NULL; |
429 | } | |
430 | ||
431 | return ret; | |
432 | }; | |
433 | ||
434 | static const char * const spdifrx_enum_input[] = { | |
435 | "in0", "in1", "in2", "in3" | |
436 | }; | |
437 | ||
438 | /* By default CS bits are retrieved from channel A */ | |
439 | static const char * const spdifrx_enum_cs_channel[] = { | |
440 | "A", "B" | |
441 | }; | |
442 | ||
443 | static SOC_ENUM_SINGLE_DECL(ctrl_enum_input, | |
444 | STM32_SPDIFRX_CR, SPDIFRX_CR_INSEL_SHIFT, | |
445 | spdifrx_enum_input); | |
446 | ||
447 | static SOC_ENUM_SINGLE_DECL(ctrl_enum_cs_channel, | |
448 | STM32_SPDIFRX_CR, SPDIFRX_CR_CHSEL_SHIFT, | |
449 | spdifrx_enum_cs_channel); | |
450 | ||
451 | static int stm32_spdifrx_info(struct snd_kcontrol *kcontrol, | |
452 | struct snd_ctl_elem_info *uinfo) | |
453 | { | |
454 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | |
455 | uinfo->count = 1; | |
456 | ||
457 | return 0; | |
458 | } | |
459 | ||
460 | static int stm32_spdifrx_ub_info(struct snd_kcontrol *kcontrol, | |
461 | struct snd_ctl_elem_info *uinfo) | |
462 | { | |
463 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | |
464 | uinfo->count = 1; | |
465 | ||
466 | return 0; | |
467 | } | |
468 | ||
469 | static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx) | |
470 | { | |
471 | int ret = 0; | |
472 | ||
473 | memset(spdifrx->cs, 0, SPDIFRX_CS_BYTES_NB); | |
474 | memset(spdifrx->ub, 0, SPDIFRX_UB_BYTES_NB); | |
475 | ||
476 | ret = stm32_spdifrx_dma_ctrl_start(spdifrx); | |
477 | if (ret < 0) | |
478 | return ret; | |
479 | ||
480 | ret = clk_prepare_enable(spdifrx->kclk); | |
481 | if (ret) { | |
482 | dev_err(&spdifrx->pdev->dev, "Enable kclk failed: %d\n", ret); | |
483 | return ret; | |
484 | } | |
485 | ||
486 | ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
487 | SPDIFRX_CR_CBDMAEN, SPDIFRX_CR_CBDMAEN); | |
488 | if (ret < 0) | |
489 | goto end; | |
490 | ||
491 | ret = stm32_spdifrx_start_sync(spdifrx); | |
492 | if (ret < 0) | |
493 | goto end; | |
494 | ||
495 | if (wait_for_completion_interruptible_timeout(&spdifrx->cs_completion, | |
496 | msecs_to_jiffies(100)) | |
497 | <= 0) { | |
498 | dev_err(&spdifrx->pdev->dev, "Failed to get control data\n"); | |
499 | ret = -EAGAIN; | |
500 | } | |
501 | ||
502 | stm32_spdifrx_stop(spdifrx); | |
503 | stm32_spdifrx_dma_ctrl_stop(spdifrx); | |
504 | ||
505 | end: | |
506 | clk_disable_unprepare(spdifrx->kclk); | |
507 | ||
508 | return ret; | |
509 | } | |
510 | ||
511 | static int stm32_spdifrx_capture_get(struct snd_kcontrol *kcontrol, | |
512 | struct snd_ctl_elem_value *ucontrol) | |
513 | { | |
514 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
515 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
516 | ||
517 | stm32_spdifrx_get_ctrl_data(spdifrx); | |
518 | ||
519 | ucontrol->value.iec958.status[0] = spdifrx->cs[0]; | |
520 | ucontrol->value.iec958.status[1] = spdifrx->cs[1]; | |
521 | ucontrol->value.iec958.status[2] = spdifrx->cs[2]; | |
522 | ucontrol->value.iec958.status[3] = spdifrx->cs[3]; | |
523 | ucontrol->value.iec958.status[4] = spdifrx->cs[4]; | |
524 | ||
525 | return 0; | |
526 | } | |
527 | ||
528 | static int stm32_spdif_user_bits_get(struct snd_kcontrol *kcontrol, | |
529 | struct snd_ctl_elem_value *ucontrol) | |
530 | { | |
531 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
532 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
533 | ||
534 | stm32_spdifrx_get_ctrl_data(spdifrx); | |
535 | ||
536 | ucontrol->value.iec958.status[0] = spdifrx->ub[0]; | |
537 | ucontrol->value.iec958.status[1] = spdifrx->ub[1]; | |
538 | ucontrol->value.iec958.status[2] = spdifrx->ub[2]; | |
539 | ucontrol->value.iec958.status[3] = spdifrx->ub[3]; | |
540 | ucontrol->value.iec958.status[4] = spdifrx->ub[4]; | |
541 | ||
542 | return 0; | |
543 | } | |
544 | ||
545 | static struct snd_kcontrol_new stm32_spdifrx_iec_ctrls[] = { | |
546 | /* Channel status control */ | |
547 | { | |
548 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
549 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), | |
550 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
551 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
552 | .info = stm32_spdifrx_info, | |
553 | .get = stm32_spdifrx_capture_get, | |
554 | }, | |
555 | /* User bits control */ | |
556 | { | |
557 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
558 | .name = "IEC958 User Bit Capture Default", | |
559 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
560 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
561 | .info = stm32_spdifrx_ub_info, | |
562 | .get = stm32_spdif_user_bits_get, | |
563 | }, | |
564 | }; | |
565 | ||
566 | static struct snd_kcontrol_new stm32_spdifrx_ctrls[] = { | |
567 | SOC_ENUM("SPDIFRX input", ctrl_enum_input), | |
568 | SOC_ENUM("SPDIFRX CS channel", ctrl_enum_cs_channel), | |
569 | }; | |
570 | ||
571 | static int stm32_spdifrx_dai_register_ctrls(struct snd_soc_dai *cpu_dai) | |
572 | { | |
573 | int ret; | |
574 | ||
575 | ret = snd_soc_add_dai_controls(cpu_dai, stm32_spdifrx_iec_ctrls, | |
576 | ARRAY_SIZE(stm32_spdifrx_iec_ctrls)); | |
577 | if (ret < 0) | |
578 | return ret; | |
579 | ||
580 | return snd_soc_add_component_controls(cpu_dai->component, | |
581 | stm32_spdifrx_ctrls, | |
582 | ARRAY_SIZE(stm32_spdifrx_ctrls)); | |
583 | } | |
584 | ||
585 | static int stm32_spdifrx_dai_probe(struct snd_soc_dai *cpu_dai) | |
586 | { | |
587 | struct stm32_spdifrx_data *spdifrx = dev_get_drvdata(cpu_dai->dev); | |
588 | ||
589 | spdifrx->dma_params.addr = (dma_addr_t)(spdifrx->phys_addr + | |
590 | STM32_SPDIFRX_DR); | |
591 | spdifrx->dma_params.maxburst = 1; | |
592 | ||
593 | snd_soc_dai_init_dma_data(cpu_dai, NULL, &spdifrx->dma_params); | |
594 | ||
595 | return stm32_spdifrx_dai_register_ctrls(cpu_dai); | |
596 | } | |
597 | ||
598 | static bool stm32_spdifrx_readable_reg(struct device *dev, unsigned int reg) | |
599 | { | |
600 | switch (reg) { | |
601 | case STM32_SPDIFRX_CR: | |
602 | case STM32_SPDIFRX_IMR: | |
603 | case STM32_SPDIFRX_SR: | |
604 | case STM32_SPDIFRX_IFCR: | |
605 | case STM32_SPDIFRX_DR: | |
606 | case STM32_SPDIFRX_CSR: | |
607 | case STM32_SPDIFRX_DIR: | |
608 | return true; | |
609 | default: | |
610 | return false; | |
611 | } | |
612 | } | |
613 | ||
614 | static bool stm32_spdifrx_volatile_reg(struct device *dev, unsigned int reg) | |
615 | { | |
616 | if (reg == STM32_SPDIFRX_DR) | |
617 | return true; | |
618 | ||
619 | return false; | |
620 | } | |
621 | ||
622 | static bool stm32_spdifrx_writeable_reg(struct device *dev, unsigned int reg) | |
623 | { | |
624 | switch (reg) { | |
625 | case STM32_SPDIFRX_CR: | |
626 | case STM32_SPDIFRX_IMR: | |
627 | case STM32_SPDIFRX_IFCR: | |
628 | return true; | |
629 | default: | |
630 | return false; | |
631 | } | |
632 | } | |
633 | ||
634 | static const struct regmap_config stm32_h7_spdifrx_regmap_conf = { | |
635 | .reg_bits = 32, | |
636 | .reg_stride = 4, | |
637 | .val_bits = 32, | |
638 | .max_register = STM32_SPDIFRX_DIR, | |
639 | .readable_reg = stm32_spdifrx_readable_reg, | |
640 | .volatile_reg = stm32_spdifrx_volatile_reg, | |
641 | .writeable_reg = stm32_spdifrx_writeable_reg, | |
642 | .fast_io = true, | |
643 | }; | |
644 | ||
645 | static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) | |
646 | { | |
647 | struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid; | |
648 | struct snd_pcm_substream *substream = spdifrx->substream; | |
649 | struct platform_device *pdev = spdifrx->pdev; | |
650 | unsigned int cr, mask, sr, imr; | |
651 | unsigned int flags; | |
652 | int err = 0, err_xrun = 0; | |
653 | ||
654 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_SR, &sr); | |
655 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_IMR, &imr); | |
656 | ||
657 | mask = imr & SPDIFRX_XIMR_MASK; | |
658 | /* SERR, TERR, FERR IRQs are generated if IFEIE is set */ | |
659 | if (mask & SPDIFRX_IMR_IFEIE) | |
660 | mask |= (SPDIFRX_IMR_IFEIE << 1) | (SPDIFRX_IMR_IFEIE << 2); | |
661 | ||
662 | flags = sr & mask; | |
663 | if (!flags) { | |
664 | dev_err(&pdev->dev, "Unexpected IRQ. rflags=%#x, imr=%#x\n", | |
665 | sr, imr); | |
666 | return IRQ_NONE; | |
667 | } | |
668 | ||
669 | /* Clear IRQs */ | |
670 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IFCR, | |
671 | SPDIFRX_XIFCR_MASK, flags); | |
672 | ||
673 | if (flags & SPDIFRX_SR_PERR) { | |
674 | dev_dbg(&pdev->dev, "Parity error\n"); | |
675 | err_xrun = 1; | |
676 | } | |
677 | ||
678 | if (flags & SPDIFRX_SR_OVR) { | |
679 | dev_dbg(&pdev->dev, "Overrun error\n"); | |
680 | err_xrun = 1; | |
681 | } | |
682 | ||
683 | if (flags & SPDIFRX_SR_SBD) | |
684 | dev_dbg(&pdev->dev, "Synchronization block detected\n"); | |
685 | ||
686 | if (flags & SPDIFRX_SR_SYNCD) { | |
687 | dev_dbg(&pdev->dev, "Synchronization done\n"); | |
688 | ||
689 | /* Enable spdifrx */ | |
690 | cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_ENABLE); | |
691 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
692 | SPDIFRX_CR_SPDIFEN_MASK, cr); | |
693 | } | |
694 | ||
695 | if (flags & SPDIFRX_SR_FERR) { | |
696 | dev_dbg(&pdev->dev, "Frame error\n"); | |
697 | err = 1; | |
698 | } | |
699 | ||
700 | if (flags & SPDIFRX_SR_SERR) { | |
701 | dev_dbg(&pdev->dev, "Synchronization error\n"); | |
702 | err = 1; | |
703 | } | |
704 | ||
705 | if (flags & SPDIFRX_SR_TERR) { | |
706 | dev_dbg(&pdev->dev, "Timeout error\n"); | |
707 | err = 1; | |
708 | } | |
709 | ||
710 | if (err) { | |
711 | /* SPDIFRX in STATE_STOP. Disable SPDIFRX to clear errors */ | |
712 | cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE); | |
713 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
714 | SPDIFRX_CR_SPDIFEN_MASK, cr); | |
715 | ||
716 | if (substream) | |
717 | snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); | |
718 | ||
719 | return IRQ_HANDLED; | |
720 | } | |
721 | ||
722 | if (err_xrun && substream) | |
723 | snd_pcm_stop_xrun(substream); | |
724 | ||
725 | return IRQ_HANDLED; | |
726 | } | |
727 | ||
728 | static int stm32_spdifrx_startup(struct snd_pcm_substream *substream, | |
729 | struct snd_soc_dai *cpu_dai) | |
730 | { | |
731 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
732 | int ret; | |
733 | ||
734 | spdifrx->substream = substream; | |
735 | ||
736 | ret = clk_prepare_enable(spdifrx->kclk); | |
737 | if (ret) | |
738 | dev_err(&spdifrx->pdev->dev, "Enable kclk failed: %d\n", ret); | |
739 | ||
740 | return ret; | |
741 | } | |
742 | ||
743 | static int stm32_spdifrx_hw_params(struct snd_pcm_substream *substream, | |
744 | struct snd_pcm_hw_params *params, | |
745 | struct snd_soc_dai *cpu_dai) | |
746 | { | |
747 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
748 | int data_size = params_width(params); | |
749 | int fmt; | |
750 | ||
751 | switch (data_size) { | |
752 | case 16: | |
753 | fmt = SPDIFRX_DRFMT_PACKED; | |
03e4d5d5 | 754 | break; |
755 | case 32: | |
756 | fmt = SPDIFRX_DRFMT_LEFT; | |
03e4d5d5 | 757 | break; |
758 | default: | |
759 | dev_err(&spdifrx->pdev->dev, "Unexpected data format\n"); | |
760 | return -EINVAL; | |
761 | } | |
762 | ||
9036e4ac | 763 | /* |
764 | * Set buswidth to 4 bytes for all data formats. | |
765 | * Packed format: transfer 2 x 2 bytes samples | |
766 | * Left format: transfer 1 x 3 bytes samples + 1 dummy byte | |
767 | */ | |
768 | spdifrx->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | |
03e4d5d5 | 769 | snd_soc_dai_init_dma_data(cpu_dai, NULL, &spdifrx->dma_params); |
770 | ||
771 | return regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
772 | SPDIFRX_CR_DRFMT_MASK, | |
773 | SPDIFRX_CR_DRFMTSET(fmt)); | |
774 | } | |
775 | ||
776 | static int stm32_spdifrx_trigger(struct snd_pcm_substream *substream, int cmd, | |
777 | struct snd_soc_dai *cpu_dai) | |
778 | { | |
779 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
780 | int ret = 0; | |
781 | ||
782 | switch (cmd) { | |
783 | case SNDRV_PCM_TRIGGER_START: | |
784 | case SNDRV_PCM_TRIGGER_RESUME: | |
785 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | |
786 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, | |
787 | SPDIFRX_IMR_OVRIE, SPDIFRX_IMR_OVRIE); | |
788 | ||
789 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | |
790 | SPDIFRX_CR_RXDMAEN, SPDIFRX_CR_RXDMAEN); | |
791 | ||
792 | ret = stm32_spdifrx_start_sync(spdifrx); | |
793 | break; | |
794 | case SNDRV_PCM_TRIGGER_SUSPEND: | |
795 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | |
796 | case SNDRV_PCM_TRIGGER_STOP: | |
797 | stm32_spdifrx_stop(spdifrx); | |
798 | break; | |
799 | default: | |
800 | return -EINVAL; | |
801 | } | |
802 | ||
803 | return ret; | |
804 | } | |
805 | ||
806 | static void stm32_spdifrx_shutdown(struct snd_pcm_substream *substream, | |
807 | struct snd_soc_dai *cpu_dai) | |
808 | { | |
809 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | |
810 | ||
811 | spdifrx->substream = NULL; | |
812 | clk_disable_unprepare(spdifrx->kclk); | |
813 | } | |
814 | ||
815 | static const struct snd_soc_dai_ops stm32_spdifrx_pcm_dai_ops = { | |
816 | .startup = stm32_spdifrx_startup, | |
817 | .hw_params = stm32_spdifrx_hw_params, | |
818 | .trigger = stm32_spdifrx_trigger, | |
819 | .shutdown = stm32_spdifrx_shutdown, | |
820 | }; | |
821 | ||
822 | static struct snd_soc_dai_driver stm32_spdifrx_dai[] = { | |
823 | { | |
824 | .name = "spdifrx-capture-cpu-dai", | |
825 | .probe = stm32_spdifrx_dai_probe, | |
826 | .capture = { | |
827 | .stream_name = "CPU-Capture", | |
828 | .channels_min = 1, | |
829 | .channels_max = 2, | |
830 | .rates = SNDRV_PCM_RATE_8000_192000, | |
831 | .formats = SNDRV_PCM_FMTBIT_S32_LE | | |
832 | SNDRV_PCM_FMTBIT_S16_LE, | |
833 | }, | |
834 | .ops = &stm32_spdifrx_pcm_dai_ops, | |
835 | } | |
836 | }; | |
837 | ||
838 | static const struct snd_pcm_hardware stm32_spdifrx_pcm_hw = { | |
839 | .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP, | |
840 | .buffer_bytes_max = 8 * PAGE_SIZE, | |
841 | .period_bytes_max = 2048, /* MDMA constraint */ | |
842 | .periods_min = 2, | |
843 | .periods_max = 8, | |
844 | }; | |
845 | ||
846 | static const struct snd_soc_component_driver stm32_spdifrx_component = { | |
847 | .name = "stm32-spdifrx", | |
848 | }; | |
849 | ||
850 | static const struct snd_dmaengine_pcm_config stm32_spdifrx_pcm_config = { | |
851 | .pcm_hardware = &stm32_spdifrx_pcm_hw, | |
852 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, | |
853 | }; | |
854 | ||
855 | static const struct of_device_id stm32_spdifrx_ids[] = { | |
856 | { | |
857 | .compatible = "st,stm32h7-spdifrx", | |
858 | .data = &stm32_h7_spdifrx_regmap_conf | |
859 | }, | |
860 | {} | |
861 | }; | |
862 | ||
863 | static int stm_spdifrx_parse_of(struct platform_device *pdev, | |
864 | struct stm32_spdifrx_data *spdifrx) | |
865 | { | |
866 | struct device_node *np = pdev->dev.of_node; | |
867 | const struct of_device_id *of_id; | |
868 | struct resource *res; | |
869 | ||
870 | if (!np) | |
871 | return -ENODEV; | |
872 | ||
873 | of_id = of_match_device(stm32_spdifrx_ids, &pdev->dev); | |
874 | if (of_id) | |
875 | spdifrx->regmap_conf = | |
876 | (const struct regmap_config *)of_id->data; | |
877 | else | |
878 | return -EINVAL; | |
879 | ||
880 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
881 | spdifrx->base = devm_ioremap_resource(&pdev->dev, res); | |
882 | if (IS_ERR(spdifrx->base)) | |
883 | return PTR_ERR(spdifrx->base); | |
884 | ||
885 | spdifrx->phys_addr = res->start; | |
886 | ||
887 | spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk"); | |
888 | if (IS_ERR(spdifrx->kclk)) { | |
889 | dev_err(&pdev->dev, "Could not get kclk\n"); | |
890 | return PTR_ERR(spdifrx->kclk); | |
891 | } | |
892 | ||
893 | spdifrx->irq = platform_get_irq(pdev, 0); | |
894 | if (spdifrx->irq < 0) { | |
895 | dev_err(&pdev->dev, "No irq for node %s\n", pdev->name); | |
896 | return spdifrx->irq; | |
897 | } | |
898 | ||
899 | return 0; | |
900 | } | |
901 | ||
902 | static int stm32_spdifrx_probe(struct platform_device *pdev) | |
903 | { | |
904 | struct stm32_spdifrx_data *spdifrx; | |
905 | struct reset_control *rst; | |
906 | const struct snd_dmaengine_pcm_config *pcm_config = NULL; | |
907 | int ret; | |
908 | ||
909 | spdifrx = devm_kzalloc(&pdev->dev, sizeof(*spdifrx), GFP_KERNEL); | |
910 | if (!spdifrx) | |
911 | return -ENOMEM; | |
912 | ||
913 | spdifrx->pdev = pdev; | |
914 | init_completion(&spdifrx->cs_completion); | |
915 | spin_lock_init(&spdifrx->lock); | |
916 | ||
917 | platform_set_drvdata(pdev, spdifrx); | |
918 | ||
919 | ret = stm_spdifrx_parse_of(pdev, spdifrx); | |
920 | if (ret) | |
921 | return ret; | |
922 | ||
923 | spdifrx->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "kclk", | |
924 | spdifrx->base, | |
925 | spdifrx->regmap_conf); | |
926 | if (IS_ERR(spdifrx->regmap)) { | |
927 | dev_err(&pdev->dev, "Regmap init failed\n"); | |
928 | return PTR_ERR(spdifrx->regmap); | |
929 | } | |
930 | ||
931 | ret = devm_request_irq(&pdev->dev, spdifrx->irq, stm32_spdifrx_isr, 0, | |
932 | dev_name(&pdev->dev), spdifrx); | |
933 | if (ret) { | |
934 | dev_err(&pdev->dev, "IRQ request returned %d\n", ret); | |
935 | return ret; | |
936 | } | |
937 | ||
635eac1e | 938 | rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); |
03e4d5d5 | 939 | if (!IS_ERR(rst)) { |
940 | reset_control_assert(rst); | |
941 | udelay(2); | |
942 | reset_control_deassert(rst); | |
943 | } | |
944 | ||
945 | ret = devm_snd_soc_register_component(&pdev->dev, | |
946 | &stm32_spdifrx_component, | |
947 | stm32_spdifrx_dai, | |
948 | ARRAY_SIZE(stm32_spdifrx_dai)); | |
949 | if (ret) | |
950 | return ret; | |
951 | ||
952 | ret = stm32_spdifrx_dma_ctrl_register(&pdev->dev, spdifrx); | |
953 | if (ret) | |
954 | goto error; | |
955 | ||
956 | pcm_config = &stm32_spdifrx_pcm_config; | |
957 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); | |
958 | if (ret) { | |
959 | dev_err(&pdev->dev, "PCM DMA register returned %d\n", ret); | |
960 | goto error; | |
961 | } | |
962 | ||
963 | return 0; | |
964 | ||
965 | error: | |
98c8dc2f | 966 | if (!IS_ERR(spdifrx->ctrl_chan)) |
03e4d5d5 | 967 | dma_release_channel(spdifrx->ctrl_chan); |
968 | if (spdifrx->dmab) | |
969 | snd_dma_free_pages(spdifrx->dmab); | |
970 | ||
971 | return ret; | |
972 | } | |
973 | ||
974 | static int stm32_spdifrx_remove(struct platform_device *pdev) | |
975 | { | |
976 | struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); | |
977 | ||
978 | if (spdifrx->ctrl_chan) | |
979 | dma_release_channel(spdifrx->ctrl_chan); | |
980 | ||
981 | if (spdifrx->dmab) | |
982 | snd_dma_free_pages(spdifrx->dmab); | |
983 | ||
984 | return 0; | |
985 | } | |
986 | ||
987 | MODULE_DEVICE_TABLE(of, stm32_spdifrx_ids); | |
988 | ||
989 | static struct platform_driver stm32_spdifrx_driver = { | |
990 | .driver = { | |
991 | .name = "st,stm32-spdifrx", | |
992 | .of_match_table = stm32_spdifrx_ids, | |
993 | }, | |
994 | .probe = stm32_spdifrx_probe, | |
995 | .remove = stm32_spdifrx_remove, | |
996 | }; | |
997 | ||
998 | module_platform_driver(stm32_spdifrx_driver); | |
999 | ||
1000 | MODULE_DESCRIPTION("STM32 Soc spdifrx Interface"); | |
1001 | MODULE_AUTHOR("Olivier Moysan, <olivier.moysan@st.com>"); | |
1002 | MODULE_ALIAS("platform:stm32-spdifrx"); | |
1003 | MODULE_LICENSE("GPL v2"); |