xref: /linux/sound/soc/sunxi/sun50i-dmic.c (revision d2c9a99135da931377240942d44f3dea104cedb8)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 //
3 // This driver supports the DMIC in Allwinner's H6 SoCs.
4 //
5 // Copyright 2021 Ban Tao <fengzheng923@gmail.com>
6 
7 #include <linux/clk.h>
8 #include <linux/device.h>
9 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/reset.h>
13 #include <sound/dmaengine_pcm.h>
14 #include <sound/pcm_params.h>
15 #include <sound/soc.h>
16 #include <sound/tlv.h>
17 
18 #define SUN50I_DMIC_EN_CTL			(0x00)
19 	#define SUN50I_DMIC_EN_CTL_GLOBE			BIT(8)
20 	#define SUN50I_DMIC_EN_CTL_CHAN(v)			((v) << 0)
21 	#define SUN50I_DMIC_EN_CTL_CHAN_MASK			GENMASK(7, 0)
22 #define SUN50I_DMIC_SR				(0x04)
23 	#define SUN50I_DMIC_SR_SAMPLE_RATE(v)			((v) << 0)
24 	#define SUN50I_DMIC_SR_SAMPLE_RATE_MASK			GENMASK(2, 0)
25 #define SUN50I_DMIC_CTL				(0x08)
26 	#define SUN50I_DMIC_CTL_OVERSAMPLE_RATE			BIT(0)
27 #define SUN50I_DMIC_DATA			(0x10)
28 #define SUN50I_DMIC_INTC			(0x14)
29 	#define SUN50I_DMIC_FIFO_DRQ_EN				BIT(2)
30 #define SUN50I_DMIC_INT_STA			(0x18)
31 	#define SUN50I_DMIC_INT_STA_OVERRUN_IRQ_PENDING		BIT(1)
32 	#define SUN50I_DMIC_INT_STA_DATA_IRQ_PENDING		BIT(0)
33 #define SUN50I_DMIC_RXFIFO_CTL			(0x1c)
34 	#define SUN50I_DMIC_RXFIFO_CTL_FLUSH			BIT(31)
35 	#define SUN50I_DMIC_RXFIFO_CTL_MODE_MASK		BIT(9)
36 	#define SUN50I_DMIC_RXFIFO_CTL_MODE_LSB			(0 << 9)
37 	#define SUN50I_DMIC_RXFIFO_CTL_MODE_MSB			(1 << 9)
38 	#define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK		BIT(8)
39 	#define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16		(0 << 8)
40 	#define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_24		(1 << 8)
41 #define SUN50I_DMIC_CH_NUM			(0x24)
42 	#define SUN50I_DMIC_CH_NUM_N(v)				((v) << 0)
43 	#define SUN50I_DMIC_CH_NUM_N_MASK			GENMASK(2, 0)
44 #define SUN50I_DMIC_CNT				(0x2c)
45 	#define SUN50I_DMIC_CNT_N				(1 << 0)
46 #define SUN50I_DMIC_D0D1_VOL_CTR		(0x30)
47 	#define SUN50I_DMIC_D0D1_VOL_CTR_0R			(0)
48 	#define SUN50I_DMIC_D0D1_VOL_CTR_0L			(8)
49 	#define SUN50I_DMIC_D0D1_VOL_CTR_1R			(16)
50 	#define SUN50I_DMIC_D0D1_VOL_CTR_1L			(24)
51 #define SUN50I_DMIC_D2D3_VOL_CTR                (0x34)
52         #define SUN50I_DMIC_D2D3_VOL_CTR_2R                     (0)
53         #define SUN50I_DMIC_D2D3_VOL_CTR_2L                     (8)
54         #define SUN50I_DMIC_D2D3_VOL_CTR_3R                     (16)
55         #define SUN50I_DMIC_D2D3_VOL_CTR_3L                     (24)
56 
57 #define SUN50I_DMIC_HPF_CTRL			(0x38)
58 #define SUN50I_DMIC_VERSION			(0x50)
59 
60 struct sun50i_dmic_dev {
61 	struct clk *dmic_clk;
62 	struct clk *bus_clk;
63 	struct reset_control *rst;
64 	struct regmap *regmap;
65 	struct snd_dmaengine_dai_dma_data dma_params_rx;
66 };
67 
68 struct dmic_rate {
69 	unsigned int samplerate;
70 	unsigned int rate_bit;
71 };
72 
73 static const struct dmic_rate dmic_rate_s[] = {
74 	{48000, 0x0},
75 	{44100, 0x0},
76 	{32000, 0x1},
77 	{24000, 0x2},
78 	{22050, 0x2},
79 	{16000, 0x3},
80 	{12000, 0x4},
81 	{11025, 0x4},
82 	{8000,  0x5},
83 };
84 
sun50i_dmic_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * cpu_dai)85 static int sun50i_dmic_startup(struct snd_pcm_substream *substream,
86 			       struct snd_soc_dai *cpu_dai)
87 {
88 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
89 	struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0));
90 
91 	/* only support capture */
92 	if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
93 		return -EINVAL;
94 
95 	regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL,
96 			SUN50I_DMIC_RXFIFO_CTL_FLUSH,
97 			SUN50I_DMIC_RXFIFO_CTL_FLUSH);
98 	regmap_write(host->regmap, SUN50I_DMIC_CNT, SUN50I_DMIC_CNT_N);
99 
100 	return 0;
101 }
102 
sun50i_dmic_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * cpu_dai)103 static int sun50i_dmic_hw_params(struct snd_pcm_substream *substream,
104 				 struct snd_pcm_hw_params *params,
105 				 struct snd_soc_dai *cpu_dai)
106 {
107 	int i = 0;
108 	unsigned long rate = params_rate(params);
109 	unsigned int mclk = 0;
110 	unsigned int channels = params_channels(params);
111 	unsigned int chan_en = (1 << channels) - 1;
112 	struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
113 
114 	/* DMIC num is N+1 */
115 	regmap_update_bits(host->regmap, SUN50I_DMIC_CH_NUM,
116 			   SUN50I_DMIC_CH_NUM_N_MASK,
117 			   SUN50I_DMIC_CH_NUM_N(channels - 1));
118 	regmap_write(host->regmap, SUN50I_DMIC_HPF_CTRL, chan_en);
119 	regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL,
120 			   SUN50I_DMIC_EN_CTL_CHAN_MASK,
121 			   SUN50I_DMIC_EN_CTL_CHAN(chan_en));
122 
123 	switch (params_format(params)) {
124 	case SNDRV_PCM_FORMAT_S16_LE:
125 		regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL,
126 				   SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK,
127 				   SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16);
128 		break;
129 	case SNDRV_PCM_FORMAT_S24_LE:
130 		regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL,
131 				   SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK,
132 				   SUN50I_DMIC_RXFIFO_CTL_SAMPLE_24);
133 		break;
134 	default:
135 		dev_err(cpu_dai->dev, "Invalid format!\n");
136 		return -EINVAL;
137 	}
138 	/* The hardware supports FIFO mode 1 for 24-bit samples */
139 	regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL,
140 			   SUN50I_DMIC_RXFIFO_CTL_MODE_MASK,
141 			   SUN50I_DMIC_RXFIFO_CTL_MODE_MSB);
142 
143 	switch (rate) {
144 	case 11025:
145 	case 22050:
146 	case 44100:
147 		mclk = 22579200;
148 		break;
149 	case 8000:
150 	case 12000:
151 	case 16000:
152 	case 24000:
153 	case 32000:
154 	case 48000:
155 		mclk = 24576000;
156 		break;
157 	default:
158 		dev_err(cpu_dai->dev, "Invalid rate!\n");
159 		return -EINVAL;
160 	}
161 
162 	if (clk_set_rate(host->dmic_clk, mclk)) {
163 		dev_err(cpu_dai->dev, "mclk : %u not support\n", mclk);
164 		return -EINVAL;
165 	}
166 
167 	for (i = 0; i < ARRAY_SIZE(dmic_rate_s); i++) {
168 		if (dmic_rate_s[i].samplerate == rate) {
169 			regmap_update_bits(host->regmap, SUN50I_DMIC_SR,
170 					   SUN50I_DMIC_SR_SAMPLE_RATE_MASK,
171 					   SUN50I_DMIC_SR_SAMPLE_RATE(dmic_rate_s[i].rate_bit));
172 			break;
173 		}
174 	}
175 
176 	switch (params_physical_width(params)) {
177 	case 16:
178 		host->dma_params_rx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
179 		break;
180 	case 32:
181 		host->dma_params_rx.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
182 		break;
183 	default:
184 		dev_err(cpu_dai->dev, "Unsupported physical sample width: %d\n",
185 			params_physical_width(params));
186 		return -EINVAL;
187 	}
188 
189 	/* oversamplerate adjust */
190 	if (params_rate(params) >= 24000)
191 		regmap_update_bits(host->regmap, SUN50I_DMIC_CTL,
192 				   SUN50I_DMIC_CTL_OVERSAMPLE_RATE,
193 				   SUN50I_DMIC_CTL_OVERSAMPLE_RATE);
194 	else
195 		regmap_update_bits(host->regmap, SUN50I_DMIC_CTL,
196 				   SUN50I_DMIC_CTL_OVERSAMPLE_RATE, 0);
197 
198 	return 0;
199 }
200 
sun50i_dmic_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)201 static int sun50i_dmic_trigger(struct snd_pcm_substream *substream, int cmd,
202 			       struct snd_soc_dai *dai)
203 {
204 	int ret = 0;
205 	struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(dai);
206 
207 	if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
208 		return -EINVAL;
209 
210 	switch (cmd) {
211 	case SNDRV_PCM_TRIGGER_START:
212 	case SNDRV_PCM_TRIGGER_RESUME:
213 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
214 		/* DRQ ENABLE */
215 		regmap_update_bits(host->regmap, SUN50I_DMIC_INTC,
216 				   SUN50I_DMIC_FIFO_DRQ_EN,
217 				   SUN50I_DMIC_FIFO_DRQ_EN);
218 		/* Global enable */
219 		regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL,
220 				   SUN50I_DMIC_EN_CTL_GLOBE,
221 				   SUN50I_DMIC_EN_CTL_GLOBE);
222 		break;
223 	case SNDRV_PCM_TRIGGER_STOP:
224 	case SNDRV_PCM_TRIGGER_SUSPEND:
225 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
226 		/* DRQ DISABLE */
227 		regmap_update_bits(host->regmap, SUN50I_DMIC_INTC,
228 				   SUN50I_DMIC_FIFO_DRQ_EN, 0);
229 		/* Global disable */
230 		regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL,
231 				   SUN50I_DMIC_EN_CTL_GLOBE, 0);
232 		break;
233 	default:
234 		ret = -EINVAL;
235 		break;
236 	}
237 	return ret;
238 }
239 
sun50i_dmic_soc_dai_probe(struct snd_soc_dai * dai)240 static int sun50i_dmic_soc_dai_probe(struct snd_soc_dai *dai)
241 {
242 	struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(dai);
243 
244 	snd_soc_dai_init_dma_data(dai, NULL, &host->dma_params_rx);
245 
246 	return 0;
247 }
248 
249 static const struct snd_soc_dai_ops sun50i_dmic_dai_ops = {
250 	.probe		= sun50i_dmic_soc_dai_probe,
251 	.startup        = sun50i_dmic_startup,
252 	.trigger        = sun50i_dmic_trigger,
253 	.hw_params      = sun50i_dmic_hw_params,
254 };
255 
256 static const struct regmap_config sun50i_dmic_regmap_config = {
257 	.reg_bits = 32,
258 	.reg_stride = 4,
259 	.val_bits = 32,
260 	.max_register = SUN50I_DMIC_VERSION,
261 	.cache_type = REGCACHE_NONE,
262 };
263 
264 #define SUN50I_DMIC_RATES (SNDRV_PCM_RATE_8000_48000)
265 #define SUN50I_DMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
266 
267 static struct snd_soc_dai_driver sun50i_dmic_dai = {
268 	.capture = {
269 		.channels_min = 1,
270 		.channels_max = 8,
271 		.rates = SUN50I_DMIC_RATES,
272 		.formats = SUN50I_DMIC_FORMATS,
273 		.sig_bits = 21,
274 	},
275 	.ops = &sun50i_dmic_dai_ops,
276 	.name = "dmic",
277 };
278 
279 static const struct of_device_id sun50i_dmic_of_match[] = {
280 	{
281 		.compatible = "allwinner,sun50i-h6-dmic",
282 	},
283 	{ /* sentinel */ }
284 };
285 MODULE_DEVICE_TABLE(of, sun50i_dmic_of_match);
286 
287 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(sun50i_dmic_vol_scale, -12000, 75, 1);
288 
289 static const struct snd_kcontrol_new sun50i_dmic_controls[] = {
290 
291         SOC_DOUBLE_TLV("DMIC Channel 0 Capture Volume", SUN50I_DMIC_D0D1_VOL_CTR,
292                        SUN50I_DMIC_D0D1_VOL_CTR_0L, SUN50I_DMIC_D0D1_VOL_CTR_0R,
293                        0xFF, 0, sun50i_dmic_vol_scale),
294         SOC_DOUBLE_TLV("DMIC Channel 1 Capture Volume", SUN50I_DMIC_D0D1_VOL_CTR,
295                        SUN50I_DMIC_D0D1_VOL_CTR_1L, SUN50I_DMIC_D0D1_VOL_CTR_1R,
296                        0xFF, 0, sun50i_dmic_vol_scale),
297         SOC_DOUBLE_TLV("DMIC Channel 2 Capture Volume", SUN50I_DMIC_D2D3_VOL_CTR,
298                        SUN50I_DMIC_D2D3_VOL_CTR_2L, SUN50I_DMIC_D2D3_VOL_CTR_2R,
299                        0xFF, 0, sun50i_dmic_vol_scale),
300         SOC_DOUBLE_TLV("DMIC Channel 3 Capture Volume", SUN50I_DMIC_D2D3_VOL_CTR,
301                        SUN50I_DMIC_D2D3_VOL_CTR_3L, SUN50I_DMIC_D2D3_VOL_CTR_3R,
302                        0xFF, 0, sun50i_dmic_vol_scale),
303 
304 
305 };
306 
307 static const struct snd_soc_component_driver sun50i_dmic_component = {
308 	.name           = "sun50i-dmic",
309 	.controls	= sun50i_dmic_controls,
310 	.num_controls	= ARRAY_SIZE(sun50i_dmic_controls),
311 };
312 
sun50i_dmic_runtime_suspend(struct device * dev)313 static int sun50i_dmic_runtime_suspend(struct device *dev)
314 {
315 	struct sun50i_dmic_dev *host  = dev_get_drvdata(dev);
316 
317 	clk_disable_unprepare(host->dmic_clk);
318 	clk_disable_unprepare(host->bus_clk);
319 
320 	return 0;
321 }
322 
sun50i_dmic_runtime_resume(struct device * dev)323 static int sun50i_dmic_runtime_resume(struct device *dev)
324 {
325 	struct sun50i_dmic_dev *host  = dev_get_drvdata(dev);
326 	int ret;
327 
328 	ret = clk_prepare_enable(host->dmic_clk);
329 	if (ret)
330 		return ret;
331 
332 	ret = clk_prepare_enable(host->bus_clk);
333 	if (ret) {
334 		clk_disable_unprepare(host->dmic_clk);
335 		return ret;
336 	}
337 
338 	return 0;
339 }
340 
sun50i_dmic_probe(struct platform_device * pdev)341 static int sun50i_dmic_probe(struct platform_device *pdev)
342 {
343 	struct sun50i_dmic_dev *host;
344 	struct resource *res;
345 	int ret;
346 	void __iomem *base;
347 
348 	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
349 	if (!host)
350 		return -ENOMEM;
351 
352 	/* Get the addresses */
353 	base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
354 	if (IS_ERR(base))
355 		return dev_err_probe(&pdev->dev, PTR_ERR(base),
356 				     "get resource failed.\n");
357 
358 	host->regmap = devm_regmap_init_mmio(&pdev->dev, base,
359 					     &sun50i_dmic_regmap_config);
360 	if (IS_ERR(host->regmap))
361 		return dev_err_probe(&pdev->dev, PTR_ERR(host->regmap),
362 				     "failed to initialise regmap\n");
363 
364 	/* Clocks */
365 	host->bus_clk = devm_clk_get(&pdev->dev, "bus");
366 	if (IS_ERR(host->bus_clk))
367 		return dev_err_probe(&pdev->dev, PTR_ERR(host->bus_clk),
368 				     "failed to get bus clock.\n");
369 
370 	host->dmic_clk = devm_clk_get(&pdev->dev, "mod");
371 	if (IS_ERR(host->dmic_clk))
372 		return dev_err_probe(&pdev->dev, PTR_ERR(host->dmic_clk),
373 				     "failed to get dmic clock.\n");
374 
375 	host->dma_params_rx.addr = res->start + SUN50I_DMIC_DATA;
376 	host->dma_params_rx.maxburst = 8;
377 
378 	platform_set_drvdata(pdev, host);
379 
380 	host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
381 	if (IS_ERR(host->rst))
382 		return dev_err_probe(&pdev->dev, PTR_ERR(host->rst),
383 				     "Failed to get reset.\n");
384 	reset_control_deassert(host->rst);
385 
386 	ret = devm_snd_soc_register_component(&pdev->dev, &sun50i_dmic_component,
387 					      &sun50i_dmic_dai, 1);
388 	if (ret)
389 		return dev_err_probe(&pdev->dev, ret,
390 				     "failed to register component.\n");
391 
392 	pm_runtime_enable(&pdev->dev);
393 	if (!pm_runtime_enabled(&pdev->dev)) {
394 		ret = sun50i_dmic_runtime_resume(&pdev->dev);
395 		if (ret)
396 			goto err_disable_runtime_pm;
397 	}
398 
399 	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
400 	if (ret)
401 		goto err_suspend;
402 
403 	return 0;
404 err_suspend:
405 	if (!pm_runtime_status_suspended(&pdev->dev))
406 		sun50i_dmic_runtime_suspend(&pdev->dev);
407 err_disable_runtime_pm:
408 	pm_runtime_disable(&pdev->dev);
409 	return ret;
410 }
411 
sun50i_dmic_remove(struct platform_device * pdev)412 static void sun50i_dmic_remove(struct platform_device *pdev)
413 {
414 	pm_runtime_disable(&pdev->dev);
415 	if (!pm_runtime_status_suspended(&pdev->dev))
416 		sun50i_dmic_runtime_suspend(&pdev->dev);
417 }
418 
419 static const struct dev_pm_ops sun50i_dmic_pm = {
420 	RUNTIME_PM_OPS(sun50i_dmic_runtime_suspend,
421 		       sun50i_dmic_runtime_resume, NULL)
422 };
423 
424 static struct platform_driver sun50i_dmic_driver = {
425 	.driver         = {
426 		.name   = "sun50i-dmic",
427 		.of_match_table = sun50i_dmic_of_match,
428 		.pm     = pm_ptr(&sun50i_dmic_pm),
429 	},
430 	.probe          = sun50i_dmic_probe,
431 	.remove         = sun50i_dmic_remove,
432 };
433 
434 module_platform_driver(sun50i_dmic_driver);
435 
436 MODULE_DESCRIPTION("Allwinner sun50i DMIC SoC Interface");
437 MODULE_AUTHOR("Ban Tao <fengzheng923@gmail.com>");
438 MODULE_LICENSE("GPL");
439 MODULE_ALIAS("platform:sun50i-dmic");
440