2 * IMG I2S output 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_I2S_OUT_TX_FIFO 0x0
31 #define IMG_I2S_OUT_CTL 0x4
32 #define IMG_I2S_OUT_CTL_DATA_EN_MASK BIT(24)
33 #define IMG_I2S_OUT_CTL_ACTIVE_CHAN_MASK 0xffe000
34 #define IMG_I2S_OUT_CTL_ACTIVE_CHAN_SHIFT 13
35 #define IMG_I2S_OUT_CTL_FRM_SIZE_MASK BIT(8)
36 #define IMG_I2S_OUT_CTL_MASTER_MASK BIT(6)
37 #define IMG_I2S_OUT_CTL_CLK_MASK BIT(5)
38 #define IMG_I2S_OUT_CTL_CLK_EN_MASK BIT(4)
39 #define IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK BIT(3)
40 #define IMG_I2S_OUT_CTL_BCLK_POL_MASK BIT(2)
41 #define IMG_I2S_OUT_CTL_ME_MASK BIT(0)
43 #define IMG_I2S_OUT_CH_CTL 0x4
44 #define IMG_I2S_OUT_CHAN_CTL_CH_MASK BIT(11)
45 #define IMG_I2S_OUT_CHAN_CTL_LT_MASK BIT(10)
46 #define IMG_I2S_OUT_CHAN_CTL_FMT_MASK 0xf0
47 #define IMG_I2S_OUT_CHAN_CTL_FMT_SHIFT 4
48 #define IMG_I2S_OUT_CHAN_CTL_JUST_MASK BIT(3)
49 #define IMG_I2S_OUT_CHAN_CTL_CLKT_MASK BIT(1)
50 #define IMG_I2S_OUT_CHAN_CTL_ME_MASK BIT(0)
52 #define IMG_I2S_OUT_CH_STRIDE 0x20
58 struct snd_dmaengine_dai_dma_data dma_data
;
60 unsigned int max_i2s_chan
;
61 void __iomem
*channel_base
;
62 bool force_clk_active
;
63 unsigned int active_channels
;
64 struct reset_control
*rst
;
65 struct snd_soc_dai_driver dai_driver
;
70 static int img_i2s_out_runtime_suspend(struct device
*dev
)
72 struct img_i2s_out
*i2s
= dev_get_drvdata(dev
);
74 clk_disable_unprepare(i2s
->clk_ref
);
75 clk_disable_unprepare(i2s
->clk_sys
);
80 static int img_i2s_out_runtime_resume(struct device
*dev
)
82 struct img_i2s_out
*i2s
= dev_get_drvdata(dev
);
85 ret
= clk_prepare_enable(i2s
->clk_sys
);
87 dev_err(dev
, "clk_enable failed: %d\n", ret
);
91 ret
= clk_prepare_enable(i2s
->clk_ref
);
93 dev_err(dev
, "clk_enable failed: %d\n", ret
);
94 clk_disable_unprepare(i2s
->clk_sys
);
101 static inline void img_i2s_out_writel(struct img_i2s_out
*i2s
, u32 val
,
104 writel(val
, i2s
->base
+ reg
);
107 static inline u32
img_i2s_out_readl(struct img_i2s_out
*i2s
, u32 reg
)
109 return readl(i2s
->base
+ reg
);
112 static inline void img_i2s_out_ch_writel(struct img_i2s_out
*i2s
,
113 u32 chan
, u32 val
, u32 reg
)
115 writel(val
, i2s
->channel_base
+ (chan
* IMG_I2S_OUT_CH_STRIDE
) + reg
);
118 static inline u32
img_i2s_out_ch_readl(struct img_i2s_out
*i2s
, u32 chan
,
121 return readl(i2s
->channel_base
+ (chan
* IMG_I2S_OUT_CH_STRIDE
) + reg
);
124 static inline void img_i2s_out_ch_disable(struct img_i2s_out
*i2s
, u32 chan
)
128 reg
= img_i2s_out_ch_readl(i2s
, chan
, IMG_I2S_OUT_CH_CTL
);
129 reg
&= ~IMG_I2S_OUT_CHAN_CTL_ME_MASK
;
130 img_i2s_out_ch_writel(i2s
, chan
, reg
, IMG_I2S_OUT_CH_CTL
);
133 static inline void img_i2s_out_ch_enable(struct img_i2s_out
*i2s
, u32 chan
)
137 reg
= img_i2s_out_ch_readl(i2s
, chan
, IMG_I2S_OUT_CH_CTL
);
138 reg
|= IMG_I2S_OUT_CHAN_CTL_ME_MASK
;
139 img_i2s_out_ch_writel(i2s
, chan
, reg
, IMG_I2S_OUT_CH_CTL
);
142 static inline void img_i2s_out_disable(struct img_i2s_out
*i2s
)
146 reg
= img_i2s_out_readl(i2s
, IMG_I2S_OUT_CTL
);
147 reg
&= ~IMG_I2S_OUT_CTL_ME_MASK
;
148 img_i2s_out_writel(i2s
, reg
, IMG_I2S_OUT_CTL
);
151 static inline void img_i2s_out_enable(struct img_i2s_out
*i2s
)
155 reg
= img_i2s_out_readl(i2s
, IMG_I2S_OUT_CTL
);
156 reg
|= IMG_I2S_OUT_CTL_ME_MASK
;
157 img_i2s_out_writel(i2s
, reg
, IMG_I2S_OUT_CTL
);
160 static void img_i2s_out_reset(struct img_i2s_out
*i2s
)
163 u32 core_ctl
, chan_ctl
;
165 core_ctl
= img_i2s_out_readl(i2s
, IMG_I2S_OUT_CTL
) &
166 ~IMG_I2S_OUT_CTL_ME_MASK
&
167 ~IMG_I2S_OUT_CTL_DATA_EN_MASK
;
169 if (!i2s
->force_clk_active
)
170 core_ctl
&= ~IMG_I2S_OUT_CTL_CLK_EN_MASK
;
172 chan_ctl
= img_i2s_out_ch_readl(i2s
, 0, IMG_I2S_OUT_CH_CTL
) &
173 ~IMG_I2S_OUT_CHAN_CTL_ME_MASK
;
175 reset_control_assert(i2s
->rst
);
176 reset_control_deassert(i2s
->rst
);
178 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++)
179 img_i2s_out_ch_writel(i2s
, i
, chan_ctl
, IMG_I2S_OUT_CH_CTL
);
181 for (i
= 0; i
< i2s
->active_channels
; i
++)
182 img_i2s_out_ch_enable(i2s
, i
);
184 img_i2s_out_writel(i2s
, core_ctl
, IMG_I2S_OUT_CTL
);
185 img_i2s_out_enable(i2s
);
188 static int img_i2s_out_trigger(struct snd_pcm_substream
*substream
, int cmd
,
189 struct snd_soc_dai
*dai
)
191 struct img_i2s_out
*i2s
= snd_soc_dai_get_drvdata(dai
);
195 case SNDRV_PCM_TRIGGER_START
:
196 case SNDRV_PCM_TRIGGER_RESUME
:
197 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
198 reg
= img_i2s_out_readl(i2s
, IMG_I2S_OUT_CTL
);
199 if (!i2s
->force_clk_active
)
200 reg
|= IMG_I2S_OUT_CTL_CLK_EN_MASK
;
201 reg
|= IMG_I2S_OUT_CTL_DATA_EN_MASK
;
202 img_i2s_out_writel(i2s
, reg
, IMG_I2S_OUT_CTL
);
204 case SNDRV_PCM_TRIGGER_STOP
:
205 case SNDRV_PCM_TRIGGER_SUSPEND
:
206 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
207 img_i2s_out_reset(i2s
);
216 static int img_i2s_out_hw_params(struct snd_pcm_substream
*substream
,
217 struct snd_pcm_hw_params
*params
, struct snd_soc_dai
*dai
)
219 struct img_i2s_out
*i2s
= snd_soc_dai_get_drvdata(dai
);
220 unsigned int channels
, i2s_channels
;
221 long pre_div_a
, pre_div_b
, diff_a
, diff_b
, rate
, clk_rate
;
223 u32 reg
, control_mask
, control_set
= 0;
224 snd_pcm_format_t format
;
226 rate
= params_rate(params
);
227 format
= params_format(params
);
228 channels
= params_channels(params
);
229 i2s_channels
= channels
/ 2;
231 if (format
!= SNDRV_PCM_FORMAT_S32_LE
)
234 if ((channels
< 2) ||
235 (channels
> (i2s
->max_i2s_chan
* 2)) ||
239 pre_div_a
= clk_round_rate(i2s
->clk_ref
, rate
* 256);
242 pre_div_b
= clk_round_rate(i2s
->clk_ref
, rate
* 384);
246 diff_a
= abs((pre_div_a
/ 256) - rate
);
247 diff_b
= abs((pre_div_b
/ 384) - rate
);
249 /* If diffs are equal, use lower clock rate */
251 clk_set_rate(i2s
->clk_ref
, pre_div_b
);
253 clk_set_rate(i2s
->clk_ref
, pre_div_a
);
256 * Another driver (eg alsa machine driver) may have rejected the above
257 * change. Get the current rate and set the register bit according to
258 * the new minimum diff
260 clk_rate
= clk_get_rate(i2s
->clk_ref
);
262 diff_a
= abs((clk_rate
/ 256) - rate
);
263 diff_b
= abs((clk_rate
/ 384) - rate
);
266 control_set
|= IMG_I2S_OUT_CTL_CLK_MASK
;
268 control_set
|= ((i2s_channels
- 1) <<
269 IMG_I2S_OUT_CTL_ACTIVE_CHAN_SHIFT
) &
270 IMG_I2S_OUT_CTL_ACTIVE_CHAN_MASK
;
272 control_mask
= IMG_I2S_OUT_CTL_CLK_MASK
|
273 IMG_I2S_OUT_CTL_ACTIVE_CHAN_MASK
;
275 img_i2s_out_disable(i2s
);
277 reg
= img_i2s_out_readl(i2s
, IMG_I2S_OUT_CTL
);
278 reg
= (reg
& ~control_mask
) | control_set
;
279 img_i2s_out_writel(i2s
, reg
, IMG_I2S_OUT_CTL
);
281 for (i
= 0; i
< i2s_channels
; i
++)
282 img_i2s_out_ch_enable(i2s
, i
);
284 for (; i
< i2s
->max_i2s_chan
; i
++)
285 img_i2s_out_ch_disable(i2s
, i
);
287 img_i2s_out_enable(i2s
);
289 i2s
->active_channels
= i2s_channels
;
294 static int img_i2s_out_set_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
296 struct img_i2s_out
*i2s
= snd_soc_dai_get_drvdata(dai
);
298 bool force_clk_active
;
299 u32 chan_control_mask
, control_mask
, chan_control_set
= 0;
300 u32 reg
, control_set
= 0;
302 force_clk_active
= ((fmt
& SND_SOC_DAIFMT_CLOCK_MASK
) ==
303 SND_SOC_DAIFMT_CONT
);
305 if (force_clk_active
)
306 control_set
|= IMG_I2S_OUT_CTL_CLK_EN_MASK
;
308 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
309 case SND_SOC_DAIFMT_CBM_CFM
:
311 case SND_SOC_DAIFMT_CBS_CFS
:
312 control_set
|= IMG_I2S_OUT_CTL_MASTER_MASK
;
318 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
319 case SND_SOC_DAIFMT_NB_NF
:
320 control_set
|= IMG_I2S_OUT_CTL_BCLK_POL_MASK
;
322 case SND_SOC_DAIFMT_NB_IF
:
323 control_set
|= IMG_I2S_OUT_CTL_BCLK_POL_MASK
;
324 control_set
|= IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK
;
326 case SND_SOC_DAIFMT_IB_NF
:
328 case SND_SOC_DAIFMT_IB_IF
:
329 control_set
|= IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK
;
335 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
336 case SND_SOC_DAIFMT_I2S
:
337 chan_control_set
|= IMG_I2S_OUT_CHAN_CTL_CLKT_MASK
;
339 case SND_SOC_DAIFMT_LEFT_J
:
345 control_mask
= IMG_I2S_OUT_CTL_CLK_EN_MASK
|
346 IMG_I2S_OUT_CTL_MASTER_MASK
|
347 IMG_I2S_OUT_CTL_BCLK_POL_MASK
|
348 IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK
;
350 chan_control_mask
= IMG_I2S_OUT_CHAN_CTL_CLKT_MASK
;
352 ret
= pm_runtime_get_sync(i2s
->dev
);
356 img_i2s_out_disable(i2s
);
358 reg
= img_i2s_out_readl(i2s
, IMG_I2S_OUT_CTL
);
359 reg
= (reg
& ~control_mask
) | control_set
;
360 img_i2s_out_writel(i2s
, reg
, IMG_I2S_OUT_CTL
);
362 for (i
= 0; i
< i2s
->active_channels
; i
++)
363 img_i2s_out_ch_disable(i2s
, i
);
365 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++) {
366 reg
= img_i2s_out_ch_readl(i2s
, i
, IMG_I2S_OUT_CH_CTL
);
367 reg
= (reg
& ~chan_control_mask
) | chan_control_set
;
368 img_i2s_out_ch_writel(i2s
, i
, reg
, IMG_I2S_OUT_CH_CTL
);
371 for (i
= 0; i
< i2s
->active_channels
; i
++)
372 img_i2s_out_ch_enable(i2s
, i
);
374 img_i2s_out_enable(i2s
);
375 pm_runtime_put(i2s
->dev
);
377 i2s
->force_clk_active
= force_clk_active
;
382 static const struct snd_soc_dai_ops img_i2s_out_dai_ops
= {
383 .trigger
= img_i2s_out_trigger
,
384 .hw_params
= img_i2s_out_hw_params
,
385 .set_fmt
= img_i2s_out_set_fmt
388 static int img_i2s_out_dai_probe(struct snd_soc_dai
*dai
)
390 struct img_i2s_out
*i2s
= snd_soc_dai_get_drvdata(dai
);
392 snd_soc_dai_init_dma_data(dai
, &i2s
->dma_data
, NULL
);
397 static const struct snd_soc_component_driver img_i2s_out_component
= {
398 .name
= "img-i2s-out"
401 static int img_i2s_out_dma_prepare_slave_config(struct snd_pcm_substream
*st
,
402 struct snd_pcm_hw_params
*params
, struct dma_slave_config
*sc
)
404 unsigned int i2s_channels
= params_channels(params
) / 2;
405 struct snd_soc_pcm_runtime
*rtd
= st
->private_data
;
406 struct snd_dmaengine_dai_dma_data
*dma_data
;
409 dma_data
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, st
);
411 ret
= snd_hwparams_to_dma_slave_config(st
, params
, sc
);
415 sc
->dst_addr
= dma_data
->addr
;
416 sc
->dst_addr_width
= dma_data
->addr_width
;
417 sc
->dst_maxburst
= 4 * i2s_channels
;
422 static const struct snd_dmaengine_pcm_config img_i2s_out_dma_config
= {
423 .prepare_slave_config
= img_i2s_out_dma_prepare_slave_config
426 static int img_i2s_out_probe(struct platform_device
*pdev
)
428 struct img_i2s_out
*i2s
;
429 struct resource
*res
;
432 unsigned int max_i2s_chan_pow_2
;
434 struct device
*dev
= &pdev
->dev
;
436 i2s
= devm_kzalloc(&pdev
->dev
, sizeof(*i2s
), GFP_KERNEL
);
440 platform_set_drvdata(pdev
, i2s
);
442 i2s
->dev
= &pdev
->dev
;
444 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
445 base
= devm_ioremap_resource(&pdev
->dev
, res
);
447 return PTR_ERR(base
);
451 if (of_property_read_u32(pdev
->dev
.of_node
, "img,i2s-channels",
452 &i2s
->max_i2s_chan
)) {
453 dev_err(&pdev
->dev
, "No img,i2s-channels property\n");
457 max_i2s_chan_pow_2
= 1 << get_count_order(i2s
->max_i2s_chan
);
459 i2s
->channel_base
= base
+ (max_i2s_chan_pow_2
* 0x20);
461 i2s
->rst
= devm_reset_control_get_exclusive(&pdev
->dev
, "rst");
462 if (IS_ERR(i2s
->rst
)) {
463 if (PTR_ERR(i2s
->rst
) != -EPROBE_DEFER
)
464 dev_err(&pdev
->dev
, "No top level reset found\n");
465 return PTR_ERR(i2s
->rst
);
468 i2s
->clk_sys
= devm_clk_get(&pdev
->dev
, "sys");
469 if (IS_ERR(i2s
->clk_sys
)) {
470 if (PTR_ERR(i2s
->clk_sys
) != -EPROBE_DEFER
)
471 dev_err(dev
, "Failed to acquire clock 'sys'\n");
472 return PTR_ERR(i2s
->clk_sys
);
475 i2s
->clk_ref
= devm_clk_get(&pdev
->dev
, "ref");
476 if (IS_ERR(i2s
->clk_ref
)) {
477 if (PTR_ERR(i2s
->clk_ref
) != -EPROBE_DEFER
)
478 dev_err(dev
, "Failed to acquire clock 'ref'\n");
479 return PTR_ERR(i2s
->clk_ref
);
482 i2s
->suspend_ch_ctl
= devm_kzalloc(dev
,
483 sizeof(*i2s
->suspend_ch_ctl
) * i2s
->max_i2s_chan
, GFP_KERNEL
);
484 if (!i2s
->suspend_ch_ctl
)
487 pm_runtime_enable(&pdev
->dev
);
488 if (!pm_runtime_enabled(&pdev
->dev
)) {
489 ret
= img_i2s_out_runtime_resume(&pdev
->dev
);
493 ret
= pm_runtime_get_sync(&pdev
->dev
);
497 reg
= IMG_I2S_OUT_CTL_FRM_SIZE_MASK
;
498 img_i2s_out_writel(i2s
, reg
, IMG_I2S_OUT_CTL
);
500 reg
= IMG_I2S_OUT_CHAN_CTL_JUST_MASK
|
501 IMG_I2S_OUT_CHAN_CTL_LT_MASK
|
502 IMG_I2S_OUT_CHAN_CTL_CH_MASK
|
503 (8 << IMG_I2S_OUT_CHAN_CTL_FMT_SHIFT
);
505 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++)
506 img_i2s_out_ch_writel(i2s
, i
, reg
, IMG_I2S_OUT_CH_CTL
);
508 img_i2s_out_reset(i2s
);
509 pm_runtime_put(&pdev
->dev
);
511 i2s
->active_channels
= 1;
512 i2s
->dma_data
.addr
= res
->start
+ IMG_I2S_OUT_TX_FIFO
;
513 i2s
->dma_data
.addr_width
= 4;
514 i2s
->dma_data
.maxburst
= 4;
516 i2s
->dai_driver
.probe
= img_i2s_out_dai_probe
;
517 i2s
->dai_driver
.playback
.channels_min
= 2;
518 i2s
->dai_driver
.playback
.channels_max
= i2s
->max_i2s_chan
* 2;
519 i2s
->dai_driver
.playback
.rates
= SNDRV_PCM_RATE_8000_192000
;
520 i2s
->dai_driver
.playback
.formats
= SNDRV_PCM_FMTBIT_S32_LE
;
521 i2s
->dai_driver
.ops
= &img_i2s_out_dai_ops
;
523 ret
= devm_snd_soc_register_component(&pdev
->dev
,
524 &img_i2s_out_component
, &i2s
->dai_driver
, 1);
528 ret
= devm_snd_dmaengine_pcm_register(&pdev
->dev
,
529 &img_i2s_out_dma_config
, 0);
536 if (!pm_runtime_status_suspended(&pdev
->dev
))
537 img_i2s_out_runtime_suspend(&pdev
->dev
);
539 pm_runtime_disable(&pdev
->dev
);
544 static int img_i2s_out_dev_remove(struct platform_device
*pdev
)
546 pm_runtime_disable(&pdev
->dev
);
547 if (!pm_runtime_status_suspended(&pdev
->dev
))
548 img_i2s_out_runtime_suspend(&pdev
->dev
);
553 #ifdef CONFIG_PM_SLEEP
554 static int img_i2s_out_suspend(struct device
*dev
)
556 struct img_i2s_out
*i2s
= dev_get_drvdata(dev
);
560 if (pm_runtime_status_suspended(dev
)) {
561 ret
= img_i2s_out_runtime_resume(dev
);
566 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++) {
567 reg
= img_i2s_out_ch_readl(i2s
, i
, IMG_I2S_OUT_CH_CTL
);
568 i2s
->suspend_ch_ctl
[i
] = reg
;
571 i2s
->suspend_ctl
= img_i2s_out_readl(i2s
, IMG_I2S_OUT_CTL
);
573 img_i2s_out_runtime_suspend(dev
);
578 static int img_i2s_out_resume(struct device
*dev
)
580 struct img_i2s_out
*i2s
= dev_get_drvdata(dev
);
584 ret
= img_i2s_out_runtime_resume(dev
);
588 for (i
= 0; i
< i2s
->max_i2s_chan
; i
++) {
589 reg
= i2s
->suspend_ch_ctl
[i
];
590 img_i2s_out_ch_writel(i2s
, i
, reg
, IMG_I2S_OUT_CH_CTL
);
593 img_i2s_out_writel(i2s
, i2s
->suspend_ctl
, IMG_I2S_OUT_CTL
);
595 if (pm_runtime_status_suspended(dev
))
596 img_i2s_out_runtime_suspend(dev
);
602 static const struct of_device_id img_i2s_out_of_match
[] = {
603 { .compatible
= "img,i2s-out" },
606 MODULE_DEVICE_TABLE(of
, img_i2s_out_of_match
);
608 static const struct dev_pm_ops img_i2s_out_pm_ops
= {
609 SET_RUNTIME_PM_OPS(img_i2s_out_runtime_suspend
,
610 img_i2s_out_runtime_resume
, NULL
)
611 SET_SYSTEM_SLEEP_PM_OPS(img_i2s_out_suspend
, img_i2s_out_resume
)
614 static struct platform_driver img_i2s_out_driver
= {
616 .name
= "img-i2s-out",
617 .of_match_table
= img_i2s_out_of_match
,
618 .pm
= &img_i2s_out_pm_ops
620 .probe
= img_i2s_out_probe
,
621 .remove
= img_i2s_out_dev_remove
623 module_platform_driver(img_i2s_out_driver
);
625 MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
626 MODULE_DESCRIPTION("IMG I2S Output Driver");
627 MODULE_LICENSE("GPL v2");