2 * IMG SPDIF input controller driver
4 * Copyright (C) 2015 Imagination Technologies Ltd.
6 * Author: Damien Horsley <Damien.Horsley@imgtec.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
13 #include <linux/clk.h>
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/reset.h>
21 #include <sound/core.h>
22 #include <sound/dmaengine_pcm.h>
23 #include <sound/initval.h>
24 #include <sound/pcm.h>
25 #include <sound/pcm_params.h>
26 #include <sound/soc.h>
28 #define IMG_SPDIF_IN_RX_FIFO_OFFSET 0
30 #define IMG_SPDIF_IN_CTL 0x4
31 #define IMG_SPDIF_IN_CTL_LOCKLO_MASK 0xff
32 #define IMG_SPDIF_IN_CTL_LOCKLO_SHIFT 0
33 #define IMG_SPDIF_IN_CTL_LOCKHI_MASK 0xff00
34 #define IMG_SPDIF_IN_CTL_LOCKHI_SHIFT 8
35 #define IMG_SPDIF_IN_CTL_TRK_MASK 0xff0000
36 #define IMG_SPDIF_IN_CTL_TRK_SHIFT 16
37 #define IMG_SPDIF_IN_CTL_SRD_MASK 0x70000000
38 #define IMG_SPDIF_IN_CTL_SRD_SHIFT 28
39 #define IMG_SPDIF_IN_CTL_SRT_MASK BIT(31)
41 #define IMG_SPDIF_IN_STATUS 0x8
42 #define IMG_SPDIF_IN_STATUS_SAM_MASK 0x7000
43 #define IMG_SPDIF_IN_STATUS_SAM_SHIFT 12
44 #define IMG_SPDIF_IN_STATUS_LOCK_MASK BIT(15)
45 #define IMG_SPDIF_IN_STATUS_LOCK_SHIFT 15
47 #define IMG_SPDIF_IN_CLKGEN 0x1c
48 #define IMG_SPDIF_IN_CLKGEN_NOM_MASK 0x3ff
49 #define IMG_SPDIF_IN_CLKGEN_NOM_SHIFT 0
50 #define IMG_SPDIF_IN_CLKGEN_HLD_MASK 0x3ff0000
51 #define IMG_SPDIF_IN_CLKGEN_HLD_SHIFT 16
53 #define IMG_SPDIF_IN_CSL 0x20
55 #define IMG_SPDIF_IN_CSH 0x24
56 #define IMG_SPDIF_IN_CSH_MASK 0xff
57 #define IMG_SPDIF_IN_CSH_SHIFT 0
59 #define IMG_SPDIF_IN_SOFT_RESET 0x28
60 #define IMG_SPDIF_IN_SOFT_RESET_MASK BIT(0)
62 #define IMG_SPDIF_IN_ACLKGEN_START 0x2c
63 #define IMG_SPDIF_IN_ACLKGEN_NOM_MASK 0x3ff
64 #define IMG_SPDIF_IN_ACLKGEN_NOM_SHIFT 0
65 #define IMG_SPDIF_IN_ACLKGEN_HLD_MASK 0xffc00
66 #define IMG_SPDIF_IN_ACLKGEN_HLD_SHIFT 10
67 #define IMG_SPDIF_IN_ACLKGEN_TRK_MASK 0xff00000
68 #define IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT 20
70 #define IMG_SPDIF_IN_NUM_ACLKGEN 4
76 struct snd_dmaengine_dai_dma_data dma_data
;
82 unsigned int single_freq
;
83 unsigned int multi_freqs
[IMG_SPDIF_IN_NUM_ACLKGEN
];
86 /* Write-only registers */
87 unsigned int aclkgen_regs
[IMG_SPDIF_IN_NUM_ACLKGEN
];
90 static inline void img_spdif_in_writel(struct img_spdif_in
*spdif
,
93 writel(val
, spdif
->base
+ reg
);
96 static inline u32
img_spdif_in_readl(struct img_spdif_in
*spdif
, u32 reg
)
98 return readl(spdif
->base
+ reg
);
101 static inline void img_spdif_in_aclkgen_writel(struct img_spdif_in
*spdif
,
104 img_spdif_in_writel(spdif
, spdif
->aclkgen_regs
[index
],
105 IMG_SPDIF_IN_ACLKGEN_START
+ (index
* 0x4));
108 static int img_spdif_in_check_max_rate(struct img_spdif_in
*spdif
,
109 unsigned int sample_rate
, unsigned long *actual_freq
)
111 unsigned long min_freq
, freq_t
;
113 /* Clock rate must be at least 24x the bit rate */
114 min_freq
= sample_rate
* 2 * 32 * 24;
116 freq_t
= clk_get_rate(spdif
->clk_sys
);
118 if (freq_t
< min_freq
)
121 *actual_freq
= freq_t
;
126 static int img_spdif_in_do_clkgen_calc(unsigned int rate
, unsigned int *pnom
,
127 unsigned int *phld
, unsigned long clk_rate
)
129 unsigned int ori
, nom
, hld
;
132 * Calculate oversampling ratio, nominal phase increment and hold
133 * increment for the given rate / frequency
139 ori
= clk_rate
/ (rate
* 64);
144 nom
= (4096 / ori
) + 1;
146 hld
= 4096 - (--nom
* (ori
- 1));
155 static int img_spdif_in_do_clkgen_single(struct img_spdif_in
*spdif
,
158 unsigned int nom
, hld
;
159 unsigned long flags
, clk_rate
;
163 ret
= img_spdif_in_check_max_rate(spdif
, rate
, &clk_rate
);
167 ret
= img_spdif_in_do_clkgen_calc(rate
, &nom
, &hld
, clk_rate
);
171 reg
= (nom
<< IMG_SPDIF_IN_CLKGEN_NOM_SHIFT
) &
172 IMG_SPDIF_IN_CLKGEN_NOM_MASK
;
173 reg
|= (hld
<< IMG_SPDIF_IN_CLKGEN_HLD_SHIFT
) &
174 IMG_SPDIF_IN_CLKGEN_HLD_MASK
;
176 spin_lock_irqsave(&spdif
->lock
, flags
);
179 spin_unlock_irqrestore(&spdif
->lock
, flags
);
183 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CLKGEN
);
185 spdif
->single_freq
= rate
;
187 spin_unlock_irqrestore(&spdif
->lock
, flags
);
192 static int img_spdif_in_do_clkgen_multi(struct img_spdif_in
*spdif
,
193 unsigned int multi_freqs
[])
195 unsigned int nom
, hld
, rate
, max_rate
= 0;
196 unsigned long flags
, clk_rate
;
198 u32 reg
, trk_reg
, temp_regs
[IMG_SPDIF_IN_NUM_ACLKGEN
];
200 for (i
= 0; i
< IMG_SPDIF_IN_NUM_ACLKGEN
; i
++)
201 if (multi_freqs
[i
] > max_rate
)
202 max_rate
= multi_freqs
[i
];
204 ret
= img_spdif_in_check_max_rate(spdif
, max_rate
, &clk_rate
);
208 for (i
= 0; i
< IMG_SPDIF_IN_NUM_ACLKGEN
; i
++) {
209 rate
= multi_freqs
[i
];
211 ret
= img_spdif_in_do_clkgen_calc(rate
, &nom
, &hld
, clk_rate
);
215 reg
= (nom
<< IMG_SPDIF_IN_ACLKGEN_NOM_SHIFT
) &
216 IMG_SPDIF_IN_ACLKGEN_NOM_MASK
;
217 reg
|= (hld
<< IMG_SPDIF_IN_ACLKGEN_HLD_SHIFT
) &
218 IMG_SPDIF_IN_ACLKGEN_HLD_MASK
;
222 spin_lock_irqsave(&spdif
->lock
, flags
);
225 spin_unlock_irqrestore(&spdif
->lock
, flags
);
229 trk_reg
= spdif
->trk
<< IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT
;
231 for (i
= 0; i
< IMG_SPDIF_IN_NUM_ACLKGEN
; i
++) {
232 spdif
->aclkgen_regs
[i
] = temp_regs
[i
] | trk_reg
;
233 img_spdif_in_aclkgen_writel(spdif
, i
);
236 spdif
->multi_freq
= true;
237 spdif
->multi_freqs
[0] = multi_freqs
[0];
238 spdif
->multi_freqs
[1] = multi_freqs
[1];
239 spdif
->multi_freqs
[2] = multi_freqs
[2];
240 spdif
->multi_freqs
[3] = multi_freqs
[3];
242 spin_unlock_irqrestore(&spdif
->lock
, flags
);
247 static int img_spdif_in_iec958_info(struct snd_kcontrol
*kcontrol
,
248 struct snd_ctl_elem_info
*uinfo
)
250 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_IEC958
;
256 static int img_spdif_in_get_status_mask(struct snd_kcontrol
*kcontrol
,
257 struct snd_ctl_elem_value
*ucontrol
)
259 ucontrol
->value
.iec958
.status
[0] = 0xff;
260 ucontrol
->value
.iec958
.status
[1] = 0xff;
261 ucontrol
->value
.iec958
.status
[2] = 0xff;
262 ucontrol
->value
.iec958
.status
[3] = 0xff;
263 ucontrol
->value
.iec958
.status
[4] = 0xff;
268 static int img_spdif_in_get_status(struct snd_kcontrol
*kcontrol
,
269 struct snd_ctl_elem_value
*ucontrol
)
271 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
272 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
275 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CSL
);
276 ucontrol
->value
.iec958
.status
[0] = reg
& 0xff;
277 ucontrol
->value
.iec958
.status
[1] = (reg
>> 8) & 0xff;
278 ucontrol
->value
.iec958
.status
[2] = (reg
>> 16) & 0xff;
279 ucontrol
->value
.iec958
.status
[3] = (reg
>> 24) & 0xff;
280 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CSH
);
281 ucontrol
->value
.iec958
.status
[4] = (reg
& IMG_SPDIF_IN_CSH_MASK
)
282 >> IMG_SPDIF_IN_CSH_SHIFT
;
287 static int img_spdif_in_info_multi_freq(struct snd_kcontrol
*kcontrol
,
288 struct snd_ctl_elem_info
*uinfo
)
290 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
291 uinfo
->count
= IMG_SPDIF_IN_NUM_ACLKGEN
;
292 uinfo
->value
.integer
.min
= 0;
293 uinfo
->value
.integer
.max
= LONG_MAX
;
298 static int img_spdif_in_get_multi_freq(struct snd_kcontrol
*kcontrol
,
299 struct snd_ctl_elem_value
*ucontrol
)
301 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
302 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
305 spin_lock_irqsave(&spdif
->lock
, flags
);
306 if (spdif
->multi_freq
) {
307 ucontrol
->value
.integer
.value
[0] = spdif
->multi_freqs
[0];
308 ucontrol
->value
.integer
.value
[1] = spdif
->multi_freqs
[1];
309 ucontrol
->value
.integer
.value
[2] = spdif
->multi_freqs
[2];
310 ucontrol
->value
.integer
.value
[3] = spdif
->multi_freqs
[3];
312 ucontrol
->value
.integer
.value
[0] = 0;
313 ucontrol
->value
.integer
.value
[1] = 0;
314 ucontrol
->value
.integer
.value
[2] = 0;
315 ucontrol
->value
.integer
.value
[3] = 0;
317 spin_unlock_irqrestore(&spdif
->lock
, flags
);
322 static int img_spdif_in_set_multi_freq(struct snd_kcontrol
*kcontrol
,
323 struct snd_ctl_elem_value
*ucontrol
)
325 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
326 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
327 unsigned int multi_freqs
[IMG_SPDIF_IN_NUM_ACLKGEN
];
331 if ((ucontrol
->value
.integer
.value
[0] == 0) &&
332 (ucontrol
->value
.integer
.value
[1] == 0) &&
333 (ucontrol
->value
.integer
.value
[2] == 0) &&
334 (ucontrol
->value
.integer
.value
[3] == 0)) {
337 multi_freqs
[0] = ucontrol
->value
.integer
.value
[0];
338 multi_freqs
[1] = ucontrol
->value
.integer
.value
[1];
339 multi_freqs
[2] = ucontrol
->value
.integer
.value
[2];
340 multi_freqs
[3] = ucontrol
->value
.integer
.value
[3];
345 return img_spdif_in_do_clkgen_multi(spdif
, multi_freqs
);
347 spin_lock_irqsave(&spdif
->lock
, flags
);
350 spin_unlock_irqrestore(&spdif
->lock
, flags
);
354 spdif
->multi_freq
= false;
356 spin_unlock_irqrestore(&spdif
->lock
, flags
);
361 static int img_spdif_in_info_lock_freq(struct snd_kcontrol
*kcontrol
,
362 struct snd_ctl_elem_info
*uinfo
)
364 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
366 uinfo
->value
.integer
.min
= 0;
367 uinfo
->value
.integer
.max
= LONG_MAX
;
372 static int img_spdif_in_get_lock_freq(struct snd_kcontrol
*kcontrol
,
373 struct snd_ctl_elem_value
*uc
)
375 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
376 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
381 spin_lock_irqsave(&spdif
->lock
, flags
);
383 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_STATUS
);
384 if (reg
& IMG_SPDIF_IN_STATUS_LOCK_MASK
) {
385 if (spdif
->multi_freq
) {
386 i
= ((reg
& IMG_SPDIF_IN_STATUS_SAM_MASK
) >>
387 IMG_SPDIF_IN_STATUS_SAM_SHIFT
) - 1;
388 uc
->value
.integer
.value
[0] = spdif
->multi_freqs
[i
];
390 uc
->value
.integer
.value
[0] = spdif
->single_freq
;
393 uc
->value
.integer
.value
[0] = 0;
396 spin_unlock_irqrestore(&spdif
->lock
, flags
);
401 static int img_spdif_in_info_trk(struct snd_kcontrol
*kcontrol
,
402 struct snd_ctl_elem_info
*uinfo
)
404 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
406 uinfo
->value
.integer
.min
= 0;
407 uinfo
->value
.integer
.max
= 255;
412 static int img_spdif_in_get_trk(struct snd_kcontrol
*kcontrol
,
413 struct snd_ctl_elem_value
*ucontrol
)
415 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
416 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
418 ucontrol
->value
.integer
.value
[0] = spdif
->trk
;
423 static int img_spdif_in_set_trk(struct snd_kcontrol
*kcontrol
,
424 struct snd_ctl_elem_value
*ucontrol
)
426 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
427 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
432 spin_lock_irqsave(&spdif
->lock
, flags
);
435 spin_unlock_irqrestore(&spdif
->lock
, flags
);
439 spdif
->trk
= ucontrol
->value
.integer
.value
[0];
441 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
442 reg
&= ~IMG_SPDIF_IN_CTL_TRK_MASK
;
443 reg
|= spdif
->trk
<< IMG_SPDIF_IN_CTL_TRK_SHIFT
;
444 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
446 for (i
= 0; i
< IMG_SPDIF_IN_NUM_ACLKGEN
; i
++) {
447 spdif
->aclkgen_regs
[i
] = (spdif
->aclkgen_regs
[i
] &
448 ~IMG_SPDIF_IN_ACLKGEN_TRK_MASK
) |
449 (spdif
->trk
<< IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT
);
451 img_spdif_in_aclkgen_writel(spdif
, i
);
454 spin_unlock_irqrestore(&spdif
->lock
, flags
);
459 static int img_spdif_in_info_lock(struct snd_kcontrol
*kcontrol
,
460 struct snd_ctl_elem_info
*uinfo
)
462 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
464 uinfo
->value
.integer
.min
= -128;
465 uinfo
->value
.integer
.max
= 127;
470 static int img_spdif_in_get_lock_acquire(struct snd_kcontrol
*kcontrol
,
471 struct snd_ctl_elem_value
*ucontrol
)
473 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
474 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
476 ucontrol
->value
.integer
.value
[0] = spdif
->lock_acquire
;
481 static int img_spdif_in_set_lock_acquire(struct snd_kcontrol
*kcontrol
,
482 struct snd_ctl_elem_value
*ucontrol
)
484 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
485 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
489 spin_lock_irqsave(&spdif
->lock
, flags
);
492 spin_unlock_irqrestore(&spdif
->lock
, flags
);
496 spdif
->lock_acquire
= ucontrol
->value
.integer
.value
[0];
498 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
499 reg
&= ~IMG_SPDIF_IN_CTL_LOCKHI_MASK
;
500 reg
|= (spdif
->lock_acquire
<< IMG_SPDIF_IN_CTL_LOCKHI_SHIFT
) &
501 IMG_SPDIF_IN_CTL_LOCKHI_MASK
;
502 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
504 spin_unlock_irqrestore(&spdif
->lock
, flags
);
509 static int img_spdif_in_get_lock_release(struct snd_kcontrol
*kcontrol
,
510 struct snd_ctl_elem_value
*ucontrol
)
512 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
513 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
515 ucontrol
->value
.integer
.value
[0] = spdif
->lock_release
;
520 static int img_spdif_in_set_lock_release(struct snd_kcontrol
*kcontrol
,
521 struct snd_ctl_elem_value
*ucontrol
)
523 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
524 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
528 spin_lock_irqsave(&spdif
->lock
, flags
);
531 spin_unlock_irqrestore(&spdif
->lock
, flags
);
535 spdif
->lock_release
= ucontrol
->value
.integer
.value
[0];
537 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
538 reg
&= ~IMG_SPDIF_IN_CTL_LOCKLO_MASK
;
539 reg
|= (spdif
->lock_release
<< IMG_SPDIF_IN_CTL_LOCKLO_SHIFT
) &
540 IMG_SPDIF_IN_CTL_LOCKLO_MASK
;
541 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
543 spin_unlock_irqrestore(&spdif
->lock
, flags
);
548 static struct snd_kcontrol_new img_spdif_in_controls
[] = {
550 .access
= SNDRV_CTL_ELEM_ACCESS_READ
,
551 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
552 .name
= SNDRV_CTL_NAME_IEC958("", CAPTURE
, MASK
),
553 .info
= img_spdif_in_iec958_info
,
554 .get
= img_spdif_in_get_status_mask
557 .access
= SNDRV_CTL_ELEM_ACCESS_READ
|
558 SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
559 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
560 .name
= SNDRV_CTL_NAME_IEC958("", CAPTURE
, DEFAULT
),
561 .info
= img_spdif_in_iec958_info
,
562 .get
= img_spdif_in_get_status
565 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
566 .name
= "SPDIF In Multi Frequency Acquire",
567 .info
= img_spdif_in_info_multi_freq
,
568 .get
= img_spdif_in_get_multi_freq
,
569 .put
= img_spdif_in_set_multi_freq
572 .access
= SNDRV_CTL_ELEM_ACCESS_READ
|
573 SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
574 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
575 .name
= "SPDIF In Lock Frequency",
576 .info
= img_spdif_in_info_lock_freq
,
577 .get
= img_spdif_in_get_lock_freq
580 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
581 .name
= "SPDIF In Lock TRK",
582 .info
= img_spdif_in_info_trk
,
583 .get
= img_spdif_in_get_trk
,
584 .put
= img_spdif_in_set_trk
587 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
588 .name
= "SPDIF In Lock Acquire Threshold",
589 .info
= img_spdif_in_info_lock
,
590 .get
= img_spdif_in_get_lock_acquire
,
591 .put
= img_spdif_in_set_lock_acquire
594 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
595 .name
= "SPDIF In Lock Release Threshold",
596 .info
= img_spdif_in_info_lock
,
597 .get
= img_spdif_in_get_lock_release
,
598 .put
= img_spdif_in_set_lock_release
602 static int img_spdif_in_trigger(struct snd_pcm_substream
*substream
, int cmd
,
603 struct snd_soc_dai
*dai
)
606 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(dai
);
610 spin_lock_irqsave(&spdif
->lock
, flags
);
613 case SNDRV_PCM_TRIGGER_START
:
614 case SNDRV_PCM_TRIGGER_RESUME
:
615 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
616 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
617 if (spdif
->multi_freq
)
618 reg
&= ~IMG_SPDIF_IN_CTL_SRD_MASK
;
620 reg
|= (1UL << IMG_SPDIF_IN_CTL_SRD_SHIFT
);
621 reg
|= IMG_SPDIF_IN_CTL_SRT_MASK
;
622 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
623 spdif
->active
= true;
625 case SNDRV_PCM_TRIGGER_STOP
:
626 case SNDRV_PCM_TRIGGER_SUSPEND
:
627 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
628 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
629 reg
&= ~IMG_SPDIF_IN_CTL_SRT_MASK
;
630 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
631 spdif
->active
= false;
637 spin_unlock_irqrestore(&spdif
->lock
, flags
);
642 static int img_spdif_in_hw_params(struct snd_pcm_substream
*substream
,
643 struct snd_pcm_hw_params
*params
, struct snd_soc_dai
*dai
)
645 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(dai
);
646 unsigned int rate
, channels
;
647 snd_pcm_format_t format
;
649 rate
= params_rate(params
);
650 channels
= params_channels(params
);
651 format
= params_format(params
);
653 if (format
!= SNDRV_PCM_FORMAT_S32_LE
)
659 return img_spdif_in_do_clkgen_single(spdif
, rate
);
662 static const struct snd_soc_dai_ops img_spdif_in_dai_ops
= {
663 .trigger
= img_spdif_in_trigger
,
664 .hw_params
= img_spdif_in_hw_params
667 static int img_spdif_in_dai_probe(struct snd_soc_dai
*dai
)
669 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(dai
);
671 snd_soc_dai_init_dma_data(dai
, NULL
, &spdif
->dma_data
);
673 snd_soc_add_dai_controls(dai
, img_spdif_in_controls
,
674 ARRAY_SIZE(img_spdif_in_controls
));
679 static struct snd_soc_dai_driver img_spdif_in_dai
= {
680 .probe
= img_spdif_in_dai_probe
,
684 .rates
= SNDRV_PCM_RATE_8000_192000
,
685 .formats
= SNDRV_PCM_FMTBIT_S32_LE
687 .ops
= &img_spdif_in_dai_ops
690 static const struct snd_soc_component_driver img_spdif_in_component
= {
691 .name
= "img-spdif-in"
694 static int img_spdif_in_probe(struct platform_device
*pdev
)
696 struct img_spdif_in
*spdif
;
697 struct resource
*res
;
700 struct reset_control
*rst
;
702 struct device
*dev
= &pdev
->dev
;
704 spdif
= devm_kzalloc(&pdev
->dev
, sizeof(*spdif
), GFP_KERNEL
);
708 platform_set_drvdata(pdev
, spdif
);
710 spdif
->dev
= &pdev
->dev
;
712 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
713 base
= devm_ioremap_resource(&pdev
->dev
, res
);
715 return PTR_ERR(base
);
719 spdif
->clk_sys
= devm_clk_get(dev
, "sys");
720 if (IS_ERR(spdif
->clk_sys
)) {
721 if (PTR_ERR(spdif
->clk_sys
) != -EPROBE_DEFER
)
722 dev_err(dev
, "Failed to acquire clock 'sys'\n");
723 return PTR_ERR(spdif
->clk_sys
);
726 ret
= clk_prepare_enable(spdif
->clk_sys
);
730 rst
= devm_reset_control_get(&pdev
->dev
, "rst");
732 if (PTR_ERR(rst
) == -EPROBE_DEFER
) {
734 goto err_clk_disable
;
736 dev_dbg(dev
, "No top level reset found\n");
737 img_spdif_in_writel(spdif
, IMG_SPDIF_IN_SOFT_RESET_MASK
,
738 IMG_SPDIF_IN_SOFT_RESET
);
739 img_spdif_in_writel(spdif
, 0, IMG_SPDIF_IN_SOFT_RESET
);
741 reset_control_assert(rst
);
742 reset_control_deassert(rst
);
745 spin_lock_init(&spdif
->lock
);
747 spdif
->dma_data
.addr
= res
->start
+ IMG_SPDIF_IN_RX_FIFO_OFFSET
;
748 spdif
->dma_data
.addr_width
= 4;
749 spdif
->dma_data
.maxburst
= 4;
751 spdif
->lock_acquire
= 4;
752 spdif
->lock_release
= -128;
754 reg
= (spdif
->lock_acquire
<< IMG_SPDIF_IN_CTL_LOCKHI_SHIFT
) &
755 IMG_SPDIF_IN_CTL_LOCKHI_MASK
;
756 reg
|= (spdif
->lock_release
<< IMG_SPDIF_IN_CTL_LOCKLO_SHIFT
) &
757 IMG_SPDIF_IN_CTL_LOCKLO_MASK
;
758 reg
|= (spdif
->trk
<< IMG_SPDIF_IN_CTL_TRK_SHIFT
) &
759 IMG_SPDIF_IN_CTL_TRK_MASK
;
760 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
762 ret
= devm_snd_soc_register_component(&pdev
->dev
,
763 &img_spdif_in_component
, &img_spdif_in_dai
, 1);
765 goto err_clk_disable
;
767 ret
= devm_snd_dmaengine_pcm_register(&pdev
->dev
, NULL
, 0);
769 goto err_clk_disable
;
774 clk_disable_unprepare(spdif
->clk_sys
);
779 static int img_spdif_in_dev_remove(struct platform_device
*pdev
)
781 struct img_spdif_in
*spdif
= platform_get_drvdata(pdev
);
783 clk_disable_unprepare(spdif
->clk_sys
);
788 static const struct of_device_id img_spdif_in_of_match
[] = {
789 { .compatible
= "img,spdif-in" },
792 MODULE_DEVICE_TABLE(of
, img_spdif_in_of_match
);
794 static struct platform_driver img_spdif_in_driver
= {
796 .name
= "img-spdif-in",
797 .of_match_table
= img_spdif_in_of_match
799 .probe
= img_spdif_in_probe
,
800 .remove
= img_spdif_in_dev_remove
802 module_platform_driver(img_spdif_in_driver
);
804 MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
805 MODULE_DESCRIPTION("IMG SPDIF Input driver");
806 MODULE_LICENSE("GPL v2");