1 // SPDX-License-Identifier: GPL-2.0-or-later
3 // This driver supports the DMIC in Allwinner's H6 SoCs.
5 // Copyright 2021 Ban Tao <fengzheng923@gmail.com>
8 #include <linux/device.h>
9 #include <linux/mod_devicetable.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/reset.h>
14 #include <sound/dmaengine_pcm.h>
15 #include <sound/pcm_params.h>
16 #include <sound/soc.h>
17 #include <sound/tlv.h>
19 #define SUN50I_DMIC_EN_CTL (0x00)
20 #define SUN50I_DMIC_EN_CTL_GLOBE BIT(8)
21 #define SUN50I_DMIC_EN_CTL_CHAN(v) ((v) << 0)
22 #define SUN50I_DMIC_EN_CTL_CHAN_MASK GENMASK(7, 0)
23 #define SUN50I_DMIC_SR (0x04)
24 #define SUN50I_DMIC_SR_SAMPLE_RATE(v) ((v) << 0)
25 #define SUN50I_DMIC_SR_SAMPLE_RATE_MASK GENMASK(2, 0)
26 #define SUN50I_DMIC_CTL (0x08)
27 #define SUN50I_DMIC_CTL_OVERSAMPLE_RATE BIT(0)
28 #define SUN50I_DMIC_DATA (0x10)
29 #define SUN50I_DMIC_INTC (0x14)
30 #define SUN50I_DMIC_FIFO_DRQ_EN BIT(2)
31 #define SUN50I_DMIC_INT_STA (0x18)
32 #define SUN50I_DMIC_INT_STA_OVERRUN_IRQ_PENDING BIT(1)
33 #define SUN50I_DMIC_INT_STA_DATA_IRQ_PENDING BIT(0)
34 #define SUN50I_DMIC_RXFIFO_CTL (0x1c)
35 #define SUN50I_DMIC_RXFIFO_CTL_FLUSH BIT(31)
36 #define SUN50I_DMIC_RXFIFO_CTL_MODE_MASK BIT(9)
37 #define SUN50I_DMIC_RXFIFO_CTL_MODE_LSB (0 << 9)
38 #define SUN50I_DMIC_RXFIFO_CTL_MODE_MSB (1 << 9)
39 #define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK BIT(8)
40 #define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16 (0 << 8)
41 #define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_24 (1 << 8)
42 #define SUN50I_DMIC_CH_NUM (0x24)
43 #define SUN50I_DMIC_CH_NUM_N(v) ((v) << 0)
44 #define SUN50I_DMIC_CH_NUM_N_MASK GENMASK(2, 0)
45 #define SUN50I_DMIC_CNT (0x2c)
46 #define SUN50I_DMIC_CNT_N (1 << 0)
47 #define SUN50I_DMIC_D0D1_VOL_CTR (0x30)
48 #define SUN50I_DMIC_D0D1_VOL_CTR_0R (0)
49 #define SUN50I_DMIC_D0D1_VOL_CTR_0L (8)
50 #define SUN50I_DMIC_D0D1_VOL_CTR_1R (16)
51 #define SUN50I_DMIC_D0D1_VOL_CTR_1L (24)
52 #define SUN50I_DMIC_D2D3_VOL_CTR (0x34)
53 #define SUN50I_DMIC_D2D3_VOL_CTR_2R (0)
54 #define SUN50I_DMIC_D2D3_VOL_CTR_2L (8)
55 #define SUN50I_DMIC_D2D3_VOL_CTR_3R (16)
56 #define SUN50I_DMIC_D2D3_VOL_CTR_3L (24)
58 #define SUN50I_DMIC_HPF_CTRL (0x38)
59 #define SUN50I_DMIC_VERSION (0x50)
61 struct sun50i_dmic_dev
{
64 struct reset_control
*rst
;
65 struct regmap
*regmap
;
66 struct snd_dmaengine_dai_dma_data dma_params_rx
;
70 unsigned int samplerate
;
71 unsigned int rate_bit
;
74 static const struct dmic_rate dmic_rate_s
[] = {
86 static int sun50i_dmic_startup(struct snd_pcm_substream
*substream
,
87 struct snd_soc_dai
*cpu_dai
)
89 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
90 struct sun50i_dmic_dev
*host
= snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd
, 0));
92 /* only support capture */
93 if (substream
->stream
!= SNDRV_PCM_STREAM_CAPTURE
)
96 regmap_update_bits(host
->regmap
, SUN50I_DMIC_RXFIFO_CTL
,
97 SUN50I_DMIC_RXFIFO_CTL_FLUSH
,
98 SUN50I_DMIC_RXFIFO_CTL_FLUSH
);
99 regmap_write(host
->regmap
, SUN50I_DMIC_CNT
, SUN50I_DMIC_CNT_N
);
104 static int sun50i_dmic_hw_params(struct snd_pcm_substream
*substream
,
105 struct snd_pcm_hw_params
*params
,
106 struct snd_soc_dai
*cpu_dai
)
109 unsigned long rate
= params_rate(params
);
110 unsigned int mclk
= 0;
111 unsigned int channels
= params_channels(params
);
112 unsigned int chan_en
= (1 << channels
) - 1;
113 struct sun50i_dmic_dev
*host
= snd_soc_dai_get_drvdata(cpu_dai
);
115 /* DMIC num is N+1 */
116 regmap_update_bits(host
->regmap
, SUN50I_DMIC_CH_NUM
,
117 SUN50I_DMIC_CH_NUM_N_MASK
,
118 SUN50I_DMIC_CH_NUM_N(channels
- 1));
119 regmap_write(host
->regmap
, SUN50I_DMIC_HPF_CTRL
, chan_en
);
120 regmap_update_bits(host
->regmap
, SUN50I_DMIC_EN_CTL
,
121 SUN50I_DMIC_EN_CTL_CHAN_MASK
,
122 SUN50I_DMIC_EN_CTL_CHAN(chan_en
));
124 switch (params_format(params
)) {
125 case SNDRV_PCM_FORMAT_S16_LE
:
126 regmap_update_bits(host
->regmap
, SUN50I_DMIC_RXFIFO_CTL
,
127 SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK
,
128 SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16
);
130 case SNDRV_PCM_FORMAT_S24_LE
:
131 regmap_update_bits(host
->regmap
, SUN50I_DMIC_RXFIFO_CTL
,
132 SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK
,
133 SUN50I_DMIC_RXFIFO_CTL_SAMPLE_24
);
136 dev_err(cpu_dai
->dev
, "Invalid format!\n");
139 /* The hardware supports FIFO mode 1 for 24-bit samples */
140 regmap_update_bits(host
->regmap
, SUN50I_DMIC_RXFIFO_CTL
,
141 SUN50I_DMIC_RXFIFO_CTL_MODE_MASK
,
142 SUN50I_DMIC_RXFIFO_CTL_MODE_MSB
);
159 dev_err(cpu_dai
->dev
, "Invalid rate!\n");
163 if (clk_set_rate(host
->dmic_clk
, mclk
)) {
164 dev_err(cpu_dai
->dev
, "mclk : %u not support\n", mclk
);
168 for (i
= 0; i
< ARRAY_SIZE(dmic_rate_s
); i
++) {
169 if (dmic_rate_s
[i
].samplerate
== rate
) {
170 regmap_update_bits(host
->regmap
, SUN50I_DMIC_SR
,
171 SUN50I_DMIC_SR_SAMPLE_RATE_MASK
,
172 SUN50I_DMIC_SR_SAMPLE_RATE(dmic_rate_s
[i
].rate_bit
));
177 switch (params_physical_width(params
)) {
179 host
->dma_params_rx
.addr_width
= DMA_SLAVE_BUSWIDTH_2_BYTES
;
182 host
->dma_params_rx
.addr_width
= DMA_SLAVE_BUSWIDTH_4_BYTES
;
185 dev_err(cpu_dai
->dev
, "Unsupported physical sample width: %d\n",
186 params_physical_width(params
));
190 /* oversamplerate adjust */
191 if (params_rate(params
) >= 24000)
192 regmap_update_bits(host
->regmap
, SUN50I_DMIC_CTL
,
193 SUN50I_DMIC_CTL_OVERSAMPLE_RATE
,
194 SUN50I_DMIC_CTL_OVERSAMPLE_RATE
);
196 regmap_update_bits(host
->regmap
, SUN50I_DMIC_CTL
,
197 SUN50I_DMIC_CTL_OVERSAMPLE_RATE
, 0);
202 static int sun50i_dmic_trigger(struct snd_pcm_substream
*substream
, int cmd
,
203 struct snd_soc_dai
*dai
)
206 struct sun50i_dmic_dev
*host
= snd_soc_dai_get_drvdata(dai
);
208 if (substream
->stream
!= SNDRV_PCM_STREAM_CAPTURE
)
212 case SNDRV_PCM_TRIGGER_START
:
213 case SNDRV_PCM_TRIGGER_RESUME
:
214 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
216 regmap_update_bits(host
->regmap
, SUN50I_DMIC_INTC
,
217 SUN50I_DMIC_FIFO_DRQ_EN
,
218 SUN50I_DMIC_FIFO_DRQ_EN
);
220 regmap_update_bits(host
->regmap
, SUN50I_DMIC_EN_CTL
,
221 SUN50I_DMIC_EN_CTL_GLOBE
,
222 SUN50I_DMIC_EN_CTL_GLOBE
);
224 case SNDRV_PCM_TRIGGER_STOP
:
225 case SNDRV_PCM_TRIGGER_SUSPEND
:
226 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
228 regmap_update_bits(host
->regmap
, SUN50I_DMIC_INTC
,
229 SUN50I_DMIC_FIFO_DRQ_EN
, 0);
231 regmap_update_bits(host
->regmap
, SUN50I_DMIC_EN_CTL
,
232 SUN50I_DMIC_EN_CTL_GLOBE
, 0);
241 static int sun50i_dmic_soc_dai_probe(struct snd_soc_dai
*dai
)
243 struct sun50i_dmic_dev
*host
= snd_soc_dai_get_drvdata(dai
);
245 snd_soc_dai_init_dma_data(dai
, NULL
, &host
->dma_params_rx
);
250 static const struct snd_soc_dai_ops sun50i_dmic_dai_ops
= {
251 .probe
= sun50i_dmic_soc_dai_probe
,
252 .startup
= sun50i_dmic_startup
,
253 .trigger
= sun50i_dmic_trigger
,
254 .hw_params
= sun50i_dmic_hw_params
,
257 static const struct regmap_config sun50i_dmic_regmap_config
= {
261 .max_register
= SUN50I_DMIC_VERSION
,
262 .cache_type
= REGCACHE_NONE
,
265 #define SUN50I_DMIC_RATES (SNDRV_PCM_RATE_8000_48000)
266 #define SUN50I_DMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
268 static struct snd_soc_dai_driver sun50i_dmic_dai
= {
272 .rates
= SUN50I_DMIC_RATES
,
273 .formats
= SUN50I_DMIC_FORMATS
,
276 .ops
= &sun50i_dmic_dai_ops
,
280 static const struct of_device_id sun50i_dmic_of_match
[] = {
282 .compatible
= "allwinner,sun50i-h6-dmic",
286 MODULE_DEVICE_TABLE(of
, sun50i_dmic_of_match
);
288 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(sun50i_dmic_vol_scale
, -12000, 75, 1);
290 static const struct snd_kcontrol_new sun50i_dmic_controls
[] = {
292 SOC_DOUBLE_TLV("DMIC Channel 0 Capture Volume", SUN50I_DMIC_D0D1_VOL_CTR
,
293 SUN50I_DMIC_D0D1_VOL_CTR_0L
, SUN50I_DMIC_D0D1_VOL_CTR_0R
,
294 0xFF, 0, sun50i_dmic_vol_scale
),
295 SOC_DOUBLE_TLV("DMIC Channel 1 Capture Volume", SUN50I_DMIC_D0D1_VOL_CTR
,
296 SUN50I_DMIC_D0D1_VOL_CTR_1L
, SUN50I_DMIC_D0D1_VOL_CTR_1R
,
297 0xFF, 0, sun50i_dmic_vol_scale
),
298 SOC_DOUBLE_TLV("DMIC Channel 2 Capture Volume", SUN50I_DMIC_D2D3_VOL_CTR
,
299 SUN50I_DMIC_D2D3_VOL_CTR_2L
, SUN50I_DMIC_D2D3_VOL_CTR_2R
,
300 0xFF, 0, sun50i_dmic_vol_scale
),
301 SOC_DOUBLE_TLV("DMIC Channel 3 Capture Volume", SUN50I_DMIC_D2D3_VOL_CTR
,
302 SUN50I_DMIC_D2D3_VOL_CTR_3L
, SUN50I_DMIC_D2D3_VOL_CTR_3R
,
303 0xFF, 0, sun50i_dmic_vol_scale
),
308 static const struct snd_soc_component_driver sun50i_dmic_component
= {
309 .name
= "sun50i-dmic",
310 .controls
= sun50i_dmic_controls
,
311 .num_controls
= ARRAY_SIZE(sun50i_dmic_controls
),
314 static int sun50i_dmic_runtime_suspend(struct device
*dev
)
316 struct sun50i_dmic_dev
*host
= dev_get_drvdata(dev
);
318 clk_disable_unprepare(host
->dmic_clk
);
319 clk_disable_unprepare(host
->bus_clk
);
324 static int sun50i_dmic_runtime_resume(struct device
*dev
)
326 struct sun50i_dmic_dev
*host
= dev_get_drvdata(dev
);
329 ret
= clk_prepare_enable(host
->dmic_clk
);
333 ret
= clk_prepare_enable(host
->bus_clk
);
335 clk_disable_unprepare(host
->dmic_clk
);
342 static int sun50i_dmic_probe(struct platform_device
*pdev
)
344 struct sun50i_dmic_dev
*host
;
345 struct resource
*res
;
349 host
= devm_kzalloc(&pdev
->dev
, sizeof(*host
), GFP_KERNEL
);
353 /* Get the addresses */
354 base
= devm_platform_get_and_ioremap_resource(pdev
, 0, &res
);
356 return dev_err_probe(&pdev
->dev
, PTR_ERR(base
),
357 "get resource failed.\n");
359 host
->regmap
= devm_regmap_init_mmio(&pdev
->dev
, base
,
360 &sun50i_dmic_regmap_config
);
363 host
->bus_clk
= devm_clk_get(&pdev
->dev
, "bus");
364 if (IS_ERR(host
->bus_clk
))
365 return dev_err_probe(&pdev
->dev
, PTR_ERR(host
->bus_clk
),
366 "failed to get bus clock.\n");
368 host
->dmic_clk
= devm_clk_get(&pdev
->dev
, "mod");
369 if (IS_ERR(host
->dmic_clk
))
370 return dev_err_probe(&pdev
->dev
, PTR_ERR(host
->dmic_clk
),
371 "failed to get dmic clock.\n");
373 host
->dma_params_rx
.addr
= res
->start
+ SUN50I_DMIC_DATA
;
374 host
->dma_params_rx
.maxburst
= 8;
376 platform_set_drvdata(pdev
, host
);
378 host
->rst
= devm_reset_control_get_optional_exclusive(&pdev
->dev
, NULL
);
379 if (IS_ERR(host
->rst
))
380 return dev_err_probe(&pdev
->dev
, PTR_ERR(host
->rst
),
381 "Failed to get reset.\n");
382 reset_control_deassert(host
->rst
);
384 ret
= devm_snd_soc_register_component(&pdev
->dev
, &sun50i_dmic_component
,
385 &sun50i_dmic_dai
, 1);
387 return dev_err_probe(&pdev
->dev
, ret
,
388 "failed to register component.\n");
390 pm_runtime_enable(&pdev
->dev
);
391 if (!pm_runtime_enabled(&pdev
->dev
)) {
392 ret
= sun50i_dmic_runtime_resume(&pdev
->dev
);
394 goto err_disable_runtime_pm
;
397 ret
= devm_snd_dmaengine_pcm_register(&pdev
->dev
, NULL
, 0);
403 if (!pm_runtime_status_suspended(&pdev
->dev
))
404 sun50i_dmic_runtime_suspend(&pdev
->dev
);
405 err_disable_runtime_pm
:
406 pm_runtime_disable(&pdev
->dev
);
410 static void sun50i_dmic_remove(struct platform_device
*pdev
)
412 pm_runtime_disable(&pdev
->dev
);
413 if (!pm_runtime_status_suspended(&pdev
->dev
))
414 sun50i_dmic_runtime_suspend(&pdev
->dev
);
417 static const struct dev_pm_ops sun50i_dmic_pm
= {
418 SET_RUNTIME_PM_OPS(sun50i_dmic_runtime_suspend
,
419 sun50i_dmic_runtime_resume
, NULL
)
422 static struct platform_driver sun50i_dmic_driver
= {
424 .name
= "sun50i-dmic",
425 .of_match_table
= sun50i_dmic_of_match
,
426 .pm
= &sun50i_dmic_pm
,
428 .probe
= sun50i_dmic_probe
,
429 .remove
= sun50i_dmic_remove
,
432 module_platform_driver(sun50i_dmic_driver
);
434 MODULE_DESCRIPTION("Allwinner sun50i DMIC SoC Interface");
435 MODULE_AUTHOR("Ban Tao <fengzheng923@gmail.com>");
436 MODULE_LICENSE("GPL");
437 MODULE_ALIAS("platform:sun50i-dmic");