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/pm_runtime.h>
20 #include <linux/reset.h>
22 #include <sound/core.h>
23 #include <sound/dmaengine_pcm.h>
24 #include <sound/initval.h>
25 #include <sound/pcm.h>
26 #include <sound/pcm_params.h>
27 #include <sound/soc.h>
29 #define IMG_SPDIF_IN_RX_FIFO_OFFSET 0
31 #define IMG_SPDIF_IN_CTL 0x4
32 #define IMG_SPDIF_IN_CTL_LOCKLO_MASK 0xff
33 #define IMG_SPDIF_IN_CTL_LOCKLO_SHIFT 0
34 #define IMG_SPDIF_IN_CTL_LOCKHI_MASK 0xff00
35 #define IMG_SPDIF_IN_CTL_LOCKHI_SHIFT 8
36 #define IMG_SPDIF_IN_CTL_TRK_MASK 0xff0000
37 #define IMG_SPDIF_IN_CTL_TRK_SHIFT 16
38 #define IMG_SPDIF_IN_CTL_SRD_MASK 0x70000000
39 #define IMG_SPDIF_IN_CTL_SRD_SHIFT 28
40 #define IMG_SPDIF_IN_CTL_SRT_MASK BIT(31)
42 #define IMG_SPDIF_IN_STATUS 0x8
43 #define IMG_SPDIF_IN_STATUS_SAM_MASK 0x7000
44 #define IMG_SPDIF_IN_STATUS_SAM_SHIFT 12
45 #define IMG_SPDIF_IN_STATUS_LOCK_MASK BIT(15)
46 #define IMG_SPDIF_IN_STATUS_LOCK_SHIFT 15
48 #define IMG_SPDIF_IN_CLKGEN 0x1c
49 #define IMG_SPDIF_IN_CLKGEN_NOM_MASK 0x3ff
50 #define IMG_SPDIF_IN_CLKGEN_NOM_SHIFT 0
51 #define IMG_SPDIF_IN_CLKGEN_HLD_MASK 0x3ff0000
52 #define IMG_SPDIF_IN_CLKGEN_HLD_SHIFT 16
54 #define IMG_SPDIF_IN_CSL 0x20
56 #define IMG_SPDIF_IN_CSH 0x24
57 #define IMG_SPDIF_IN_CSH_MASK 0xff
58 #define IMG_SPDIF_IN_CSH_SHIFT 0
60 #define IMG_SPDIF_IN_SOFT_RESET 0x28
61 #define IMG_SPDIF_IN_SOFT_RESET_MASK BIT(0)
63 #define IMG_SPDIF_IN_ACLKGEN_START 0x2c
64 #define IMG_SPDIF_IN_ACLKGEN_NOM_MASK 0x3ff
65 #define IMG_SPDIF_IN_ACLKGEN_NOM_SHIFT 0
66 #define IMG_SPDIF_IN_ACLKGEN_HLD_MASK 0xffc00
67 #define IMG_SPDIF_IN_ACLKGEN_HLD_SHIFT 10
68 #define IMG_SPDIF_IN_ACLKGEN_TRK_MASK 0xff00000
69 #define IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT 20
71 #define IMG_SPDIF_IN_NUM_ACLKGEN 4
77 struct snd_dmaengine_dai_dma_data dma_data
;
83 unsigned int single_freq
;
84 unsigned int multi_freqs
[IMG_SPDIF_IN_NUM_ACLKGEN
];
89 /* Write-only registers */
90 unsigned int aclkgen_regs
[IMG_SPDIF_IN_NUM_ACLKGEN
];
93 static int img_spdif_in_runtime_suspend(struct device
*dev
)
95 struct img_spdif_in
*spdif
= dev_get_drvdata(dev
);
97 clk_disable_unprepare(spdif
->clk_sys
);
102 static int img_spdif_in_runtime_resume(struct device
*dev
)
104 struct img_spdif_in
*spdif
= dev_get_drvdata(dev
);
107 ret
= clk_prepare_enable(spdif
->clk_sys
);
109 dev_err(dev
, "Unable to enable sys clock\n");
116 static inline void img_spdif_in_writel(struct img_spdif_in
*spdif
,
119 writel(val
, spdif
->base
+ reg
);
122 static inline u32
img_spdif_in_readl(struct img_spdif_in
*spdif
, u32 reg
)
124 return readl(spdif
->base
+ reg
);
127 static inline void img_spdif_in_aclkgen_writel(struct img_spdif_in
*spdif
,
130 img_spdif_in_writel(spdif
, spdif
->aclkgen_regs
[index
],
131 IMG_SPDIF_IN_ACLKGEN_START
+ (index
* 0x4));
134 static int img_spdif_in_check_max_rate(struct img_spdif_in
*spdif
,
135 unsigned int sample_rate
, unsigned long *actual_freq
)
137 unsigned long min_freq
, freq_t
;
139 /* Clock rate must be at least 24x the bit rate */
140 min_freq
= sample_rate
* 2 * 32 * 24;
142 freq_t
= clk_get_rate(spdif
->clk_sys
);
144 if (freq_t
< min_freq
)
147 *actual_freq
= freq_t
;
152 static int img_spdif_in_do_clkgen_calc(unsigned int rate
, unsigned int *pnom
,
153 unsigned int *phld
, unsigned long clk_rate
)
155 unsigned int ori
, nom
, hld
;
158 * Calculate oversampling ratio, nominal phase increment and hold
159 * increment for the given rate / frequency
165 ori
= clk_rate
/ (rate
* 64);
170 nom
= (4096 / ori
) + 1;
172 hld
= 4096 - (--nom
* (ori
- 1));
181 static int img_spdif_in_do_clkgen_single(struct img_spdif_in
*spdif
,
184 unsigned int nom
, hld
;
185 unsigned long flags
, clk_rate
;
189 ret
= img_spdif_in_check_max_rate(spdif
, rate
, &clk_rate
);
193 ret
= img_spdif_in_do_clkgen_calc(rate
, &nom
, &hld
, clk_rate
);
197 reg
= (nom
<< IMG_SPDIF_IN_CLKGEN_NOM_SHIFT
) &
198 IMG_SPDIF_IN_CLKGEN_NOM_MASK
;
199 reg
|= (hld
<< IMG_SPDIF_IN_CLKGEN_HLD_SHIFT
) &
200 IMG_SPDIF_IN_CLKGEN_HLD_MASK
;
202 spin_lock_irqsave(&spdif
->lock
, flags
);
205 spin_unlock_irqrestore(&spdif
->lock
, flags
);
209 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CLKGEN
);
211 spdif
->single_freq
= rate
;
213 spin_unlock_irqrestore(&spdif
->lock
, flags
);
218 static int img_spdif_in_do_clkgen_multi(struct img_spdif_in
*spdif
,
219 unsigned int multi_freqs
[])
221 unsigned int nom
, hld
, rate
, max_rate
= 0;
222 unsigned long flags
, clk_rate
;
224 u32 reg
, trk_reg
, temp_regs
[IMG_SPDIF_IN_NUM_ACLKGEN
];
226 for (i
= 0; i
< IMG_SPDIF_IN_NUM_ACLKGEN
; i
++)
227 if (multi_freqs
[i
] > max_rate
)
228 max_rate
= multi_freqs
[i
];
230 ret
= img_spdif_in_check_max_rate(spdif
, max_rate
, &clk_rate
);
234 for (i
= 0; i
< IMG_SPDIF_IN_NUM_ACLKGEN
; i
++) {
235 rate
= multi_freqs
[i
];
237 ret
= img_spdif_in_do_clkgen_calc(rate
, &nom
, &hld
, clk_rate
);
241 reg
= (nom
<< IMG_SPDIF_IN_ACLKGEN_NOM_SHIFT
) &
242 IMG_SPDIF_IN_ACLKGEN_NOM_MASK
;
243 reg
|= (hld
<< IMG_SPDIF_IN_ACLKGEN_HLD_SHIFT
) &
244 IMG_SPDIF_IN_ACLKGEN_HLD_MASK
;
248 spin_lock_irqsave(&spdif
->lock
, flags
);
251 spin_unlock_irqrestore(&spdif
->lock
, flags
);
255 trk_reg
= spdif
->trk
<< IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT
;
257 for (i
= 0; i
< IMG_SPDIF_IN_NUM_ACLKGEN
; i
++) {
258 spdif
->aclkgen_regs
[i
] = temp_regs
[i
] | trk_reg
;
259 img_spdif_in_aclkgen_writel(spdif
, i
);
262 spdif
->multi_freq
= true;
263 spdif
->multi_freqs
[0] = multi_freqs
[0];
264 spdif
->multi_freqs
[1] = multi_freqs
[1];
265 spdif
->multi_freqs
[2] = multi_freqs
[2];
266 spdif
->multi_freqs
[3] = multi_freqs
[3];
268 spin_unlock_irqrestore(&spdif
->lock
, flags
);
273 static int img_spdif_in_iec958_info(struct snd_kcontrol
*kcontrol
,
274 struct snd_ctl_elem_info
*uinfo
)
276 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_IEC958
;
282 static int img_spdif_in_get_status_mask(struct snd_kcontrol
*kcontrol
,
283 struct snd_ctl_elem_value
*ucontrol
)
285 ucontrol
->value
.iec958
.status
[0] = 0xff;
286 ucontrol
->value
.iec958
.status
[1] = 0xff;
287 ucontrol
->value
.iec958
.status
[2] = 0xff;
288 ucontrol
->value
.iec958
.status
[3] = 0xff;
289 ucontrol
->value
.iec958
.status
[4] = 0xff;
294 static int img_spdif_in_get_status(struct snd_kcontrol
*kcontrol
,
295 struct snd_ctl_elem_value
*ucontrol
)
297 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
298 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
301 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CSL
);
302 ucontrol
->value
.iec958
.status
[0] = reg
& 0xff;
303 ucontrol
->value
.iec958
.status
[1] = (reg
>> 8) & 0xff;
304 ucontrol
->value
.iec958
.status
[2] = (reg
>> 16) & 0xff;
305 ucontrol
->value
.iec958
.status
[3] = (reg
>> 24) & 0xff;
306 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CSH
);
307 ucontrol
->value
.iec958
.status
[4] = (reg
& IMG_SPDIF_IN_CSH_MASK
)
308 >> IMG_SPDIF_IN_CSH_SHIFT
;
313 static int img_spdif_in_info_multi_freq(struct snd_kcontrol
*kcontrol
,
314 struct snd_ctl_elem_info
*uinfo
)
316 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
317 uinfo
->count
= IMG_SPDIF_IN_NUM_ACLKGEN
;
318 uinfo
->value
.integer
.min
= 0;
319 uinfo
->value
.integer
.max
= LONG_MAX
;
324 static int img_spdif_in_get_multi_freq(struct snd_kcontrol
*kcontrol
,
325 struct snd_ctl_elem_value
*ucontrol
)
327 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
328 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
331 spin_lock_irqsave(&spdif
->lock
, flags
);
332 if (spdif
->multi_freq
) {
333 ucontrol
->value
.integer
.value
[0] = spdif
->multi_freqs
[0];
334 ucontrol
->value
.integer
.value
[1] = spdif
->multi_freqs
[1];
335 ucontrol
->value
.integer
.value
[2] = spdif
->multi_freqs
[2];
336 ucontrol
->value
.integer
.value
[3] = spdif
->multi_freqs
[3];
338 ucontrol
->value
.integer
.value
[0] = 0;
339 ucontrol
->value
.integer
.value
[1] = 0;
340 ucontrol
->value
.integer
.value
[2] = 0;
341 ucontrol
->value
.integer
.value
[3] = 0;
343 spin_unlock_irqrestore(&spdif
->lock
, flags
);
348 static int img_spdif_in_set_multi_freq(struct snd_kcontrol
*kcontrol
,
349 struct snd_ctl_elem_value
*ucontrol
)
351 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
352 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
353 unsigned int multi_freqs
[IMG_SPDIF_IN_NUM_ACLKGEN
];
357 if ((ucontrol
->value
.integer
.value
[0] == 0) &&
358 (ucontrol
->value
.integer
.value
[1] == 0) &&
359 (ucontrol
->value
.integer
.value
[2] == 0) &&
360 (ucontrol
->value
.integer
.value
[3] == 0)) {
363 multi_freqs
[0] = ucontrol
->value
.integer
.value
[0];
364 multi_freqs
[1] = ucontrol
->value
.integer
.value
[1];
365 multi_freqs
[2] = ucontrol
->value
.integer
.value
[2];
366 multi_freqs
[3] = ucontrol
->value
.integer
.value
[3];
371 return img_spdif_in_do_clkgen_multi(spdif
, multi_freqs
);
373 spin_lock_irqsave(&spdif
->lock
, flags
);
376 spin_unlock_irqrestore(&spdif
->lock
, flags
);
380 spdif
->multi_freq
= false;
382 spin_unlock_irqrestore(&spdif
->lock
, flags
);
387 static int img_spdif_in_info_lock_freq(struct snd_kcontrol
*kcontrol
,
388 struct snd_ctl_elem_info
*uinfo
)
390 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
392 uinfo
->value
.integer
.min
= 0;
393 uinfo
->value
.integer
.max
= LONG_MAX
;
398 static int img_spdif_in_get_lock_freq(struct snd_kcontrol
*kcontrol
,
399 struct snd_ctl_elem_value
*uc
)
401 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
402 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
407 spin_lock_irqsave(&spdif
->lock
, flags
);
409 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_STATUS
);
410 if (reg
& IMG_SPDIF_IN_STATUS_LOCK_MASK
) {
411 if (spdif
->multi_freq
) {
412 i
= ((reg
& IMG_SPDIF_IN_STATUS_SAM_MASK
) >>
413 IMG_SPDIF_IN_STATUS_SAM_SHIFT
) - 1;
414 uc
->value
.integer
.value
[0] = spdif
->multi_freqs
[i
];
416 uc
->value
.integer
.value
[0] = spdif
->single_freq
;
419 uc
->value
.integer
.value
[0] = 0;
422 spin_unlock_irqrestore(&spdif
->lock
, flags
);
427 static int img_spdif_in_info_trk(struct snd_kcontrol
*kcontrol
,
428 struct snd_ctl_elem_info
*uinfo
)
430 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
432 uinfo
->value
.integer
.min
= 0;
433 uinfo
->value
.integer
.max
= 255;
438 static int img_spdif_in_get_trk(struct snd_kcontrol
*kcontrol
,
439 struct snd_ctl_elem_value
*ucontrol
)
441 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
442 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
444 ucontrol
->value
.integer
.value
[0] = spdif
->trk
;
449 static int img_spdif_in_set_trk(struct snd_kcontrol
*kcontrol
,
450 struct snd_ctl_elem_value
*ucontrol
)
452 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
453 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
458 spin_lock_irqsave(&spdif
->lock
, flags
);
461 spin_unlock_irqrestore(&spdif
->lock
, flags
);
465 spdif
->trk
= ucontrol
->value
.integer
.value
[0];
467 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
468 reg
&= ~IMG_SPDIF_IN_CTL_TRK_MASK
;
469 reg
|= spdif
->trk
<< IMG_SPDIF_IN_CTL_TRK_SHIFT
;
470 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
472 for (i
= 0; i
< IMG_SPDIF_IN_NUM_ACLKGEN
; i
++) {
473 spdif
->aclkgen_regs
[i
] = (spdif
->aclkgen_regs
[i
] &
474 ~IMG_SPDIF_IN_ACLKGEN_TRK_MASK
) |
475 (spdif
->trk
<< IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT
);
477 img_spdif_in_aclkgen_writel(spdif
, i
);
480 spin_unlock_irqrestore(&spdif
->lock
, flags
);
485 static int img_spdif_in_info_lock(struct snd_kcontrol
*kcontrol
,
486 struct snd_ctl_elem_info
*uinfo
)
488 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
490 uinfo
->value
.integer
.min
= -128;
491 uinfo
->value
.integer
.max
= 127;
496 static int img_spdif_in_get_lock_acquire(struct snd_kcontrol
*kcontrol
,
497 struct snd_ctl_elem_value
*ucontrol
)
499 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
500 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
502 ucontrol
->value
.integer
.value
[0] = spdif
->lock_acquire
;
507 static int img_spdif_in_set_lock_acquire(struct snd_kcontrol
*kcontrol
,
508 struct snd_ctl_elem_value
*ucontrol
)
510 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
511 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
515 spin_lock_irqsave(&spdif
->lock
, flags
);
518 spin_unlock_irqrestore(&spdif
->lock
, flags
);
522 spdif
->lock_acquire
= ucontrol
->value
.integer
.value
[0];
524 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
525 reg
&= ~IMG_SPDIF_IN_CTL_LOCKHI_MASK
;
526 reg
|= (spdif
->lock_acquire
<< IMG_SPDIF_IN_CTL_LOCKHI_SHIFT
) &
527 IMG_SPDIF_IN_CTL_LOCKHI_MASK
;
528 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
530 spin_unlock_irqrestore(&spdif
->lock
, flags
);
535 static int img_spdif_in_get_lock_release(struct snd_kcontrol
*kcontrol
,
536 struct snd_ctl_elem_value
*ucontrol
)
538 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
539 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
541 ucontrol
->value
.integer
.value
[0] = spdif
->lock_release
;
546 static int img_spdif_in_set_lock_release(struct snd_kcontrol
*kcontrol
,
547 struct snd_ctl_elem_value
*ucontrol
)
549 struct snd_soc_dai
*cpu_dai
= snd_kcontrol_chip(kcontrol
);
550 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(cpu_dai
);
554 spin_lock_irqsave(&spdif
->lock
, flags
);
557 spin_unlock_irqrestore(&spdif
->lock
, flags
);
561 spdif
->lock_release
= ucontrol
->value
.integer
.value
[0];
563 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
564 reg
&= ~IMG_SPDIF_IN_CTL_LOCKLO_MASK
;
565 reg
|= (spdif
->lock_release
<< IMG_SPDIF_IN_CTL_LOCKLO_SHIFT
) &
566 IMG_SPDIF_IN_CTL_LOCKLO_MASK
;
567 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
569 spin_unlock_irqrestore(&spdif
->lock
, flags
);
574 static struct snd_kcontrol_new img_spdif_in_controls
[] = {
576 .access
= SNDRV_CTL_ELEM_ACCESS_READ
,
577 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
578 .name
= SNDRV_CTL_NAME_IEC958("", CAPTURE
, MASK
),
579 .info
= img_spdif_in_iec958_info
,
580 .get
= img_spdif_in_get_status_mask
583 .access
= SNDRV_CTL_ELEM_ACCESS_READ
|
584 SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
585 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
586 .name
= SNDRV_CTL_NAME_IEC958("", CAPTURE
, DEFAULT
),
587 .info
= img_spdif_in_iec958_info
,
588 .get
= img_spdif_in_get_status
591 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
592 .name
= "SPDIF In Multi Frequency Acquire",
593 .info
= img_spdif_in_info_multi_freq
,
594 .get
= img_spdif_in_get_multi_freq
,
595 .put
= img_spdif_in_set_multi_freq
598 .access
= SNDRV_CTL_ELEM_ACCESS_READ
|
599 SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
600 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
601 .name
= "SPDIF In Lock Frequency",
602 .info
= img_spdif_in_info_lock_freq
,
603 .get
= img_spdif_in_get_lock_freq
606 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
607 .name
= "SPDIF In Lock TRK",
608 .info
= img_spdif_in_info_trk
,
609 .get
= img_spdif_in_get_trk
,
610 .put
= img_spdif_in_set_trk
613 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
614 .name
= "SPDIF In Lock Acquire Threshold",
615 .info
= img_spdif_in_info_lock
,
616 .get
= img_spdif_in_get_lock_acquire
,
617 .put
= img_spdif_in_set_lock_acquire
620 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
621 .name
= "SPDIF In Lock Release Threshold",
622 .info
= img_spdif_in_info_lock
,
623 .get
= img_spdif_in_get_lock_release
,
624 .put
= img_spdif_in_set_lock_release
628 static int img_spdif_in_trigger(struct snd_pcm_substream
*substream
, int cmd
,
629 struct snd_soc_dai
*dai
)
632 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(dai
);
636 spin_lock_irqsave(&spdif
->lock
, flags
);
639 case SNDRV_PCM_TRIGGER_START
:
640 case SNDRV_PCM_TRIGGER_RESUME
:
641 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
642 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
643 if (spdif
->multi_freq
)
644 reg
&= ~IMG_SPDIF_IN_CTL_SRD_MASK
;
646 reg
|= (1UL << IMG_SPDIF_IN_CTL_SRD_SHIFT
);
647 reg
|= IMG_SPDIF_IN_CTL_SRT_MASK
;
648 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
649 spdif
->active
= true;
651 case SNDRV_PCM_TRIGGER_STOP
:
652 case SNDRV_PCM_TRIGGER_SUSPEND
:
653 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
654 reg
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
655 reg
&= ~IMG_SPDIF_IN_CTL_SRT_MASK
;
656 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
657 spdif
->active
= false;
663 spin_unlock_irqrestore(&spdif
->lock
, flags
);
668 static int img_spdif_in_hw_params(struct snd_pcm_substream
*substream
,
669 struct snd_pcm_hw_params
*params
, struct snd_soc_dai
*dai
)
671 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(dai
);
672 unsigned int rate
, channels
;
673 snd_pcm_format_t format
;
675 rate
= params_rate(params
);
676 channels
= params_channels(params
);
677 format
= params_format(params
);
679 if (format
!= SNDRV_PCM_FORMAT_S32_LE
)
685 return img_spdif_in_do_clkgen_single(spdif
, rate
);
688 static const struct snd_soc_dai_ops img_spdif_in_dai_ops
= {
689 .trigger
= img_spdif_in_trigger
,
690 .hw_params
= img_spdif_in_hw_params
693 static int img_spdif_in_dai_probe(struct snd_soc_dai
*dai
)
695 struct img_spdif_in
*spdif
= snd_soc_dai_get_drvdata(dai
);
697 snd_soc_dai_init_dma_data(dai
, NULL
, &spdif
->dma_data
);
699 snd_soc_add_dai_controls(dai
, img_spdif_in_controls
,
700 ARRAY_SIZE(img_spdif_in_controls
));
705 static struct snd_soc_dai_driver img_spdif_in_dai
= {
706 .probe
= img_spdif_in_dai_probe
,
710 .rates
= SNDRV_PCM_RATE_8000_192000
,
711 .formats
= SNDRV_PCM_FMTBIT_S32_LE
713 .ops
= &img_spdif_in_dai_ops
716 static const struct snd_soc_component_driver img_spdif_in_component
= {
717 .name
= "img-spdif-in"
720 static int img_spdif_in_probe(struct platform_device
*pdev
)
722 struct img_spdif_in
*spdif
;
723 struct resource
*res
;
726 struct reset_control
*rst
;
728 struct device
*dev
= &pdev
->dev
;
730 spdif
= devm_kzalloc(&pdev
->dev
, sizeof(*spdif
), GFP_KERNEL
);
734 platform_set_drvdata(pdev
, spdif
);
736 spdif
->dev
= &pdev
->dev
;
738 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
739 base
= devm_ioremap_resource(&pdev
->dev
, res
);
741 return PTR_ERR(base
);
745 spdif
->clk_sys
= devm_clk_get(dev
, "sys");
746 if (IS_ERR(spdif
->clk_sys
)) {
747 if (PTR_ERR(spdif
->clk_sys
) != -EPROBE_DEFER
)
748 dev_err(dev
, "Failed to acquire clock 'sys'\n");
749 return PTR_ERR(spdif
->clk_sys
);
752 pm_runtime_enable(&pdev
->dev
);
753 if (!pm_runtime_enabled(&pdev
->dev
)) {
754 ret
= img_spdif_in_runtime_resume(&pdev
->dev
);
758 ret
= pm_runtime_get_sync(&pdev
->dev
);
762 rst
= devm_reset_control_get_exclusive(&pdev
->dev
, "rst");
764 if (PTR_ERR(rst
) == -EPROBE_DEFER
) {
768 dev_dbg(dev
, "No top level reset found\n");
769 img_spdif_in_writel(spdif
, IMG_SPDIF_IN_SOFT_RESET_MASK
,
770 IMG_SPDIF_IN_SOFT_RESET
);
771 img_spdif_in_writel(spdif
, 0, IMG_SPDIF_IN_SOFT_RESET
);
773 reset_control_assert(rst
);
774 reset_control_deassert(rst
);
777 spin_lock_init(&spdif
->lock
);
779 spdif
->dma_data
.addr
= res
->start
+ IMG_SPDIF_IN_RX_FIFO_OFFSET
;
780 spdif
->dma_data
.addr_width
= 4;
781 spdif
->dma_data
.maxburst
= 4;
783 spdif
->lock_acquire
= 4;
784 spdif
->lock_release
= -128;
786 reg
= (spdif
->lock_acquire
<< IMG_SPDIF_IN_CTL_LOCKHI_SHIFT
) &
787 IMG_SPDIF_IN_CTL_LOCKHI_MASK
;
788 reg
|= (spdif
->lock_release
<< IMG_SPDIF_IN_CTL_LOCKLO_SHIFT
) &
789 IMG_SPDIF_IN_CTL_LOCKLO_MASK
;
790 reg
|= (spdif
->trk
<< IMG_SPDIF_IN_CTL_TRK_SHIFT
) &
791 IMG_SPDIF_IN_CTL_TRK_MASK
;
792 img_spdif_in_writel(spdif
, reg
, IMG_SPDIF_IN_CTL
);
794 pm_runtime_put(&pdev
->dev
);
796 ret
= devm_snd_soc_register_component(&pdev
->dev
,
797 &img_spdif_in_component
, &img_spdif_in_dai
, 1);
801 ret
= devm_snd_dmaengine_pcm_register(&pdev
->dev
, NULL
, 0);
808 pm_runtime_put(&pdev
->dev
);
810 if (!pm_runtime_enabled(&pdev
->dev
))
811 img_spdif_in_runtime_suspend(&pdev
->dev
);
813 pm_runtime_disable(&pdev
->dev
);
818 static int img_spdif_in_dev_remove(struct platform_device
*pdev
)
820 pm_runtime_disable(&pdev
->dev
);
821 if (!pm_runtime_status_suspended(&pdev
->dev
))
822 img_spdif_in_runtime_suspend(&pdev
->dev
);
827 #ifdef CONFIG_PM_SLEEP
828 static int img_spdif_in_suspend(struct device
*dev
)
830 struct img_spdif_in
*spdif
= dev_get_drvdata(dev
);
833 if (pm_runtime_status_suspended(dev
)) {
834 ret
= img_spdif_in_runtime_resume(dev
);
839 spdif
->suspend_clkgen
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CLKGEN
);
840 spdif
->suspend_ctl
= img_spdif_in_readl(spdif
, IMG_SPDIF_IN_CTL
);
842 img_spdif_in_runtime_suspend(dev
);
847 static int img_spdif_in_resume(struct device
*dev
)
849 struct img_spdif_in
*spdif
= dev_get_drvdata(dev
);
852 ret
= img_spdif_in_runtime_resume(dev
);
856 for (i
= 0; i
< IMG_SPDIF_IN_NUM_ACLKGEN
; i
++)
857 img_spdif_in_aclkgen_writel(spdif
, i
);
859 img_spdif_in_writel(spdif
, spdif
->suspend_clkgen
, IMG_SPDIF_IN_CLKGEN
);
860 img_spdif_in_writel(spdif
, spdif
->suspend_ctl
, IMG_SPDIF_IN_CTL
);
862 if (pm_runtime_status_suspended(dev
))
863 img_spdif_in_runtime_suspend(dev
);
869 static const struct of_device_id img_spdif_in_of_match
[] = {
870 { .compatible
= "img,spdif-in" },
873 MODULE_DEVICE_TABLE(of
, img_spdif_in_of_match
);
875 static const struct dev_pm_ops img_spdif_in_pm_ops
= {
876 SET_RUNTIME_PM_OPS(img_spdif_in_runtime_suspend
,
877 img_spdif_in_runtime_resume
, NULL
)
878 SET_SYSTEM_SLEEP_PM_OPS(img_spdif_in_suspend
, img_spdif_in_resume
)
881 static struct platform_driver img_spdif_in_driver
= {
883 .name
= "img-spdif-in",
884 .of_match_table
= img_spdif_in_of_match
,
885 .pm
= &img_spdif_in_pm_ops
887 .probe
= img_spdif_in_probe
,
888 .remove
= img_spdif_in_dev_remove
890 module_platform_driver(img_spdif_in_driver
);
892 MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
893 MODULE_DESCRIPTION("IMG SPDIF Input driver");
894 MODULE_LICENSE("GPL v2");