1 // SPDX-License-Identifier: GPL-2.0-only
3 * IMG I2S input controller driver
5 * Copyright (C) 2015 Imagination Technologies Ltd.
7 * Author: Damien Horsley <Damien.Horsley@imgtec.com>
10 #include <linux/clk.h>
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/reset.h>
19 #include <sound/core.h>
20 #include <sound/dmaengine_pcm.h>
21 #include <sound/initval.h>
22 #include <sound/pcm.h>
23 #include <sound/pcm_params.h>
24 #include <sound/soc.h>
26 #define IMG_I2S_IN_RX_FIFO 0x0
28 #define IMG_I2S_IN_CTL 0x4
29 #define IMG_I2S_IN_CTL_ACTIVE_CHAN_MASK 0xfffffffc
30 #define IMG_I2S_IN_CTL_ACTIVE_CH_SHIFT 2
31 #define IMG_I2S_IN_CTL_16PACK_MASK BIT(1)
32 #define IMG_I2S_IN_CTL_ME_MASK BIT(0)
34 #define IMG_I2S_IN_CH_CTL 0x4
35 #define IMG_I2S_IN_CH_CTL_CCDEL_MASK 0x38000
36 #define IMG_I2S_IN_CH_CTL_CCDEL_SHIFT 15
37 #define IMG_I2S_IN_CH_CTL_FEN_MASK BIT(14)
38 #define IMG_I2S_IN_CH_CTL_FMODE_MASK BIT(13)
39 #define IMG_I2S_IN_CH_CTL_16PACK_MASK BIT(12)
40 #define IMG_I2S_IN_CH_CTL_JUST_MASK BIT(10)
41 #define IMG_I2S_IN_CH_CTL_PACKH_MASK BIT(9)
42 #define IMG_I2S_IN_CH_CTL_CLK_TRANS_MASK BIT(8)
43 #define IMG_I2S_IN_CH_CTL_BLKP_MASK BIT(7)
44 #define IMG_I2S_IN_CH_CTL_FIFO_FLUSH_MASK BIT(6)
45 #define IMG_I2S_IN_CH_CTL_LRD_MASK BIT(3)
46 #define IMG_I2S_IN_CH_CTL_FW_MASK BIT(2)
47 #define IMG_I2S_IN_CH_CTL_SW_MASK BIT(1)
48 #define IMG_I2S_IN_CH_CTL_ME_MASK BIT(0)
50 #define IMG_I2S_IN_CH_STRIDE 0x20
55 struct snd_dmaengine_dai_dma_data dma_data
;
57 unsigned int max_i2s_chan
;
58 void __iomem
*channel_base
;
59 unsigned int active_channels
;
60 struct snd_soc_dai_driver dai_driver
;
65 static int img_i2s_in_runtime_suspend(struct device
*dev
)
67 struct img_i2s_in
*i2s
= dev_get_drvdata(dev
);
69 clk_disable_unprepare(i2s
->clk_sys
);
74 static int img_i2s_in_runtime_resume(struct device
*dev
)
76 struct img_i2s_in
*i2s
= dev_get_drvdata(dev
);
79 ret
= clk_prepare_enable(i2s
->clk_sys
);
81 dev_err(dev
, "Unable to enable sys clock\n");
88 static inline void img_i2s_in_writel(struct img_i2s_in
*i2s
, u32 val
, u32 reg
)
90 writel(val
, i2s
->base
+ reg
);
93 static inline u32
img_i2s_in_readl(struct img_i2s_in
*i2s
, u32 reg
)
95 return readl(i2s
->base
+ reg
);
98 static inline void img_i2s_in_ch_writel(struct img_i2s_in
*i2s
, u32 chan
,
101 writel(val
, i2s
->channel_base
+ (chan
* IMG_I2S_IN_CH_STRIDE
) + reg
);
104 static inline u32
img_i2s_in_ch_readl(struct img_i2s_in
*i2s
, u32 chan
,
107 return readl(i2s
->channel_base
+ (chan
* IMG_I2S_IN_CH_STRIDE
) + reg
);
110 static inline void img_i2s_in_ch_disable(struct img_i2s_in
*i2s
, u32 chan
)
114 reg
= img_i2s_in_ch_readl(i2s
, chan
, IMG_I2S_IN_CH_CTL
);
115 reg
&= ~IMG_I2S_IN_CH_CTL_ME_MASK
;
116 img_i2s_in_ch_writel(i2s
, chan
, reg
, IMG_I2S_IN_CH_CTL
);
119 static inline void img_i2s_in_ch_enable(struct img_i2s_in
*i2s
, u32 chan
)
123 reg
= img_i2s_in_ch_readl(i2s
, chan
, IMG_I2S_IN_CH_CTL
);
124 reg
|= IMG_I2S_IN_CH_CTL_ME_MASK
;
125 img_i2s_in_ch_writel(i2s
, chan
, reg
, IMG_I2S_IN_CH_CTL
);
128 static inline void img_i2s_in_disable(struct img_i2s_in
*i2s
)
132 reg
= img_i2s_in_readl(i2s
, IMG_I2S_IN_CTL
);
133 reg
&= ~IMG_I2S_IN_CTL_ME_MASK
;
134 img_i2s_in_writel(i2s
, reg
, IMG_I2S_IN_CTL
);
137 static inline void img_i2s_in_enable(struct img_i2s_in
*i2s
)
141 reg
= img_i2s_in_readl(i2s
, IMG_I2S_IN_CTL
);
142 reg
|= IMG_I2S_IN_CTL_ME_MASK
;
143 img_i2s_in_writel(i2s
, reg
, IMG_I2S_IN_CTL
);
146 static inline void img_i2s_in_flush(struct img_i2s_in
*i2s
)
151 for (i
= 0; i
< i2s
->active_channels
; i
++) {
152 reg
= img_i2s_in_ch_readl(i2s
, i
, IMG_I2S_IN_CH_CTL
);
153 reg
|= IMG_I2S_IN_CH_CTL_FIFO_FLUSH_MASK
;
154 img_i2s_in_ch_writel(i2s
, i
, reg
, IMG_I2S_IN_CH_CTL
);
155 reg
&= ~IMG_I2S_IN_CH_CTL_FIFO_FLUSH_MASK
;
156 img_i2s_in_ch_writel(i2s
, i
, reg
, IMG_I2S_IN_CH_CTL
);
160 static int img_i2s_in_trigger(struct snd_pcm_substream
*substream
, int cmd
,
161 struct snd_soc_dai
*dai
)
163 struct img_i2s_in
*i2s
= snd_soc_dai_get_drvdata(dai
);
166 case SNDRV_PCM_TRIGGER_START
:
167 case SNDRV_PCM_TRIGGER_RESUME
:
168 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
169 img_i2s_in_enable(i2s
);
172 case SNDRV_PCM_TRIGGER_STOP
:
173 case SNDRV_PCM_TRIGGER_SUSPEND
:
174 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
175 img_i2s_in_disable(i2s
);
184 static int img_i2s_in_check_rate(struct img_i2s_in
*i2s
,
185 unsigned int sample_rate
, unsigned int frame_size
,
186 unsigned int *bclk_filter_enable
,
187 unsigned int *bclk_filter_value
)
189 unsigned int bclk_freq
, cur_freq
;
191 bclk_freq
= sample_rate
* frame_size
;
193 cur_freq
= clk_get_rate(i2s
->clk_sys
);
195 if (cur_freq
>= bclk_freq
* 8) {
196 *bclk_filter_enable
= 1;
197 *bclk_filter_value
= 0;
198 } else if (cur_freq
>= bclk_freq
* 7) {
199 *bclk_filter_enable
= 1;
200 *bclk_filter_value
= 1;
201 } else if (cur_freq
>= bclk_freq
* 6) {
202 *bclk_filter_enable
= 0;
203 *bclk_filter_value
= 0;
206 "Sys clock rate %u insufficient for sample rate %u\n",
207 cur_freq
, sample_rate
);
214 static int img_i2s_in_hw_params(struct snd_pcm_substream
*substream
,
215 struct snd_pcm_hw_params
*params
, struct snd_soc_dai
*dai
)
217 struct img_i2s_in
*i2s
= snd_soc_dai_get_drvdata(dai
);
218 unsigned int rate
, channels
, i2s_channels
, frame_size
;
219 unsigned int bclk_filter_enable
, bclk_filter_value
;
221 u32 reg
, control_mask
, chan_control_mask
;
222 u32 control_set
= 0, chan_control_set
= 0;
223 snd_pcm_format_t format
;
225 rate
= params_rate(params
);
226 format
= params_format(params
);
227 channels
= params_channels(params
);
228 i2s_channels
= channels
/ 2;
231 case SNDRV_PCM_FORMAT_S32_LE
:
233 chan_control_set
|= IMG_I2S_IN_CH_CTL_SW_MASK
;
234 chan_control_set
|= IMG_I2S_IN_CH_CTL_FW_MASK
;
235 chan_control_set
|= IMG_I2S_IN_CH_CTL_PACKH_MASK
;
237 case SNDRV_PCM_FORMAT_S24_LE
:
239 chan_control_set
|= IMG_I2S_IN_CH_CTL_SW_MASK
;
240 chan_control_set
|= IMG_I2S_IN_CH_CTL_FW_MASK
;
242 case SNDRV_PCM_FORMAT_S16_LE
:
244 control_set
|= IMG_I2S_IN_CTL_16PACK_MASK
;
245 chan_control_set
|= IMG_I2S_IN_CH_CTL_16PACK_MASK
;
251 if ((channels
< 2) ||
252 (channels
> (i2s
->max_i2s_chan
* 2)) ||
256 control_set
|= ((i2s_channels
- 1) << IMG_I2S_IN_CTL_ACTIVE_CH_SHIFT
);
258 ret
= img_i2s_in_check_rate(i2s
, rate
, frame_size
,
259 &bclk_filter_enable
, &bclk_filter_value
);
263 if (bclk_filter_enable
)
264 chan_control_set
|= IMG_I2S_IN_CH_CTL_FEN_MASK
;
266 if (bclk_filter_value
)
267 chan_control_set
|= IMG_I2S_IN_CH_CTL_FMODE_MASK
;
269 control_mask
= IMG_I2S_IN_CTL_16PACK_MASK
|
270 IMG_I2S_IN_CTL_ACTIVE_CHAN_MASK
;
272 chan_control_mask
= IMG_I2S_IN_CH_CTL_16PACK_MASK
|
273 IMG_I2S_IN_CH_CTL_FEN_MASK
|
274 IMG_I2S_IN_CH_CTL_FMODE_MASK
|
275 IMG_I2S_IN_CH_CTL_SW_MASK
|
276 IMG_I2S_IN_CH_CTL_FW_MASK
|
277 IMG_I2S_IN_CH_CTL_PACKH_MASK
;
279 reg
= img_i2s_in_readl(i2s
, IMG_I2S_IN_CTL
);
280 reg
= (reg
& ~control_mask
) | control_set
;
281 img_i2s_in_writel(i2s
, reg
, IMG_I2S_IN_CTL
);
283 for (i
= 0; i
< i2s
->active_channels
; i
++)
284 img_i2s_in_ch_disable(i2s
, i
);
286 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++) {
287 reg
= img_i2s_in_ch_readl(i2s
, i
, IMG_I2S_IN_CH_CTL
);
288 reg
= (reg
& ~chan_control_mask
) | chan_control_set
;
289 img_i2s_in_ch_writel(i2s
, i
, reg
, IMG_I2S_IN_CH_CTL
);
292 i2s
->active_channels
= i2s_channels
;
294 img_i2s_in_flush(i2s
);
296 for (i
= 0; i
< i2s
->active_channels
; i
++)
297 img_i2s_in_ch_enable(i2s
, i
);
302 static int img_i2s_in_set_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
304 struct img_i2s_in
*i2s
= snd_soc_dai_get_drvdata(dai
);
306 u32 chan_control_mask
, lrd_set
= 0, blkp_set
= 0, chan_control_set
= 0;
309 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
310 case SND_SOC_DAIFMT_NB_NF
:
311 lrd_set
|= IMG_I2S_IN_CH_CTL_LRD_MASK
;
313 case SND_SOC_DAIFMT_NB_IF
:
315 case SND_SOC_DAIFMT_IB_NF
:
316 lrd_set
|= IMG_I2S_IN_CH_CTL_LRD_MASK
;
317 blkp_set
|= IMG_I2S_IN_CH_CTL_BLKP_MASK
;
319 case SND_SOC_DAIFMT_IB_IF
:
320 blkp_set
|= IMG_I2S_IN_CH_CTL_BLKP_MASK
;
326 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
327 case SND_SOC_DAIFMT_I2S
:
328 chan_control_set
|= IMG_I2S_IN_CH_CTL_CLK_TRANS_MASK
;
330 case SND_SOC_DAIFMT_LEFT_J
:
336 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
337 case SND_SOC_DAIFMT_CBM_CFM
:
343 chan_control_mask
= IMG_I2S_IN_CH_CTL_CLK_TRANS_MASK
;
345 ret
= pm_runtime_get_sync(i2s
->dev
);
349 for (i
= 0; i
< i2s
->active_channels
; i
++)
350 img_i2s_in_ch_disable(i2s
, i
);
353 * BLKP and LRD must be set during separate register writes
355 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++) {
356 reg
= img_i2s_in_ch_readl(i2s
, i
, IMG_I2S_IN_CH_CTL
);
357 reg
= (reg
& ~chan_control_mask
) | chan_control_set
;
358 img_i2s_in_ch_writel(i2s
, i
, reg
, IMG_I2S_IN_CH_CTL
);
359 reg
= (reg
& ~IMG_I2S_IN_CH_CTL_BLKP_MASK
) | blkp_set
;
360 img_i2s_in_ch_writel(i2s
, i
, reg
, IMG_I2S_IN_CH_CTL
);
361 reg
= (reg
& ~IMG_I2S_IN_CH_CTL_LRD_MASK
) | lrd_set
;
362 img_i2s_in_ch_writel(i2s
, i
, reg
, IMG_I2S_IN_CH_CTL
);
365 for (i
= 0; i
< i2s
->active_channels
; i
++)
366 img_i2s_in_ch_enable(i2s
, i
);
368 pm_runtime_put(i2s
->dev
);
373 static const struct snd_soc_dai_ops img_i2s_in_dai_ops
= {
374 .trigger
= img_i2s_in_trigger
,
375 .hw_params
= img_i2s_in_hw_params
,
376 .set_fmt
= img_i2s_in_set_fmt
379 static int img_i2s_in_dai_probe(struct snd_soc_dai
*dai
)
381 struct img_i2s_in
*i2s
= snd_soc_dai_get_drvdata(dai
);
383 snd_soc_dai_init_dma_data(dai
, NULL
, &i2s
->dma_data
);
388 static const struct snd_soc_component_driver img_i2s_in_component
= {
392 static int img_i2s_in_dma_prepare_slave_config(struct snd_pcm_substream
*st
,
393 struct snd_pcm_hw_params
*params
, struct dma_slave_config
*sc
)
395 unsigned int i2s_channels
= params_channels(params
) / 2;
396 struct snd_soc_pcm_runtime
*rtd
= st
->private_data
;
397 struct snd_dmaengine_dai_dma_data
*dma_data
;
400 dma_data
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, st
);
402 ret
= snd_hwparams_to_dma_slave_config(st
, params
, sc
);
406 sc
->src_addr
= dma_data
->addr
;
407 sc
->src_addr_width
= dma_data
->addr_width
;
408 sc
->src_maxburst
= 4 * i2s_channels
;
413 static const struct snd_dmaengine_pcm_config img_i2s_in_dma_config
= {
414 .prepare_slave_config
= img_i2s_in_dma_prepare_slave_config
417 static int img_i2s_in_probe(struct platform_device
*pdev
)
419 struct img_i2s_in
*i2s
;
420 struct resource
*res
;
423 struct reset_control
*rst
;
424 unsigned int max_i2s_chan_pow_2
;
425 struct device
*dev
= &pdev
->dev
;
427 i2s
= devm_kzalloc(dev
, sizeof(*i2s
), GFP_KERNEL
);
431 platform_set_drvdata(pdev
, i2s
);
435 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
436 base
= devm_ioremap_resource(dev
, res
);
438 return PTR_ERR(base
);
442 if (of_property_read_u32(pdev
->dev
.of_node
, "img,i2s-channels",
443 &i2s
->max_i2s_chan
)) {
444 dev_err(dev
, "No img,i2s-channels property\n");
448 max_i2s_chan_pow_2
= 1 << get_count_order(i2s
->max_i2s_chan
);
450 i2s
->channel_base
= base
+ (max_i2s_chan_pow_2
* 0x20);
452 i2s
->clk_sys
= devm_clk_get(dev
, "sys");
453 if (IS_ERR(i2s
->clk_sys
)) {
454 if (PTR_ERR(i2s
->clk_sys
) != -EPROBE_DEFER
)
455 dev_err(dev
, "Failed to acquire clock 'sys'\n");
456 return PTR_ERR(i2s
->clk_sys
);
459 pm_runtime_enable(&pdev
->dev
);
460 if (!pm_runtime_enabled(&pdev
->dev
)) {
461 ret
= img_i2s_in_runtime_resume(&pdev
->dev
);
465 ret
= pm_runtime_get_sync(&pdev
->dev
);
469 i2s
->active_channels
= 1;
470 i2s
->dma_data
.addr
= res
->start
+ IMG_I2S_IN_RX_FIFO
;
471 i2s
->dma_data
.addr_width
= 4;
473 i2s
->dai_driver
.probe
= img_i2s_in_dai_probe
;
474 i2s
->dai_driver
.capture
.channels_min
= 2;
475 i2s
->dai_driver
.capture
.channels_max
= i2s
->max_i2s_chan
* 2;
476 i2s
->dai_driver
.capture
.rates
= SNDRV_PCM_RATE_8000_192000
;
477 i2s
->dai_driver
.capture
.formats
= SNDRV_PCM_FMTBIT_S32_LE
|
478 SNDRV_PCM_FMTBIT_S24_LE
| SNDRV_PCM_FMTBIT_S16_LE
;
479 i2s
->dai_driver
.ops
= &img_i2s_in_dai_ops
;
481 rst
= devm_reset_control_get_exclusive(dev
, "rst");
483 if (PTR_ERR(rst
) == -EPROBE_DEFER
) {
488 dev_dbg(dev
, "No top level reset found\n");
490 img_i2s_in_disable(i2s
);
492 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++)
493 img_i2s_in_ch_disable(i2s
, i
);
495 reset_control_assert(rst
);
496 reset_control_deassert(rst
);
499 img_i2s_in_writel(i2s
, 0, IMG_I2S_IN_CTL
);
501 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++)
502 img_i2s_in_ch_writel(i2s
, i
,
503 (4 << IMG_I2S_IN_CH_CTL_CCDEL_SHIFT
) |
504 IMG_I2S_IN_CH_CTL_JUST_MASK
|
505 IMG_I2S_IN_CH_CTL_FW_MASK
, IMG_I2S_IN_CH_CTL
);
507 pm_runtime_put(&pdev
->dev
);
509 i2s
->suspend_ch_ctl
= devm_kcalloc(dev
,
510 i2s
->max_i2s_chan
, sizeof(*i2s
->suspend_ch_ctl
), GFP_KERNEL
);
511 if (!i2s
->suspend_ch_ctl
) {
516 ret
= devm_snd_soc_register_component(dev
, &img_i2s_in_component
,
517 &i2s
->dai_driver
, 1);
521 ret
= devm_snd_dmaengine_pcm_register(dev
, &img_i2s_in_dma_config
, 0);
528 if (!pm_runtime_enabled(&pdev
->dev
))
529 img_i2s_in_runtime_suspend(&pdev
->dev
);
531 pm_runtime_disable(&pdev
->dev
);
536 static int img_i2s_in_dev_remove(struct platform_device
*pdev
)
538 pm_runtime_disable(&pdev
->dev
);
539 if (!pm_runtime_status_suspended(&pdev
->dev
))
540 img_i2s_in_runtime_suspend(&pdev
->dev
);
545 #ifdef CONFIG_PM_SLEEP
546 static int img_i2s_in_suspend(struct device
*dev
)
548 struct img_i2s_in
*i2s
= dev_get_drvdata(dev
);
552 if (pm_runtime_status_suspended(dev
)) {
553 ret
= img_i2s_in_runtime_resume(dev
);
558 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++) {
559 reg
= img_i2s_in_ch_readl(i2s
, i
, IMG_I2S_IN_CH_CTL
);
560 i2s
->suspend_ch_ctl
[i
] = reg
;
563 i2s
->suspend_ctl
= img_i2s_in_readl(i2s
, IMG_I2S_IN_CTL
);
565 img_i2s_in_runtime_suspend(dev
);
570 static int img_i2s_in_resume(struct device
*dev
)
572 struct img_i2s_in
*i2s
= dev_get_drvdata(dev
);
576 ret
= img_i2s_in_runtime_resume(dev
);
580 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++) {
581 reg
= i2s
->suspend_ch_ctl
[i
];
582 img_i2s_in_ch_writel(i2s
, i
, reg
, IMG_I2S_IN_CH_CTL
);
585 img_i2s_in_writel(i2s
, i2s
->suspend_ctl
, IMG_I2S_IN_CTL
);
587 if (pm_runtime_status_suspended(dev
))
588 img_i2s_in_runtime_suspend(dev
);
594 static const struct of_device_id img_i2s_in_of_match
[] = {
595 { .compatible
= "img,i2s-in" },
598 MODULE_DEVICE_TABLE(of
, img_i2s_in_of_match
);
600 static const struct dev_pm_ops img_i2s_in_pm_ops
= {
601 SET_RUNTIME_PM_OPS(img_i2s_in_runtime_suspend
,
602 img_i2s_in_runtime_resume
, NULL
)
603 SET_SYSTEM_SLEEP_PM_OPS(img_i2s_in_suspend
, img_i2s_in_resume
)
606 static struct platform_driver img_i2s_in_driver
= {
608 .name
= "img-i2s-in",
609 .of_match_table
= img_i2s_in_of_match
,
610 .pm
= &img_i2s_in_pm_ops
612 .probe
= img_i2s_in_probe
,
613 .remove
= img_i2s_in_dev_remove
615 module_platform_driver(img_i2s_in_driver
);
617 MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
618 MODULE_DESCRIPTION("IMG I2S Input Driver");
619 MODULE_LICENSE("GPL v2");