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