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