Commit | Line | Data |
---|---|---|
a2388a49 NC |
1 | /* |
2 | * Freescale S/PDIF ALSA SoC Digital Audio Interface (DAI) driver | |
3 | * | |
4 | * Copyright (C) 2013 Freescale Semiconductor, Inc. | |
5 | * | |
6 | * Based on stmp3xxx_spdif_dai.c | |
7 | * Vladimir Barinov <vbarinov@embeddedalley.com> | |
8 | * Copyright 2008 SigmaTel, Inc | |
9 | * Copyright 2008 Embedded Alley Solutions, Inc | |
10 | * | |
11 | * This file is licensed under the terms of the GNU General Public License | |
12 | * version 2. This program is licensed "as is" without any warranty of any | |
13 | * kind, whether express or implied. | |
14 | */ | |
15 | ||
add180ed | 16 | #include <linux/bitrev.h> |
a2388a49 | 17 | #include <linux/clk.h> |
add180ed | 18 | #include <linux/module.h> |
a2388a49 NC |
19 | #include <linux/of_address.h> |
20 | #include <linux/of_device.h> | |
21 | #include <linux/of_irq.h> | |
add180ed | 22 | #include <linux/regmap.h> |
a2388a49 NC |
23 | |
24 | #include <sound/asoundef.h> | |
a2388a49 | 25 | #include <sound/dmaengine_pcm.h> |
add180ed | 26 | #include <sound/soc.h> |
a2388a49 NC |
27 | |
28 | #include "fsl_spdif.h" | |
29 | #include "imx-pcm.h" | |
30 | ||
31 | #define FSL_SPDIF_TXFIFO_WML 0x8 | |
32 | #define FSL_SPDIF_RXFIFO_WML 0x8 | |
33 | ||
f3a30baa NC |
34 | #define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC) |
35 | #define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL |\ | |
36 | INT_URX_OV | INT_QRX_FUL | INT_QRX_OV |\ | |
37 | INT_UQ_SYNC | INT_UQ_ERR | INT_RXFIFO_RESYNC |\ | |
38 | INT_LOSS_LOCK | INT_DPLL_LOCKED) | |
39 | ||
40 | #define SIE_INTR_FOR(tx) (tx ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE) | |
a2388a49 NC |
41 | |
42 | /* Index list for the values that has if (DPLL Locked) condition */ | |
43 | static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb }; | |
44 | #define SRPC_NODPLL_START1 0x5 | |
45 | #define SRPC_NODPLL_START2 0xc | |
46 | ||
47 | #define DEFAULT_RXCLK_SRC 1 | |
48 | ||
49 | /* | |
50 | * SPDIF control structure | |
51 | * Defines channel status, subcode and Q sub | |
52 | */ | |
53 | struct spdif_mixer_control { | |
54 | /* spinlock to access control data */ | |
55 | spinlock_t ctl_lock; | |
56 | ||
57 | /* IEC958 channel tx status bit */ | |
58 | unsigned char ch_status[4]; | |
59 | ||
60 | /* User bits */ | |
61 | unsigned char subcode[2 * SPDIF_UBITS_SIZE]; | |
62 | ||
63 | /* Q subcode part of user bits */ | |
64 | unsigned char qsub[2 * SPDIF_QSUB_SIZE]; | |
65 | ||
66 | /* Buffer offset for U/Q */ | |
67 | u32 upos; | |
68 | u32 qpos; | |
69 | ||
70 | /* Ready buffer index of the two buffers */ | |
71 | u32 ready_buf; | |
72 | }; | |
73 | ||
b8a832a0 NC |
74 | /** |
75 | * fsl_spdif_priv: Freescale SPDIF private data | |
76 | * | |
77 | * @fsl_spdif_control: SPDIF control data | |
78 | * @cpu_dai_drv: cpu dai driver | |
79 | * @pdev: platform device pointer | |
80 | * @regmap: regmap handler | |
81 | * @dpll_locked: dpll lock flag | |
82 | * @txrate: the best rates for playback | |
83 | * @txclk_df: STC_TXCLK_DF dividers value for playback | |
84 | * @sysclk_df: STC_SYSCLK_DF dividers value for playback | |
85 | * @txclk_src: STC_TXCLK_SRC values for playback | |
86 | * @rxclk_src: SRPC_CLKSRC_SEL values for capture | |
87 | * @txclk: tx clock sources for playback | |
88 | * @rxclk: rx clock sources for capture | |
89 | * @coreclk: core clock for register access via DMA | |
90 | * @sysclk: system clock for rx clock rate measurement | |
91 | * @dma_params_tx: DMA parameters for transmit channel | |
92 | * @dma_params_rx: DMA parameters for receive channel | |
b8a832a0 | 93 | */ |
a2388a49 NC |
94 | struct fsl_spdif_priv { |
95 | struct spdif_mixer_control fsl_spdif_control; | |
96 | struct snd_soc_dai_driver cpu_dai_drv; | |
97 | struct platform_device *pdev; | |
98 | struct regmap *regmap; | |
99 | bool dpll_locked; | |
c7dfeed1 | 100 | u32 txrate[SPDIF_TXRATE_MAX]; |
e41a4a79 | 101 | u8 txclk_df[SPDIF_TXRATE_MAX]; |
27c647bf | 102 | u8 sysclk_df[SPDIF_TXRATE_MAX]; |
a2388a49 NC |
103 | u8 txclk_src[SPDIF_TXRATE_MAX]; |
104 | u8 rxclk_src; | |
105 | struct clk *txclk[SPDIF_TXRATE_MAX]; | |
106 | struct clk *rxclk; | |
08f7336e | 107 | struct clk *coreclk; |
0b864390 | 108 | struct clk *sysclk; |
a2388a49 NC |
109 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
110 | struct snd_dmaengine_dai_dma_data dma_params_rx; | |
a2388a49 NC |
111 | }; |
112 | ||
a2388a49 NC |
113 | /* DPLL locked and lock loss interrupt handler */ |
114 | static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv) | |
115 | { | |
116 | struct regmap *regmap = spdif_priv->regmap; | |
117 | struct platform_device *pdev = spdif_priv->pdev; | |
118 | u32 locked; | |
119 | ||
120 | regmap_read(regmap, REG_SPDIF_SRPC, &locked); | |
121 | locked &= SRPC_DPLL_LOCKED; | |
122 | ||
123 | dev_dbg(&pdev->dev, "isr: Rx dpll %s \n", | |
124 | locked ? "locked" : "loss lock"); | |
125 | ||
126 | spdif_priv->dpll_locked = locked ? true : false; | |
127 | } | |
128 | ||
129 | /* Receiver found illegal symbol interrupt handler */ | |
130 | static void spdif_irq_sym_error(struct fsl_spdif_priv *spdif_priv) | |
131 | { | |
132 | struct regmap *regmap = spdif_priv->regmap; | |
133 | struct platform_device *pdev = spdif_priv->pdev; | |
134 | ||
135 | dev_dbg(&pdev->dev, "isr: receiver found illegal symbol\n"); | |
136 | ||
f3a30baa NC |
137 | /* Clear illegal symbol if DPLL unlocked since no audio stream */ |
138 | if (!spdif_priv->dpll_locked) | |
a2388a49 | 139 | regmap_update_bits(regmap, REG_SPDIF_SIE, INT_SYM_ERR, 0); |
a2388a49 NC |
140 | } |
141 | ||
142 | /* U/Q Channel receive register full */ | |
143 | static void spdif_irq_uqrx_full(struct fsl_spdif_priv *spdif_priv, char name) | |
144 | { | |
145 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | |
146 | struct regmap *regmap = spdif_priv->regmap; | |
147 | struct platform_device *pdev = spdif_priv->pdev; | |
148 | u32 *pos, size, val, reg; | |
149 | ||
150 | switch (name) { | |
151 | case 'U': | |
152 | pos = &ctrl->upos; | |
153 | size = SPDIF_UBITS_SIZE; | |
154 | reg = REG_SPDIF_SRU; | |
155 | break; | |
156 | case 'Q': | |
157 | pos = &ctrl->qpos; | |
158 | size = SPDIF_QSUB_SIZE; | |
159 | reg = REG_SPDIF_SRQ; | |
160 | break; | |
161 | default: | |
162 | dev_err(&pdev->dev, "unsupported channel name\n"); | |
163 | return; | |
164 | } | |
165 | ||
166 | dev_dbg(&pdev->dev, "isr: %c Channel receive register full\n", name); | |
167 | ||
168 | if (*pos >= size * 2) { | |
169 | *pos = 0; | |
170 | } else if (unlikely((*pos % size) + 3 > size)) { | |
171 | dev_err(&pdev->dev, "User bit receivce buffer overflow\n"); | |
172 | return; | |
173 | } | |
174 | ||
175 | regmap_read(regmap, reg, &val); | |
176 | ctrl->subcode[*pos++] = val >> 16; | |
177 | ctrl->subcode[*pos++] = val >> 8; | |
178 | ctrl->subcode[*pos++] = val; | |
179 | } | |
180 | ||
181 | /* U/Q Channel sync found */ | |
182 | static void spdif_irq_uq_sync(struct fsl_spdif_priv *spdif_priv) | |
183 | { | |
184 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | |
185 | struct platform_device *pdev = spdif_priv->pdev; | |
186 | ||
187 | dev_dbg(&pdev->dev, "isr: U/Q Channel sync found\n"); | |
188 | ||
189 | /* U/Q buffer reset */ | |
190 | if (ctrl->qpos == 0) | |
191 | return; | |
192 | ||
193 | /* Set ready to this buffer */ | |
194 | ctrl->ready_buf = (ctrl->qpos - 1) / SPDIF_QSUB_SIZE + 1; | |
195 | } | |
196 | ||
197 | /* U/Q Channel framing error */ | |
198 | static void spdif_irq_uq_err(struct fsl_spdif_priv *spdif_priv) | |
199 | { | |
200 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | |
201 | struct regmap *regmap = spdif_priv->regmap; | |
202 | struct platform_device *pdev = spdif_priv->pdev; | |
203 | u32 val; | |
204 | ||
205 | dev_dbg(&pdev->dev, "isr: U/Q Channel framing error\n"); | |
206 | ||
207 | /* Read U/Q data to clear the irq and do buffer reset */ | |
208 | regmap_read(regmap, REG_SPDIF_SRU, &val); | |
209 | regmap_read(regmap, REG_SPDIF_SRQ, &val); | |
210 | ||
211 | /* Drop this U/Q buffer */ | |
212 | ctrl->ready_buf = 0; | |
213 | ctrl->upos = 0; | |
214 | ctrl->qpos = 0; | |
215 | } | |
216 | ||
217 | /* Get spdif interrupt status and clear the interrupt */ | |
218 | static u32 spdif_intr_status_clear(struct fsl_spdif_priv *spdif_priv) | |
219 | { | |
220 | struct regmap *regmap = spdif_priv->regmap; | |
221 | u32 val, val2; | |
222 | ||
223 | regmap_read(regmap, REG_SPDIF_SIS, &val); | |
224 | regmap_read(regmap, REG_SPDIF_SIE, &val2); | |
225 | ||
226 | regmap_write(regmap, REG_SPDIF_SIC, val & val2); | |
227 | ||
228 | return val; | |
229 | } | |
230 | ||
231 | static irqreturn_t spdif_isr(int irq, void *devid) | |
232 | { | |
233 | struct fsl_spdif_priv *spdif_priv = (struct fsl_spdif_priv *)devid; | |
234 | struct platform_device *pdev = spdif_priv->pdev; | |
235 | u32 sis; | |
236 | ||
237 | sis = spdif_intr_status_clear(spdif_priv); | |
238 | ||
239 | if (sis & INT_DPLL_LOCKED) | |
240 | spdif_irq_dpll_lock(spdif_priv); | |
241 | ||
242 | if (sis & INT_TXFIFO_UNOV) | |
243 | dev_dbg(&pdev->dev, "isr: Tx FIFO under/overrun\n"); | |
244 | ||
245 | if (sis & INT_TXFIFO_RESYNC) | |
246 | dev_dbg(&pdev->dev, "isr: Tx FIFO resync\n"); | |
247 | ||
248 | if (sis & INT_CNEW) | |
249 | dev_dbg(&pdev->dev, "isr: cstatus new\n"); | |
250 | ||
251 | if (sis & INT_VAL_NOGOOD) | |
252 | dev_dbg(&pdev->dev, "isr: validity flag no good\n"); | |
253 | ||
254 | if (sis & INT_SYM_ERR) | |
255 | spdif_irq_sym_error(spdif_priv); | |
256 | ||
257 | if (sis & INT_BIT_ERR) | |
258 | dev_dbg(&pdev->dev, "isr: receiver found parity bit error\n"); | |
259 | ||
260 | if (sis & INT_URX_FUL) | |
261 | spdif_irq_uqrx_full(spdif_priv, 'U'); | |
262 | ||
263 | if (sis & INT_URX_OV) | |
264 | dev_dbg(&pdev->dev, "isr: U Channel receive register overrun\n"); | |
265 | ||
266 | if (sis & INT_QRX_FUL) | |
267 | spdif_irq_uqrx_full(spdif_priv, 'Q'); | |
268 | ||
269 | if (sis & INT_QRX_OV) | |
270 | dev_dbg(&pdev->dev, "isr: Q Channel receive register overrun\n"); | |
271 | ||
272 | if (sis & INT_UQ_SYNC) | |
273 | spdif_irq_uq_sync(spdif_priv); | |
274 | ||
275 | if (sis & INT_UQ_ERR) | |
276 | spdif_irq_uq_err(spdif_priv); | |
277 | ||
278 | if (sis & INT_RXFIFO_UNOV) | |
279 | dev_dbg(&pdev->dev, "isr: Rx FIFO under/overrun\n"); | |
280 | ||
281 | if (sis & INT_RXFIFO_RESYNC) | |
282 | dev_dbg(&pdev->dev, "isr: Rx FIFO resync\n"); | |
283 | ||
284 | if (sis & INT_LOSS_LOCK) | |
285 | spdif_irq_dpll_lock(spdif_priv); | |
286 | ||
287 | /* FIXME: Write Tx FIFO to clear TxEm */ | |
288 | if (sis & INT_TX_EM) | |
289 | dev_dbg(&pdev->dev, "isr: Tx FIFO empty\n"); | |
290 | ||
291 | /* FIXME: Read Rx FIFO to clear RxFIFOFul */ | |
292 | if (sis & INT_RXFIFO_FUL) | |
293 | dev_dbg(&pdev->dev, "isr: Rx FIFO full\n"); | |
294 | ||
295 | return IRQ_HANDLED; | |
296 | } | |
297 | ||
298 | static int spdif_softreset(struct fsl_spdif_priv *spdif_priv) | |
299 | { | |
300 | struct regmap *regmap = spdif_priv->regmap; | |
301 | u32 val, cycle = 1000; | |
302 | ||
303 | regmap_write(regmap, REG_SPDIF_SCR, SCR_SOFT_RESET); | |
304 | ||
305 | /* | |
306 | * RESET bit would be cleared after finishing its reset procedure, | |
307 | * which typically lasts 8 cycles. 1000 cycles will keep it safe. | |
308 | */ | |
309 | do { | |
310 | regmap_read(regmap, REG_SPDIF_SCR, &val); | |
311 | } while ((val & SCR_SOFT_RESET) && cycle--); | |
312 | ||
313 | if (cycle) | |
314 | return 0; | |
315 | else | |
316 | return -EBUSY; | |
317 | } | |
318 | ||
319 | static void spdif_set_cstatus(struct spdif_mixer_control *ctrl, | |
320 | u8 mask, u8 cstatus) | |
321 | { | |
322 | ctrl->ch_status[3] &= ~mask; | |
323 | ctrl->ch_status[3] |= cstatus & mask; | |
324 | } | |
325 | ||
326 | static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv) | |
327 | { | |
328 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | |
329 | struct regmap *regmap = spdif_priv->regmap; | |
330 | struct platform_device *pdev = spdif_priv->pdev; | |
331 | u32 ch_status; | |
332 | ||
333 | ch_status = (bitrev8(ctrl->ch_status[0]) << 16) | | |
f3a30baa NC |
334 | (bitrev8(ctrl->ch_status[1]) << 8) | |
335 | bitrev8(ctrl->ch_status[2]); | |
a2388a49 NC |
336 | regmap_write(regmap, REG_SPDIF_STCSCH, ch_status); |
337 | ||
338 | dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status); | |
339 | ||
340 | ch_status = bitrev8(ctrl->ch_status[3]) << 16; | |
341 | regmap_write(regmap, REG_SPDIF_STCSCL, ch_status); | |
342 | ||
343 | dev_dbg(&pdev->dev, "STCSCL: 0x%06x\n", ch_status); | |
344 | } | |
345 | ||
346 | /* Set SPDIF PhaseConfig register for rx clock */ | |
347 | static int spdif_set_rx_clksrc(struct fsl_spdif_priv *spdif_priv, | |
348 | enum spdif_gainsel gainsel, int dpll_locked) | |
349 | { | |
350 | struct regmap *regmap = spdif_priv->regmap; | |
351 | u8 clksrc = spdif_priv->rxclk_src; | |
352 | ||
353 | if (clksrc >= SRPC_CLKSRC_MAX || gainsel >= GAINSEL_MULTI_MAX) | |
354 | return -EINVAL; | |
355 | ||
356 | regmap_update_bits(regmap, REG_SPDIF_SRPC, | |
357 | SRPC_CLKSRC_SEL_MASK | SRPC_GAINSEL_MASK, | |
358 | SRPC_CLKSRC_SEL_SET(clksrc) | SRPC_GAINSEL_SET(gainsel)); | |
359 | ||
360 | return 0; | |
361 | } | |
362 | ||
363 | static int spdif_set_sample_rate(struct snd_pcm_substream *substream, | |
364 | int sample_rate) | |
365 | { | |
366 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
367 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | |
368 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | |
369 | struct regmap *regmap = spdif_priv->regmap; | |
370 | struct platform_device *pdev = spdif_priv->pdev; | |
371 | unsigned long csfs = 0; | |
372 | u32 stc, mask, rate; | |
27c647bf | 373 | u8 clk, txclk_df, sysclk_df; |
a2388a49 NC |
374 | int ret; |
375 | ||
376 | switch (sample_rate) { | |
377 | case 32000: | |
378 | rate = SPDIF_TXRATE_32000; | |
379 | csfs = IEC958_AES3_CON_FS_32000; | |
380 | break; | |
381 | case 44100: | |
382 | rate = SPDIF_TXRATE_44100; | |
383 | csfs = IEC958_AES3_CON_FS_44100; | |
384 | break; | |
385 | case 48000: | |
386 | rate = SPDIF_TXRATE_48000; | |
387 | csfs = IEC958_AES3_CON_FS_48000; | |
388 | break; | |
c7dfeed1 AH |
389 | case 96000: |
390 | rate = SPDIF_TXRATE_96000; | |
391 | csfs = IEC958_AES3_CON_FS_96000; | |
392 | break; | |
393 | case 192000: | |
394 | rate = SPDIF_TXRATE_192000; | |
395 | csfs = IEC958_AES3_CON_FS_192000; | |
396 | break; | |
a2388a49 NC |
397 | default: |
398 | dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate); | |
399 | return -EINVAL; | |
400 | } | |
401 | ||
402 | clk = spdif_priv->txclk_src[rate]; | |
403 | if (clk >= STC_TXCLK_SRC_MAX) { | |
404 | dev_err(&pdev->dev, "tx clock source is out of range\n"); | |
405 | return -EINVAL; | |
406 | } | |
407 | ||
e41a4a79 NC |
408 | txclk_df = spdif_priv->txclk_df[rate]; |
409 | if (txclk_df == 0) { | |
410 | dev_err(&pdev->dev, "the txclk_df can't be zero\n"); | |
a2388a49 NC |
411 | return -EINVAL; |
412 | } | |
413 | ||
27c647bf NC |
414 | sysclk_df = spdif_priv->sysclk_df[rate]; |
415 | ||
9c6344b3 NC |
416 | /* Don't mess up the clocks from other modules */ |
417 | if (clk != STC_TXCLK_SPDIF_ROOT) | |
418 | goto clk_set_bypass; | |
419 | ||
f490f326 NC |
420 | /* The S/PDIF block needs a clock of 64 * fs * txclk_df */ |
421 | ret = clk_set_rate(spdif_priv->txclk[rate], | |
422 | 64 * sample_rate * txclk_df); | |
a2388a49 NC |
423 | if (ret) { |
424 | dev_err(&pdev->dev, "failed to set tx clock rate\n"); | |
425 | return ret; | |
426 | } | |
427 | ||
9c6344b3 | 428 | clk_set_bypass: |
a2388a49 | 429 | dev_dbg(&pdev->dev, "expected clock rate = %d\n", |
27c647bf | 430 | (64 * sample_rate * txclk_df * sysclk_df)); |
a2388a49 NC |
431 | dev_dbg(&pdev->dev, "actual clock rate = %ld\n", |
432 | clk_get_rate(spdif_priv->txclk[rate])); | |
433 | ||
434 | /* set fs field in consumer channel status */ | |
435 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs); | |
436 | ||
437 | /* select clock source and divisor */ | |
f3a30baa NC |
438 | stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | |
439 | STC_TXCLK_DF(txclk_df) | STC_SYSCLK_DF(sysclk_df); | |
440 | mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | | |
441 | STC_TXCLK_DF_MASK | STC_SYSCLK_DF_MASK; | |
a2388a49 NC |
442 | regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc); |
443 | ||
527cda78 NC |
444 | dev_dbg(&pdev->dev, "set sample rate to %dHz for %dHz playback\n", |
445 | spdif_priv->txrate[rate], sample_rate); | |
a2388a49 NC |
446 | |
447 | return 0; | |
448 | } | |
449 | ||
6b4c80f9 MB |
450 | static int fsl_spdif_startup(struct snd_pcm_substream *substream, |
451 | struct snd_soc_dai *cpu_dai) | |
a2388a49 NC |
452 | { |
453 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
454 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | |
455 | struct platform_device *pdev = spdif_priv->pdev; | |
456 | struct regmap *regmap = spdif_priv->regmap; | |
457 | u32 scr, mask, i; | |
458 | int ret; | |
459 | ||
460 | /* Reset module and interrupts only for first initialization */ | |
461 | if (!cpu_dai->active) { | |
08f7336e NC |
462 | ret = clk_prepare_enable(spdif_priv->coreclk); |
463 | if (ret) { | |
464 | dev_err(&pdev->dev, "failed to enable core clock\n"); | |
465 | return ret; | |
466 | } | |
467 | ||
a2388a49 NC |
468 | ret = spdif_softreset(spdif_priv); |
469 | if (ret) { | |
470 | dev_err(&pdev->dev, "failed to soft reset\n"); | |
08f7336e | 471 | goto err; |
a2388a49 NC |
472 | } |
473 | ||
474 | /* Disable all the interrupts */ | |
475 | regmap_update_bits(regmap, REG_SPDIF_SIE, 0xffffff, 0); | |
476 | } | |
477 | ||
478 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
479 | scr = SCR_TXFIFO_AUTOSYNC | SCR_TXFIFO_CTRL_NORMAL | | |
480 | SCR_TXSEL_NORMAL | SCR_USRC_SEL_CHIP | | |
481 | SCR_TXFIFO_FSEL_IF8; | |
482 | mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK | | |
483 | SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | | |
484 | SCR_TXFIFO_FSEL_MASK; | |
485 | for (i = 0; i < SPDIF_TXRATE_MAX; i++) | |
486 | clk_prepare_enable(spdif_priv->txclk[i]); | |
487 | } else { | |
488 | scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC; | |
489 | mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK| | |
490 | SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK; | |
491 | clk_prepare_enable(spdif_priv->rxclk); | |
492 | } | |
493 | regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); | |
494 | ||
495 | /* Power up SPDIF module */ | |
496 | regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_LOW_POWER, 0); | |
497 | ||
498 | return 0; | |
08f7336e NC |
499 | |
500 | err: | |
501 | clk_disable_unprepare(spdif_priv->coreclk); | |
502 | ||
503 | return ret; | |
a2388a49 NC |
504 | } |
505 | ||
506 | static void fsl_spdif_shutdown(struct snd_pcm_substream *substream, | |
507 | struct snd_soc_dai *cpu_dai) | |
508 | { | |
509 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
510 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | |
511 | struct regmap *regmap = spdif_priv->regmap; | |
512 | u32 scr, mask, i; | |
513 | ||
514 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
515 | scr = 0; | |
516 | mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK | | |
517 | SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | | |
518 | SCR_TXFIFO_FSEL_MASK; | |
519 | for (i = 0; i < SPDIF_TXRATE_MAX; i++) | |
520 | clk_disable_unprepare(spdif_priv->txclk[i]); | |
521 | } else { | |
522 | scr = SCR_RXFIFO_OFF | SCR_RXFIFO_CTL_ZERO; | |
523 | mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK| | |
524 | SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK; | |
525 | clk_disable_unprepare(spdif_priv->rxclk); | |
526 | } | |
527 | regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); | |
528 | ||
529 | /* Power down SPDIF module only if tx&rx are both inactive */ | |
530 | if (!cpu_dai->active) { | |
531 | spdif_intr_status_clear(spdif_priv); | |
532 | regmap_update_bits(regmap, REG_SPDIF_SCR, | |
533 | SCR_LOW_POWER, SCR_LOW_POWER); | |
08f7336e | 534 | clk_disable_unprepare(spdif_priv->coreclk); |
a2388a49 NC |
535 | } |
536 | } | |
537 | ||
538 | static int fsl_spdif_hw_params(struct snd_pcm_substream *substream, | |
539 | struct snd_pcm_hw_params *params, | |
540 | struct snd_soc_dai *dai) | |
541 | { | |
542 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
543 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | |
544 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | |
545 | struct platform_device *pdev = spdif_priv->pdev; | |
546 | u32 sample_rate = params_rate(params); | |
547 | int ret = 0; | |
548 | ||
549 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
550 | ret = spdif_set_sample_rate(substream, sample_rate); | |
551 | if (ret) { | |
552 | dev_err(&pdev->dev, "%s: set sample rate failed: %d\n", | |
553 | __func__, sample_rate); | |
554 | return ret; | |
555 | } | |
556 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK, | |
f3a30baa | 557 | IEC958_AES3_CON_CLOCK_1000PPM); |
a2388a49 NC |
558 | spdif_write_channel_status(spdif_priv); |
559 | } else { | |
560 | /* Setup rx clock source */ | |
561 | ret = spdif_set_rx_clksrc(spdif_priv, SPDIF_DEFAULT_GAINSEL, 1); | |
562 | } | |
563 | ||
564 | return ret; | |
565 | } | |
566 | ||
567 | static int fsl_spdif_trigger(struct snd_pcm_substream *substream, | |
568 | int cmd, struct snd_soc_dai *dai) | |
569 | { | |
570 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
571 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | |
572 | struct regmap *regmap = spdif_priv->regmap; | |
f3a30baa NC |
573 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
574 | u32 intr = SIE_INTR_FOR(tx); | |
575 | u32 dmaen = SCR_DMA_xX_EN(tx); | |
a2388a49 NC |
576 | |
577 | switch (cmd) { | |
578 | case SNDRV_PCM_TRIGGER_START: | |
579 | case SNDRV_PCM_TRIGGER_RESUME: | |
580 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | |
581 | regmap_update_bits(regmap, REG_SPDIF_SIE, intr, intr); | |
582 | regmap_update_bits(regmap, REG_SPDIF_SCR, dmaen, dmaen); | |
583 | break; | |
584 | case SNDRV_PCM_TRIGGER_STOP: | |
585 | case SNDRV_PCM_TRIGGER_SUSPEND: | |
586 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | |
587 | regmap_update_bits(regmap, REG_SPDIF_SCR, dmaen, 0); | |
588 | regmap_update_bits(regmap, REG_SPDIF_SIE, intr, 0); | |
589 | break; | |
590 | default: | |
591 | return -EINVAL; | |
592 | } | |
593 | ||
594 | return 0; | |
595 | } | |
596 | ||
6b4c80f9 | 597 | static struct snd_soc_dai_ops fsl_spdif_dai_ops = { |
a2388a49 NC |
598 | .startup = fsl_spdif_startup, |
599 | .hw_params = fsl_spdif_hw_params, | |
600 | .trigger = fsl_spdif_trigger, | |
601 | .shutdown = fsl_spdif_shutdown, | |
602 | }; | |
603 | ||
604 | ||
605 | /* | |
a2388a49 NC |
606 | * FSL SPDIF IEC958 controller(mixer) functions |
607 | * | |
608 | * Channel status get/put control | |
609 | * User bit value get/put control | |
610 | * Valid bit value get control | |
611 | * DPLL lock status get control | |
612 | * User bit sync mode selection control | |
a2388a49 NC |
613 | */ |
614 | ||
615 | static int fsl_spdif_info(struct snd_kcontrol *kcontrol, | |
616 | struct snd_ctl_elem_info *uinfo) | |
617 | { | |
618 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | |
619 | uinfo->count = 1; | |
620 | ||
621 | return 0; | |
622 | } | |
623 | ||
624 | static int fsl_spdif_pb_get(struct snd_kcontrol *kcontrol, | |
625 | struct snd_ctl_elem_value *uvalue) | |
626 | { | |
627 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
628 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | |
629 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | |
630 | ||
631 | uvalue->value.iec958.status[0] = ctrl->ch_status[0]; | |
632 | uvalue->value.iec958.status[1] = ctrl->ch_status[1]; | |
633 | uvalue->value.iec958.status[2] = ctrl->ch_status[2]; | |
634 | uvalue->value.iec958.status[3] = ctrl->ch_status[3]; | |
635 | ||
636 | return 0; | |
637 | } | |
638 | ||
639 | static int fsl_spdif_pb_put(struct snd_kcontrol *kcontrol, | |
640 | struct snd_ctl_elem_value *uvalue) | |
641 | { | |
642 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
643 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | |
644 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | |
645 | ||
646 | ctrl->ch_status[0] = uvalue->value.iec958.status[0]; | |
647 | ctrl->ch_status[1] = uvalue->value.iec958.status[1]; | |
648 | ctrl->ch_status[2] = uvalue->value.iec958.status[2]; | |
649 | ctrl->ch_status[3] = uvalue->value.iec958.status[3]; | |
650 | ||
651 | spdif_write_channel_status(spdif_priv); | |
652 | ||
653 | return 0; | |
654 | } | |
655 | ||
656 | /* Get channel status from SPDIF_RX_CCHAN register */ | |
657 | static int fsl_spdif_capture_get(struct snd_kcontrol *kcontrol, | |
658 | struct snd_ctl_elem_value *ucontrol) | |
659 | { | |
660 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
661 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | |
662 | struct regmap *regmap = spdif_priv->regmap; | |
663 | u32 cstatus, val; | |
664 | ||
665 | regmap_read(regmap, REG_SPDIF_SIS, &val); | |
f3a30baa | 666 | if (!(val & INT_CNEW)) |
a2388a49 | 667 | return -EAGAIN; |
a2388a49 NC |
668 | |
669 | regmap_read(regmap, REG_SPDIF_SRCSH, &cstatus); | |
670 | ucontrol->value.iec958.status[0] = (cstatus >> 16) & 0xFF; | |
671 | ucontrol->value.iec958.status[1] = (cstatus >> 8) & 0xFF; | |
672 | ucontrol->value.iec958.status[2] = cstatus & 0xFF; | |
673 | ||
674 | regmap_read(regmap, REG_SPDIF_SRCSL, &cstatus); | |
675 | ucontrol->value.iec958.status[3] = (cstatus >> 16) & 0xFF; | |
676 | ucontrol->value.iec958.status[4] = (cstatus >> 8) & 0xFF; | |
677 | ucontrol->value.iec958.status[5] = cstatus & 0xFF; | |
678 | ||
679 | /* Clear intr */ | |
680 | regmap_write(regmap, REG_SPDIF_SIC, INT_CNEW); | |
681 | ||
682 | return 0; | |
683 | } | |
684 | ||
685 | /* | |
686 | * Get User bits (subcode) from chip value which readed out | |
687 | * in UChannel register. | |
688 | */ | |
689 | static int fsl_spdif_subcode_get(struct snd_kcontrol *kcontrol, | |
690 | struct snd_ctl_elem_value *ucontrol) | |
691 | { | |
692 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
693 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | |
694 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | |
695 | unsigned long flags; | |
f3a30baa | 696 | int ret = -EAGAIN; |
a2388a49 NC |
697 | |
698 | spin_lock_irqsave(&ctrl->ctl_lock, flags); | |
699 | if (ctrl->ready_buf) { | |
700 | int idx = (ctrl->ready_buf - 1) * SPDIF_UBITS_SIZE; | |
701 | memcpy(&ucontrol->value.iec958.subcode[0], | |
702 | &ctrl->subcode[idx], SPDIF_UBITS_SIZE); | |
f3a30baa | 703 | ret = 0; |
a2388a49 NC |
704 | } |
705 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); | |
706 | ||
707 | return ret; | |
708 | } | |
709 | ||
710 | /* Q-subcode infomation. The byte size is SPDIF_UBITS_SIZE/8 */ | |
711 | static int fsl_spdif_qinfo(struct snd_kcontrol *kcontrol, | |
712 | struct snd_ctl_elem_info *uinfo) | |
713 | { | |
714 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | |
715 | uinfo->count = SPDIF_QSUB_SIZE; | |
716 | ||
717 | return 0; | |
718 | } | |
719 | ||
720 | /* Get Q subcode from chip value which readed out in QChannel register */ | |
721 | static int fsl_spdif_qget(struct snd_kcontrol *kcontrol, | |
722 | struct snd_ctl_elem_value *ucontrol) | |
723 | { | |
724 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
725 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | |
726 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | |
727 | unsigned long flags; | |
f3a30baa | 728 | int ret = -EAGAIN; |
a2388a49 NC |
729 | |
730 | spin_lock_irqsave(&ctrl->ctl_lock, flags); | |
731 | if (ctrl->ready_buf) { | |
732 | int idx = (ctrl->ready_buf - 1) * SPDIF_QSUB_SIZE; | |
733 | memcpy(&ucontrol->value.bytes.data[0], | |
734 | &ctrl->qsub[idx], SPDIF_QSUB_SIZE); | |
f3a30baa | 735 | ret = 0; |
a2388a49 NC |
736 | } |
737 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); | |
738 | ||
739 | return ret; | |
740 | } | |
741 | ||
742 | /* Valid bit infomation */ | |
743 | static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol, | |
744 | struct snd_ctl_elem_info *uinfo) | |
745 | { | |
746 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | |
747 | uinfo->count = 1; | |
748 | uinfo->value.integer.min = 0; | |
749 | uinfo->value.integer.max = 1; | |
750 | ||
751 | return 0; | |
752 | } | |
753 | ||
754 | /* Get valid good bit from interrupt status register */ | |
755 | static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol, | |
756 | struct snd_ctl_elem_value *ucontrol) | |
757 | { | |
758 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
759 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | |
760 | struct regmap *regmap = spdif_priv->regmap; | |
761 | u32 val; | |
762 | ||
e9b383dc | 763 | regmap_read(regmap, REG_SPDIF_SIS, &val); |
a2388a49 NC |
764 | ucontrol->value.integer.value[0] = (val & INT_VAL_NOGOOD) != 0; |
765 | regmap_write(regmap, REG_SPDIF_SIC, INT_VAL_NOGOOD); | |
766 | ||
767 | return 0; | |
768 | } | |
769 | ||
770 | /* DPLL lock infomation */ | |
771 | static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol, | |
772 | struct snd_ctl_elem_info *uinfo) | |
773 | { | |
774 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
775 | uinfo->count = 1; | |
776 | uinfo->value.integer.min = 16000; | |
777 | uinfo->value.integer.max = 96000; | |
778 | ||
779 | return 0; | |
780 | } | |
781 | ||
782 | static u32 gainsel_multi[GAINSEL_MULTI_MAX] = { | |
783 | 24, 16, 12, 8, 6, 4, 3, | |
784 | }; | |
785 | ||
786 | /* Get RX data clock rate given the SPDIF bus_clk */ | |
787 | static int spdif_get_rxclk_rate(struct fsl_spdif_priv *spdif_priv, | |
788 | enum spdif_gainsel gainsel) | |
789 | { | |
790 | struct regmap *regmap = spdif_priv->regmap; | |
791 | struct platform_device *pdev = spdif_priv->pdev; | |
792 | u64 tmpval64, busclk_freq = 0; | |
793 | u32 freqmeas, phaseconf; | |
794 | u8 clksrc; | |
795 | ||
796 | regmap_read(regmap, REG_SPDIF_SRFM, &freqmeas); | |
797 | regmap_read(regmap, REG_SPDIF_SRPC, &phaseconf); | |
798 | ||
799 | clksrc = (phaseconf >> SRPC_CLKSRC_SEL_OFFSET) & 0xf; | |
f3a30baa NC |
800 | |
801 | /* Get bus clock from system */ | |
802 | if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED)) | |
0b864390 | 803 | busclk_freq = clk_get_rate(spdif_priv->sysclk); |
a2388a49 NC |
804 | |
805 | /* FreqMeas_CLK = (BUS_CLK * FreqMeas) / 2 ^ 10 / GAINSEL / 128 */ | |
806 | tmpval64 = (u64) busclk_freq * freqmeas; | |
807 | do_div(tmpval64, gainsel_multi[gainsel] * 1024); | |
808 | do_div(tmpval64, 128 * 1024); | |
809 | ||
810 | dev_dbg(&pdev->dev, "FreqMeas: %d\n", freqmeas); | |
811 | dev_dbg(&pdev->dev, "BusclkFreq: %lld\n", busclk_freq); | |
812 | dev_dbg(&pdev->dev, "RxRate: %lld\n", tmpval64); | |
813 | ||
814 | return (int)tmpval64; | |
815 | } | |
816 | ||
817 | /* | |
818 | * Get DPLL lock or not info from stable interrupt status register. | |
819 | * User application must use this control to get locked, | |
820 | * then can do next PCM operation | |
821 | */ | |
822 | static int fsl_spdif_rxrate_get(struct snd_kcontrol *kcontrol, | |
823 | struct snd_ctl_elem_value *ucontrol) | |
824 | { | |
825 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
826 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | |
f3a30baa | 827 | int rate = 0; |
a2388a49 NC |
828 | |
829 | if (spdif_priv->dpll_locked) | |
f3a30baa NC |
830 | rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL); |
831 | ||
832 | ucontrol->value.integer.value[0] = rate; | |
a2388a49 NC |
833 | |
834 | return 0; | |
835 | } | |
836 | ||
837 | /* User bit sync mode info */ | |
838 | static int fsl_spdif_usync_info(struct snd_kcontrol *kcontrol, | |
839 | struct snd_ctl_elem_info *uinfo) | |
840 | { | |
841 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | |
842 | uinfo->count = 1; | |
843 | uinfo->value.integer.min = 0; | |
844 | uinfo->value.integer.max = 1; | |
845 | ||
846 | return 0; | |
847 | } | |
848 | ||
849 | /* | |
850 | * User bit sync mode: | |
851 | * 1 CD User channel subcode | |
852 | * 0 Non-CD data | |
853 | */ | |
854 | static int fsl_spdif_usync_get(struct snd_kcontrol *kcontrol, | |
855 | struct snd_ctl_elem_value *ucontrol) | |
856 | { | |
857 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
858 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | |
859 | struct regmap *regmap = spdif_priv->regmap; | |
860 | u32 val; | |
861 | ||
862 | regmap_read(regmap, REG_SPDIF_SRCD, &val); | |
863 | ucontrol->value.integer.value[0] = (val & SRCD_CD_USER) != 0; | |
864 | ||
865 | return 0; | |
866 | } | |
867 | ||
868 | /* | |
869 | * User bit sync mode: | |
870 | * 1 CD User channel subcode | |
871 | * 0 Non-CD data | |
872 | */ | |
873 | static int fsl_spdif_usync_put(struct snd_kcontrol *kcontrol, | |
874 | struct snd_ctl_elem_value *ucontrol) | |
875 | { | |
876 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | |
877 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | |
878 | struct regmap *regmap = spdif_priv->regmap; | |
879 | u32 val = ucontrol->value.integer.value[0] << SRCD_CD_USER_OFFSET; | |
880 | ||
881 | regmap_update_bits(regmap, REG_SPDIF_SRCD, SRCD_CD_USER, val); | |
882 | ||
883 | return 0; | |
884 | } | |
885 | ||
886 | /* FSL SPDIF IEC958 controller defines */ | |
887 | static struct snd_kcontrol_new fsl_spdif_ctrls[] = { | |
888 | /* Status cchanel controller */ | |
889 | { | |
890 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
891 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), | |
892 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
893 | SNDRV_CTL_ELEM_ACCESS_WRITE | | |
894 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
895 | .info = fsl_spdif_info, | |
896 | .get = fsl_spdif_pb_get, | |
897 | .put = fsl_spdif_pb_put, | |
898 | }, | |
899 | { | |
900 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
901 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), | |
902 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
903 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
904 | .info = fsl_spdif_info, | |
905 | .get = fsl_spdif_capture_get, | |
906 | }, | |
907 | /* User bits controller */ | |
908 | { | |
909 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
910 | .name = "IEC958 Subcode Capture Default", | |
911 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
912 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
913 | .info = fsl_spdif_info, | |
914 | .get = fsl_spdif_subcode_get, | |
915 | }, | |
916 | { | |
917 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
918 | .name = "IEC958 Q-subcode Capture Default", | |
919 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
920 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
921 | .info = fsl_spdif_qinfo, | |
922 | .get = fsl_spdif_qget, | |
923 | }, | |
924 | /* Valid bit error controller */ | |
925 | { | |
926 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
927 | .name = "IEC958 V-Bit Errors", | |
928 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
929 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
930 | .info = fsl_spdif_vbit_info, | |
931 | .get = fsl_spdif_vbit_get, | |
932 | }, | |
933 | /* DPLL lock info get controller */ | |
934 | { | |
935 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
936 | .name = "RX Sample Rate", | |
937 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
938 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
939 | .info = fsl_spdif_rxrate_info, | |
940 | .get = fsl_spdif_rxrate_get, | |
941 | }, | |
942 | /* User bit sync mode set/get controller */ | |
943 | { | |
944 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
945 | .name = "IEC958 USyncMode CDText", | |
946 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | |
947 | SNDRV_CTL_ELEM_ACCESS_WRITE | | |
948 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
949 | .info = fsl_spdif_usync_info, | |
950 | .get = fsl_spdif_usync_get, | |
951 | .put = fsl_spdif_usync_put, | |
952 | }, | |
953 | }; | |
954 | ||
955 | static int fsl_spdif_dai_probe(struct snd_soc_dai *dai) | |
956 | { | |
957 | struct fsl_spdif_priv *spdif_private = snd_soc_dai_get_drvdata(dai); | |
958 | ||
05cf482d XL |
959 | snd_soc_dai_init_dma_data(dai, &spdif_private->dma_params_tx, |
960 | &spdif_private->dma_params_rx); | |
a2388a49 NC |
961 | |
962 | snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls)); | |
963 | ||
964 | return 0; | |
965 | } | |
966 | ||
6b4c80f9 | 967 | static struct snd_soc_dai_driver fsl_spdif_dai = { |
a2388a49 NC |
968 | .probe = &fsl_spdif_dai_probe, |
969 | .playback = { | |
75640932 | 970 | .stream_name = "CPU-Playback", |
a2388a49 NC |
971 | .channels_min = 2, |
972 | .channels_max = 2, | |
973 | .rates = FSL_SPDIF_RATES_PLAYBACK, | |
974 | .formats = FSL_SPDIF_FORMATS_PLAYBACK, | |
975 | }, | |
976 | .capture = { | |
75640932 | 977 | .stream_name = "CPU-Capture", |
a2388a49 NC |
978 | .channels_min = 2, |
979 | .channels_max = 2, | |
980 | .rates = FSL_SPDIF_RATES_CAPTURE, | |
981 | .formats = FSL_SPDIF_FORMATS_CAPTURE, | |
982 | }, | |
983 | .ops = &fsl_spdif_dai_ops, | |
984 | }; | |
985 | ||
986 | static const struct snd_soc_component_driver fsl_spdif_component = { | |
987 | .name = "fsl-spdif", | |
988 | }; | |
989 | ||
6d22db43 | 990 | /* FSL SPDIF REGMAP */ |
a2388a49 NC |
991 | |
992 | static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg) | |
993 | { | |
994 | switch (reg) { | |
995 | case REG_SPDIF_SCR: | |
996 | case REG_SPDIF_SRCD: | |
997 | case REG_SPDIF_SRPC: | |
998 | case REG_SPDIF_SIE: | |
999 | case REG_SPDIF_SIS: | |
1000 | case REG_SPDIF_SRL: | |
1001 | case REG_SPDIF_SRR: | |
1002 | case REG_SPDIF_SRCSH: | |
1003 | case REG_SPDIF_SRCSL: | |
1004 | case REG_SPDIF_SRU: | |
1005 | case REG_SPDIF_SRQ: | |
1006 | case REG_SPDIF_STCSCH: | |
1007 | case REG_SPDIF_STCSCL: | |
1008 | case REG_SPDIF_SRFM: | |
1009 | case REG_SPDIF_STC: | |
1010 | return true; | |
1011 | default: | |
1012 | return false; | |
e19bcb6b | 1013 | } |
a2388a49 NC |
1014 | } |
1015 | ||
1016 | static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg) | |
1017 | { | |
1018 | switch (reg) { | |
1019 | case REG_SPDIF_SCR: | |
1020 | case REG_SPDIF_SRCD: | |
1021 | case REG_SPDIF_SRPC: | |
1022 | case REG_SPDIF_SIE: | |
1023 | case REG_SPDIF_SIC: | |
1024 | case REG_SPDIF_STL: | |
1025 | case REG_SPDIF_STR: | |
1026 | case REG_SPDIF_STCSCH: | |
1027 | case REG_SPDIF_STCSCL: | |
1028 | case REG_SPDIF_STC: | |
1029 | return true; | |
1030 | default: | |
1031 | return false; | |
e19bcb6b | 1032 | } |
a2388a49 NC |
1033 | } |
1034 | ||
66491507 | 1035 | static const struct regmap_config fsl_spdif_regmap_config = { |
a2388a49 NC |
1036 | .reg_bits = 32, |
1037 | .reg_stride = 4, | |
1038 | .val_bits = 32, | |
1039 | ||
1040 | .max_register = REG_SPDIF_STC, | |
1041 | .readable_reg = fsl_spdif_readable_reg, | |
1042 | .writeable_reg = fsl_spdif_writeable_reg, | |
1043 | }; | |
1044 | ||
1045 | static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, | |
1046 | struct clk *clk, u64 savesub, | |
9c6344b3 | 1047 | enum spdif_txrate index, bool round) |
a2388a49 | 1048 | { |
c7dfeed1 | 1049 | const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 }; |
81efec85 | 1050 | bool is_sysclk = clk_is_match(clk, spdif_priv->sysclk); |
a2388a49 | 1051 | u64 rate_ideal, rate_actual, sub; |
27c647bf NC |
1052 | u32 sysclk_dfmin, sysclk_dfmax; |
1053 | u32 txclk_df, sysclk_df, arate; | |
1054 | ||
1055 | /* The sysclk has an extra divisor [2, 512] */ | |
1056 | sysclk_dfmin = is_sysclk ? 2 : 1; | |
1057 | sysclk_dfmax = is_sysclk ? 512 : 1; | |
1058 | ||
1059 | for (sysclk_df = sysclk_dfmin; sysclk_df <= sysclk_dfmax; sysclk_df++) { | |
1060 | for (txclk_df = 1; txclk_df <= 128; txclk_df++) { | |
f490f326 | 1061 | rate_ideal = rate[index] * txclk_df * 64; |
27c647bf NC |
1062 | if (round) |
1063 | rate_actual = clk_round_rate(clk, rate_ideal); | |
1064 | else | |
1065 | rate_actual = clk_get_rate(clk); | |
1066 | ||
1067 | arate = rate_actual / 64; | |
1068 | arate /= txclk_df * sysclk_df; | |
1069 | ||
1070 | if (arate == rate[index]) { | |
1071 | /* We are lucky */ | |
1072 | savesub = 0; | |
1073 | spdif_priv->txclk_df[index] = txclk_df; | |
1074 | spdif_priv->sysclk_df[index] = sysclk_df; | |
527cda78 | 1075 | spdif_priv->txrate[index] = arate; |
27c647bf NC |
1076 | goto out; |
1077 | } else if (arate / rate[index] == 1) { | |
1078 | /* A little bigger than expect */ | |
c89c7e94 | 1079 | sub = (u64)(arate - rate[index]) * 100000; |
27c647bf NC |
1080 | do_div(sub, rate[index]); |
1081 | if (sub >= savesub) | |
1082 | continue; | |
a2388a49 | 1083 | savesub = sub; |
e41a4a79 | 1084 | spdif_priv->txclk_df[index] = txclk_df; |
27c647bf | 1085 | spdif_priv->sysclk_df[index] = sysclk_df; |
527cda78 | 1086 | spdif_priv->txrate[index] = arate; |
27c647bf NC |
1087 | } else if (rate[index] / arate == 1) { |
1088 | /* A little smaller than expect */ | |
c89c7e94 | 1089 | sub = (u64)(rate[index] - arate) * 100000; |
27c647bf NC |
1090 | do_div(sub, rate[index]); |
1091 | if (sub >= savesub) | |
1092 | continue; | |
a2388a49 | 1093 | savesub = sub; |
e41a4a79 | 1094 | spdif_priv->txclk_df[index] = txclk_df; |
27c647bf | 1095 | spdif_priv->sysclk_df[index] = sysclk_df; |
527cda78 | 1096 | spdif_priv->txrate[index] = arate; |
a2388a49 NC |
1097 | } |
1098 | } | |
1099 | } | |
1100 | ||
27c647bf | 1101 | out: |
a2388a49 NC |
1102 | return savesub; |
1103 | } | |
1104 | ||
1105 | static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, | |
1106 | enum spdif_txrate index) | |
1107 | { | |
c7dfeed1 | 1108 | const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 }; |
a2388a49 NC |
1109 | struct platform_device *pdev = spdif_priv->pdev; |
1110 | struct device *dev = &pdev->dev; | |
1111 | u64 savesub = 100000, ret; | |
1112 | struct clk *clk; | |
1113 | char tmp[16]; | |
1114 | int i; | |
1115 | ||
1116 | for (i = 0; i < STC_TXCLK_SRC_MAX; i++) { | |
1117 | sprintf(tmp, "rxtx%d", i); | |
1118 | clk = devm_clk_get(&pdev->dev, tmp); | |
1119 | if (IS_ERR(clk)) { | |
1120 | dev_err(dev, "no rxtx%d clock in devicetree\n", i); | |
1121 | return PTR_ERR(clk); | |
1122 | } | |
1123 | if (!clk_get_rate(clk)) | |
1124 | continue; | |
1125 | ||
9c6344b3 NC |
1126 | ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index, |
1127 | i == STC_TXCLK_SPDIF_ROOT); | |
a2388a49 NC |
1128 | if (savesub == ret) |
1129 | continue; | |
1130 | ||
1131 | savesub = ret; | |
1132 | spdif_priv->txclk[index] = clk; | |
1133 | spdif_priv->txclk_src[index] = i; | |
1134 | ||
1135 | /* To quick catch a divisor, we allow a 0.1% deviation */ | |
1136 | if (savesub < 100) | |
1137 | break; | |
1138 | } | |
1139 | ||
8a309d71 | 1140 | dev_dbg(&pdev->dev, "use rxtx%d as tx clock source for %dHz sample rate\n", |
a2388a49 | 1141 | spdif_priv->txclk_src[index], rate[index]); |
e41a4a79 NC |
1142 | dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n", |
1143 | spdif_priv->txclk_df[index], rate[index]); | |
81efec85 | 1144 | if (clk_is_match(spdif_priv->txclk[index], spdif_priv->sysclk)) |
27c647bf NC |
1145 | dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n", |
1146 | spdif_priv->sysclk_df[index], rate[index]); | |
527cda78 NC |
1147 | dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n", |
1148 | rate[index], spdif_priv->txrate[index]); | |
a2388a49 NC |
1149 | |
1150 | return 0; | |
1151 | } | |
1152 | ||
1153 | static int fsl_spdif_probe(struct platform_device *pdev) | |
1154 | { | |
1155 | struct device_node *np = pdev->dev.of_node; | |
1156 | struct fsl_spdif_priv *spdif_priv; | |
1157 | struct spdif_mixer_control *ctrl; | |
1158 | struct resource *res; | |
1159 | void __iomem *regs; | |
1160 | int irq, ret, i; | |
1161 | ||
1162 | if (!np) | |
1163 | return -ENODEV; | |
1164 | ||
7c27ba46 | 1165 | spdif_priv = devm_kzalloc(&pdev->dev, sizeof(*spdif_priv), GFP_KERNEL); |
a2388a49 NC |
1166 | if (!spdif_priv) |
1167 | return -ENOMEM; | |
1168 | ||
a2388a49 NC |
1169 | spdif_priv->pdev = pdev; |
1170 | ||
1171 | /* Initialize this copy of the CPU DAI driver structure */ | |
1172 | memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); | |
7c27ba46 | 1173 | spdif_priv->cpu_dai_drv.name = dev_name(&pdev->dev); |
a2388a49 NC |
1174 | |
1175 | /* Get the addresses and IRQ */ | |
1176 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
a2388a49 | 1177 | regs = devm_ioremap_resource(&pdev->dev, res); |
bfd7d1aa | 1178 | if (IS_ERR(regs)) |
a2388a49 | 1179 | return PTR_ERR(regs); |
a2388a49 NC |
1180 | |
1181 | spdif_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, | |
1182 | "core", regs, &fsl_spdif_regmap_config); | |
1183 | if (IS_ERR(spdif_priv->regmap)) { | |
1184 | dev_err(&pdev->dev, "regmap init failed\n"); | |
1185 | return PTR_ERR(spdif_priv->regmap); | |
1186 | } | |
1187 | ||
1188 | irq = platform_get_irq(pdev, 0); | |
1189 | if (irq < 0) { | |
b968d83f | 1190 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); |
a2388a49 NC |
1191 | return irq; |
1192 | } | |
1193 | ||
1194 | ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0, | |
7c27ba46 | 1195 | dev_name(&pdev->dev), spdif_priv); |
a2388a49 NC |
1196 | if (ret) { |
1197 | dev_err(&pdev->dev, "could not claim irq %u\n", irq); | |
1198 | return ret; | |
1199 | } | |
1200 | ||
0b864390 NC |
1201 | /* Get system clock for rx clock rate calculation */ |
1202 | spdif_priv->sysclk = devm_clk_get(&pdev->dev, "rxtx5"); | |
1203 | if (IS_ERR(spdif_priv->sysclk)) { | |
1204 | dev_err(&pdev->dev, "no sys clock (rxtx5) in devicetree\n"); | |
1205 | return PTR_ERR(spdif_priv->sysclk); | |
1206 | } | |
1207 | ||
08f7336e NC |
1208 | /* Get core clock for data register access via DMA */ |
1209 | spdif_priv->coreclk = devm_clk_get(&pdev->dev, "core"); | |
1210 | if (IS_ERR(spdif_priv->coreclk)) { | |
1211 | dev_err(&pdev->dev, "no core clock in devicetree\n"); | |
1212 | return PTR_ERR(spdif_priv->coreclk); | |
1213 | } | |
1214 | ||
a2388a49 NC |
1215 | /* Select clock source for rx/tx clock */ |
1216 | spdif_priv->rxclk = devm_clk_get(&pdev->dev, "rxtx1"); | |
1217 | if (IS_ERR(spdif_priv->rxclk)) { | |
1218 | dev_err(&pdev->dev, "no rxtx1 clock in devicetree\n"); | |
1219 | return PTR_ERR(spdif_priv->rxclk); | |
1220 | } | |
1221 | spdif_priv->rxclk_src = DEFAULT_RXCLK_SRC; | |
1222 | ||
1223 | for (i = 0; i < SPDIF_TXRATE_MAX; i++) { | |
1224 | ret = fsl_spdif_probe_txclk(spdif_priv, i); | |
1225 | if (ret) | |
1226 | return ret; | |
1227 | } | |
1228 | ||
1229 | /* Initial spinlock for control data */ | |
1230 | ctrl = &spdif_priv->fsl_spdif_control; | |
1231 | spin_lock_init(&ctrl->ctl_lock); | |
1232 | ||
1233 | /* Init tx channel status default value */ | |
f3a30baa NC |
1234 | ctrl->ch_status[0] = IEC958_AES0_CON_NOT_COPYRIGHT | |
1235 | IEC958_AES0_CON_EMPHASIS_5015; | |
a2388a49 NC |
1236 | ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID; |
1237 | ctrl->ch_status[2] = 0x00; | |
f3a30baa NC |
1238 | ctrl->ch_status[3] = IEC958_AES3_CON_FS_44100 | |
1239 | IEC958_AES3_CON_CLOCK_1000PPM; | |
a2388a49 NC |
1240 | |
1241 | spdif_priv->dpll_locked = false; | |
1242 | ||
1243 | spdif_priv->dma_params_tx.maxburst = FSL_SPDIF_TXFIFO_WML; | |
1244 | spdif_priv->dma_params_rx.maxburst = FSL_SPDIF_RXFIFO_WML; | |
1245 | spdif_priv->dma_params_tx.addr = res->start + REG_SPDIF_STL; | |
1246 | spdif_priv->dma_params_rx.addr = res->start + REG_SPDIF_SRL; | |
1247 | ||
1248 | /* Register with ASoC */ | |
1249 | dev_set_drvdata(&pdev->dev, spdif_priv); | |
1250 | ||
256218ae SK |
1251 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_spdif_component, |
1252 | &spdif_priv->cpu_dai_drv, 1); | |
a2388a49 NC |
1253 | if (ret) { |
1254 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); | |
5af407cd | 1255 | return ret; |
a2388a49 NC |
1256 | } |
1257 | ||
1258 | ret = imx_pcm_dma_init(pdev); | |
256218ae | 1259 | if (ret) |
a2388a49 | 1260 | dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret); |
a2388a49 NC |
1261 | |
1262 | return ret; | |
1263 | } | |
1264 | ||
a2388a49 NC |
1265 | static const struct of_device_id fsl_spdif_dt_ids[] = { |
1266 | { .compatible = "fsl,imx35-spdif", }, | |
1014fad0 | 1267 | { .compatible = "fsl,vf610-spdif", }, |
a2388a49 NC |
1268 | {} |
1269 | }; | |
1270 | MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids); | |
1271 | ||
1272 | static struct platform_driver fsl_spdif_driver = { | |
1273 | .driver = { | |
1274 | .name = "fsl-spdif-dai", | |
a2388a49 NC |
1275 | .of_match_table = fsl_spdif_dt_ids, |
1276 | }, | |
1277 | .probe = fsl_spdif_probe, | |
a2388a49 NC |
1278 | }; |
1279 | ||
1280 | module_platform_driver(fsl_spdif_driver); | |
1281 | ||
1282 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | |
1283 | MODULE_DESCRIPTION("Freescale S/PDIF CPU DAI Driver"); | |
1284 | MODULE_LICENSE("GPL v2"); | |
1285 | MODULE_ALIAS("platform:fsl-spdif-dai"); |