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_CLOCK_PROVIDER_MASK
) {
337 case SND_SOC_DAIFMT_BC_FC
:
343 chan_control_mask
= IMG_I2S_IN_CH_CTL_CLK_TRANS_MASK
;
345 ret
= pm_runtime_resume_and_get(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 int img_i2s_in_dai_probe(struct snd_soc_dai
*dai
)
375 struct img_i2s_in
*i2s
= snd_soc_dai_get_drvdata(dai
);
377 snd_soc_dai_init_dma_data(dai
, NULL
, &i2s
->dma_data
);
382 static const struct snd_soc_dai_ops img_i2s_in_dai_ops
= {
383 .probe
= img_i2s_in_dai_probe
,
384 .trigger
= img_i2s_in_trigger
,
385 .hw_params
= img_i2s_in_hw_params
,
386 .set_fmt
= img_i2s_in_set_fmt
389 static const struct snd_soc_component_driver img_i2s_in_component
= {
390 .name
= "img-i2s-in",
391 .legacy_dai_naming
= 1,
394 static int img_i2s_in_dma_prepare_slave_config(struct snd_pcm_substream
*st
,
395 struct snd_pcm_hw_params
*params
, struct dma_slave_config
*sc
)
397 unsigned int i2s_channels
= params_channels(params
) / 2;
398 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(st
);
399 struct snd_dmaengine_dai_dma_data
*dma_data
;
402 dma_data
= snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd
, 0), st
);
404 ret
= snd_hwparams_to_dma_slave_config(st
, params
, sc
);
408 sc
->src_addr
= dma_data
->addr
;
409 sc
->src_addr_width
= dma_data
->addr_width
;
410 sc
->src_maxburst
= 4 * i2s_channels
;
415 static const struct snd_dmaengine_pcm_config img_i2s_in_dma_config
= {
416 .prepare_slave_config
= img_i2s_in_dma_prepare_slave_config
419 static int img_i2s_in_probe(struct platform_device
*pdev
)
421 struct img_i2s_in
*i2s
;
422 struct resource
*res
;
425 struct reset_control
*rst
;
426 unsigned int max_i2s_chan_pow_2
;
427 struct device
*dev
= &pdev
->dev
;
429 i2s
= devm_kzalloc(dev
, sizeof(*i2s
), GFP_KERNEL
);
433 platform_set_drvdata(pdev
, i2s
);
437 base
= devm_platform_get_and_ioremap_resource(pdev
, 0, &res
);
439 return PTR_ERR(base
);
443 if (of_property_read_u32(pdev
->dev
.of_node
, "img,i2s-channels",
444 &i2s
->max_i2s_chan
)) {
445 dev_err(dev
, "No img,i2s-channels property\n");
449 max_i2s_chan_pow_2
= 1 << get_count_order(i2s
->max_i2s_chan
);
451 i2s
->channel_base
= base
+ (max_i2s_chan_pow_2
* 0x20);
453 i2s
->clk_sys
= devm_clk_get(dev
, "sys");
454 if (IS_ERR(i2s
->clk_sys
))
455 return dev_err_probe(dev
, PTR_ERR(i2s
->clk_sys
),
456 "Failed to acquire clock 'sys'\n");
458 pm_runtime_enable(&pdev
->dev
);
459 if (!pm_runtime_enabled(&pdev
->dev
)) {
460 ret
= img_i2s_in_runtime_resume(&pdev
->dev
);
464 ret
= pm_runtime_resume_and_get(&pdev
->dev
);
468 i2s
->active_channels
= 1;
469 i2s
->dma_data
.addr
= res
->start
+ IMG_I2S_IN_RX_FIFO
;
470 i2s
->dma_data
.addr_width
= 4;
472 i2s
->dai_driver
.capture
.channels_min
= 2;
473 i2s
->dai_driver
.capture
.channels_max
= i2s
->max_i2s_chan
* 2;
474 i2s
->dai_driver
.capture
.rates
= SNDRV_PCM_RATE_8000_192000
;
475 i2s
->dai_driver
.capture
.formats
= SNDRV_PCM_FMTBIT_S32_LE
|
476 SNDRV_PCM_FMTBIT_S24_LE
| SNDRV_PCM_FMTBIT_S16_LE
;
477 i2s
->dai_driver
.ops
= &img_i2s_in_dai_ops
;
479 rst
= devm_reset_control_get_exclusive(dev
, "rst");
481 if (PTR_ERR(rst
) == -EPROBE_DEFER
) {
483 pm_runtime_put(&pdev
->dev
);
487 dev_dbg(dev
, "No top level reset found\n");
489 img_i2s_in_disable(i2s
);
491 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++)
492 img_i2s_in_ch_disable(i2s
, i
);
494 reset_control_assert(rst
);
495 reset_control_deassert(rst
);
498 img_i2s_in_writel(i2s
, 0, IMG_I2S_IN_CTL
);
500 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++)
501 img_i2s_in_ch_writel(i2s
, i
,
502 (4 << IMG_I2S_IN_CH_CTL_CCDEL_SHIFT
) |
503 IMG_I2S_IN_CH_CTL_JUST_MASK
|
504 IMG_I2S_IN_CH_CTL_FW_MASK
, IMG_I2S_IN_CH_CTL
);
506 pm_runtime_put(&pdev
->dev
);
508 i2s
->suspend_ch_ctl
= devm_kcalloc(dev
,
509 i2s
->max_i2s_chan
, sizeof(*i2s
->suspend_ch_ctl
), GFP_KERNEL
);
510 if (!i2s
->suspend_ch_ctl
) {
515 ret
= devm_snd_soc_register_component(dev
, &img_i2s_in_component
,
516 &i2s
->dai_driver
, 1);
520 ret
= devm_snd_dmaengine_pcm_register(dev
, &img_i2s_in_dma_config
, 0);
527 if (!pm_runtime_enabled(&pdev
->dev
))
528 img_i2s_in_runtime_suspend(&pdev
->dev
);
530 pm_runtime_disable(&pdev
->dev
);
535 static void img_i2s_in_dev_remove(struct platform_device
*pdev
)
537 pm_runtime_disable(&pdev
->dev
);
538 if (!pm_runtime_status_suspended(&pdev
->dev
))
539 img_i2s_in_runtime_suspend(&pdev
->dev
);
542 #ifdef CONFIG_PM_SLEEP
543 static int img_i2s_in_suspend(struct device
*dev
)
545 struct img_i2s_in
*i2s
= dev_get_drvdata(dev
);
549 if (pm_runtime_status_suspended(dev
)) {
550 ret
= img_i2s_in_runtime_resume(dev
);
555 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++) {
556 reg
= img_i2s_in_ch_readl(i2s
, i
, IMG_I2S_IN_CH_CTL
);
557 i2s
->suspend_ch_ctl
[i
] = reg
;
560 i2s
->suspend_ctl
= img_i2s_in_readl(i2s
, IMG_I2S_IN_CTL
);
562 img_i2s_in_runtime_suspend(dev
);
567 static int img_i2s_in_resume(struct device
*dev
)
569 struct img_i2s_in
*i2s
= dev_get_drvdata(dev
);
573 ret
= img_i2s_in_runtime_resume(dev
);
577 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++) {
578 reg
= i2s
->suspend_ch_ctl
[i
];
579 img_i2s_in_ch_writel(i2s
, i
, reg
, IMG_I2S_IN_CH_CTL
);
582 img_i2s_in_writel(i2s
, i2s
->suspend_ctl
, IMG_I2S_IN_CTL
);
584 if (pm_runtime_status_suspended(dev
))
585 img_i2s_in_runtime_suspend(dev
);
591 static const struct of_device_id img_i2s_in_of_match
[] = {
592 { .compatible
= "img,i2s-in" },
595 MODULE_DEVICE_TABLE(of
, img_i2s_in_of_match
);
597 static const struct dev_pm_ops img_i2s_in_pm_ops
= {
598 SET_RUNTIME_PM_OPS(img_i2s_in_runtime_suspend
,
599 img_i2s_in_runtime_resume
, NULL
)
600 SET_SYSTEM_SLEEP_PM_OPS(img_i2s_in_suspend
, img_i2s_in_resume
)
603 static struct platform_driver img_i2s_in_driver
= {
605 .name
= "img-i2s-in",
606 .of_match_table
= img_i2s_in_of_match
,
607 .pm
= &img_i2s_in_pm_ops
609 .probe
= img_i2s_in_probe
,
610 .remove
= img_i2s_in_dev_remove
612 module_platform_driver(img_i2s_in_driver
);
614 MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
615 MODULE_DESCRIPTION("IMG I2S Input Driver");
616 MODULE_LICENSE("GPL v2");