Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/rockchip/rockchip_pdm.c
26427 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Rockchip PDM ALSA SoC Digital Audio Interface(DAI) driver
4
*
5
* Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
6
*/
7
8
#include <linux/module.h>
9
#include <linux/clk.h>
10
#include <linux/of.h>
11
#include <linux/pm_runtime.h>
12
#include <linux/rational.h>
13
#include <linux/regmap.h>
14
#include <linux/reset.h>
15
#include <sound/dmaengine_pcm.h>
16
#include <sound/pcm_params.h>
17
18
#include "rockchip_pdm.h"
19
20
#define PDM_DMA_BURST_SIZE (8) /* size * width: 8*4 = 32 bytes */
21
#define PDM_SIGNOFF_CLK_RATE (100000000)
22
#define PDM_PATH_MAX (4)
23
24
enum rk_pdm_version {
25
RK_PDM_RK3229,
26
RK_PDM_RK3308,
27
RK_PDM_RV1126,
28
};
29
30
struct rk_pdm_dev {
31
struct device *dev;
32
struct clk *clk;
33
struct clk *hclk;
34
struct regmap *regmap;
35
struct snd_dmaengine_dai_dma_data capture_dma_data;
36
struct reset_control *reset;
37
enum rk_pdm_version version;
38
};
39
40
struct rk_pdm_clkref {
41
unsigned int sr;
42
unsigned int clk;
43
unsigned int clk_out;
44
};
45
46
struct rk_pdm_ds_ratio {
47
unsigned int ratio;
48
unsigned int sr;
49
};
50
51
static struct rk_pdm_clkref clkref[] = {
52
{ 8000, 40960000, 2048000 },
53
{ 11025, 56448000, 2822400 },
54
{ 12000, 61440000, 3072000 },
55
{ 8000, 98304000, 2048000 },
56
{ 12000, 98304000, 3072000 },
57
};
58
59
static struct rk_pdm_ds_ratio ds_ratio[] = {
60
{ 0, 192000 },
61
{ 0, 176400 },
62
{ 0, 128000 },
63
{ 1, 96000 },
64
{ 1, 88200 },
65
{ 1, 64000 },
66
{ 2, 48000 },
67
{ 2, 44100 },
68
{ 2, 32000 },
69
{ 3, 24000 },
70
{ 3, 22050 },
71
{ 3, 16000 },
72
{ 4, 12000 },
73
{ 4, 11025 },
74
{ 4, 8000 },
75
};
76
77
static unsigned int get_pdm_clk(struct rk_pdm_dev *pdm, unsigned int sr,
78
unsigned int *clk_src, unsigned int *clk_out)
79
{
80
unsigned int i, count, clk, div, rate;
81
82
clk = 0;
83
if (!sr)
84
return clk;
85
86
count = ARRAY_SIZE(clkref);
87
for (i = 0; i < count; i++) {
88
if (sr % clkref[i].sr)
89
continue;
90
div = sr / clkref[i].sr;
91
if ((div & (div - 1)) == 0) {
92
*clk_out = clkref[i].clk_out;
93
rate = clk_round_rate(pdm->clk, clkref[i].clk);
94
if (rate != clkref[i].clk)
95
continue;
96
clk = clkref[i].clk;
97
*clk_src = clkref[i].clk;
98
break;
99
}
100
}
101
102
if (!clk) {
103
clk = clk_round_rate(pdm->clk, PDM_SIGNOFF_CLK_RATE);
104
*clk_src = clk;
105
}
106
return clk;
107
}
108
109
static unsigned int get_pdm_ds_ratio(unsigned int sr)
110
{
111
unsigned int i, count, ratio;
112
113
ratio = 0;
114
if (!sr)
115
return ratio;
116
117
count = ARRAY_SIZE(ds_ratio);
118
for (i = 0; i < count; i++) {
119
if (sr == ds_ratio[i].sr)
120
ratio = ds_ratio[i].ratio;
121
}
122
return ratio;
123
}
124
125
static unsigned int get_pdm_cic_ratio(unsigned int clk)
126
{
127
switch (clk) {
128
case 4096000:
129
case 5644800:
130
case 6144000:
131
return 0;
132
case 2048000:
133
case 2822400:
134
case 3072000:
135
return 1;
136
case 1024000:
137
case 1411200:
138
case 1536000:
139
return 2;
140
default:
141
return 1;
142
}
143
}
144
145
static unsigned int samplerate_to_bit(unsigned int samplerate)
146
{
147
switch (samplerate) {
148
case 8000:
149
case 11025:
150
case 12000:
151
return 0;
152
case 16000:
153
case 22050:
154
case 24000:
155
return 1;
156
case 32000:
157
return 2;
158
case 44100:
159
case 48000:
160
return 3;
161
case 64000:
162
case 88200:
163
case 96000:
164
return 4;
165
case 128000:
166
case 176400:
167
case 192000:
168
return 5;
169
default:
170
return 1;
171
}
172
}
173
174
static inline struct rk_pdm_dev *to_info(struct snd_soc_dai *dai)
175
{
176
return snd_soc_dai_get_drvdata(dai);
177
}
178
179
static void rockchip_pdm_rxctrl(struct rk_pdm_dev *pdm, int on)
180
{
181
if (on) {
182
regmap_update_bits(pdm->regmap, PDM_DMA_CTRL,
183
PDM_DMA_RD_MSK, PDM_DMA_RD_EN);
184
regmap_update_bits(pdm->regmap, PDM_SYSCONFIG,
185
PDM_RX_MASK, PDM_RX_START);
186
} else {
187
regmap_update_bits(pdm->regmap, PDM_DMA_CTRL,
188
PDM_DMA_RD_MSK, PDM_DMA_RD_DIS);
189
regmap_update_bits(pdm->regmap, PDM_SYSCONFIG,
190
PDM_RX_MASK | PDM_RX_CLR_MASK,
191
PDM_RX_STOP | PDM_RX_CLR_WR);
192
}
193
}
194
195
static int rockchip_pdm_hw_params(struct snd_pcm_substream *substream,
196
struct snd_pcm_hw_params *params,
197
struct snd_soc_dai *dai)
198
{
199
struct rk_pdm_dev *pdm = to_info(dai);
200
unsigned int val = 0;
201
unsigned int clk_rate, clk_div, samplerate;
202
unsigned int clk_src, clk_out = 0;
203
unsigned long m, n;
204
bool change;
205
int ret;
206
207
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
208
return 0;
209
210
samplerate = params_rate(params);
211
clk_rate = get_pdm_clk(pdm, samplerate, &clk_src, &clk_out);
212
if (!clk_rate)
213
return -EINVAL;
214
215
ret = clk_set_rate(pdm->clk, clk_src);
216
if (ret)
217
return -EINVAL;
218
219
if (pdm->version == RK_PDM_RK3308 ||
220
pdm->version == RK_PDM_RV1126) {
221
rational_best_approximation(clk_out, clk_src,
222
GENMASK(16 - 1, 0),
223
GENMASK(16 - 1, 0),
224
&m, &n);
225
226
val = (m << PDM_FD_NUMERATOR_SFT) |
227
(n << PDM_FD_DENOMINATOR_SFT);
228
regmap_update_bits_check(pdm->regmap, PDM_CTRL1,
229
PDM_FD_NUMERATOR_MSK |
230
PDM_FD_DENOMINATOR_MSK,
231
val, &change);
232
if (change) {
233
reset_control_assert(pdm->reset);
234
reset_control_deassert(pdm->reset);
235
rockchip_pdm_rxctrl(pdm, 0);
236
}
237
clk_div = n / m;
238
if (clk_div >= 40)
239
val = PDM_CLK_FD_RATIO_40;
240
else if (clk_div <= 35)
241
val = PDM_CLK_FD_RATIO_35;
242
else
243
return -EINVAL;
244
regmap_update_bits(pdm->regmap, PDM_CLK_CTRL,
245
PDM_CLK_FD_RATIO_MSK,
246
val);
247
}
248
249
if (pdm->version == RK_PDM_RV1126) {
250
val = get_pdm_cic_ratio(clk_out);
251
regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_CIC_RATIO_MSK, val);
252
val = samplerate_to_bit(samplerate);
253
regmap_update_bits(pdm->regmap, PDM_CTRL0,
254
PDM_SAMPLERATE_MSK, PDM_SAMPLERATE(val));
255
} else {
256
val = get_pdm_ds_ratio(samplerate);
257
regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_DS_RATIO_MSK, val);
258
}
259
260
regmap_update_bits(pdm->regmap, PDM_HPF_CTRL,
261
PDM_HPF_CF_MSK, PDM_HPF_60HZ);
262
regmap_update_bits(pdm->regmap, PDM_HPF_CTRL,
263
PDM_HPF_LE | PDM_HPF_RE, PDM_HPF_LE | PDM_HPF_RE);
264
regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_CLK_EN, PDM_CLK_EN);
265
if (pdm->version != RK_PDM_RK3229)
266
regmap_update_bits(pdm->regmap, PDM_CTRL0,
267
PDM_MODE_MSK, PDM_MODE_LJ);
268
269
val = 0;
270
switch (params_format(params)) {
271
case SNDRV_PCM_FORMAT_S8:
272
val |= PDM_VDW(8);
273
break;
274
case SNDRV_PCM_FORMAT_S16_LE:
275
val |= PDM_VDW(16);
276
break;
277
case SNDRV_PCM_FORMAT_S20_3LE:
278
val |= PDM_VDW(20);
279
break;
280
case SNDRV_PCM_FORMAT_S24_LE:
281
val |= PDM_VDW(24);
282
break;
283
case SNDRV_PCM_FORMAT_S32_LE:
284
val |= PDM_VDW(32);
285
break;
286
default:
287
return -EINVAL;
288
}
289
290
switch (params_channels(params)) {
291
case 8:
292
val |= PDM_PATH3_EN;
293
fallthrough;
294
case 6:
295
val |= PDM_PATH2_EN;
296
fallthrough;
297
case 4:
298
val |= PDM_PATH1_EN;
299
fallthrough;
300
case 2:
301
val |= PDM_PATH0_EN;
302
break;
303
default:
304
dev_err(pdm->dev, "invalid channel: %d\n",
305
params_channels(params));
306
return -EINVAL;
307
}
308
309
regmap_update_bits(pdm->regmap, PDM_CTRL0,
310
PDM_PATH_MSK | PDM_VDW_MSK,
311
val);
312
/* all channels share the single FIFO */
313
regmap_update_bits(pdm->regmap, PDM_DMA_CTRL, PDM_DMA_RDL_MSK,
314
PDM_DMA_RDL(8 * params_channels(params)));
315
316
return 0;
317
}
318
319
static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai,
320
unsigned int fmt)
321
{
322
struct rk_pdm_dev *pdm = to_info(cpu_dai);
323
unsigned int mask = 0, val = 0;
324
325
mask = PDM_CKP_MSK;
326
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
327
case SND_SOC_DAIFMT_NB_NF:
328
val = PDM_CKP_NORMAL;
329
break;
330
case SND_SOC_DAIFMT_IB_NF:
331
val = PDM_CKP_INVERTED;
332
break;
333
default:
334
return -EINVAL;
335
}
336
337
pm_runtime_get_sync(cpu_dai->dev);
338
regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, mask, val);
339
pm_runtime_put(cpu_dai->dev);
340
341
return 0;
342
}
343
344
static int rockchip_pdm_trigger(struct snd_pcm_substream *substream, int cmd,
345
struct snd_soc_dai *dai)
346
{
347
struct rk_pdm_dev *pdm = to_info(dai);
348
int ret = 0;
349
350
switch (cmd) {
351
case SNDRV_PCM_TRIGGER_START:
352
case SNDRV_PCM_TRIGGER_RESUME:
353
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
354
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
355
rockchip_pdm_rxctrl(pdm, 1);
356
break;
357
case SNDRV_PCM_TRIGGER_SUSPEND:
358
case SNDRV_PCM_TRIGGER_STOP:
359
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
360
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
361
rockchip_pdm_rxctrl(pdm, 0);
362
break;
363
default:
364
ret = -EINVAL;
365
break;
366
}
367
368
return ret;
369
}
370
371
static int rockchip_pdm_dai_probe(struct snd_soc_dai *dai)
372
{
373
struct rk_pdm_dev *pdm = to_info(dai);
374
375
snd_soc_dai_dma_data_set_capture(dai, &pdm->capture_dma_data);
376
377
return 0;
378
}
379
380
static const struct snd_soc_dai_ops rockchip_pdm_dai_ops = {
381
.probe = rockchip_pdm_dai_probe,
382
.set_fmt = rockchip_pdm_set_fmt,
383
.trigger = rockchip_pdm_trigger,
384
.hw_params = rockchip_pdm_hw_params,
385
};
386
387
#define ROCKCHIP_PDM_RATES SNDRV_PCM_RATE_8000_192000
388
#define ROCKCHIP_PDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
389
SNDRV_PCM_FMTBIT_S20_3LE | \
390
SNDRV_PCM_FMTBIT_S24_LE | \
391
SNDRV_PCM_FMTBIT_S32_LE)
392
393
static struct snd_soc_dai_driver rockchip_pdm_dai = {
394
.capture = {
395
.stream_name = "Capture",
396
.channels_min = 2,
397
.channels_max = 8,
398
.rates = ROCKCHIP_PDM_RATES,
399
.formats = ROCKCHIP_PDM_FORMATS,
400
},
401
.ops = &rockchip_pdm_dai_ops,
402
.symmetric_rate = 1,
403
};
404
405
static const struct snd_soc_component_driver rockchip_pdm_component = {
406
.name = "rockchip-pdm",
407
.legacy_dai_naming = 1,
408
};
409
410
static int rockchip_pdm_runtime_suspend(struct device *dev)
411
{
412
struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
413
414
clk_disable_unprepare(pdm->clk);
415
clk_disable_unprepare(pdm->hclk);
416
417
return 0;
418
}
419
420
static int rockchip_pdm_runtime_resume(struct device *dev)
421
{
422
struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
423
int ret;
424
425
ret = clk_prepare_enable(pdm->clk);
426
if (ret) {
427
dev_err(pdm->dev, "clock enable failed %d\n", ret);
428
return ret;
429
}
430
431
ret = clk_prepare_enable(pdm->hclk);
432
if (ret) {
433
clk_disable_unprepare(pdm->clk);
434
dev_err(pdm->dev, "hclock enable failed %d\n", ret);
435
return ret;
436
}
437
438
return 0;
439
}
440
441
static bool rockchip_pdm_wr_reg(struct device *dev, unsigned int reg)
442
{
443
switch (reg) {
444
case PDM_SYSCONFIG:
445
case PDM_CTRL0:
446
case PDM_CTRL1:
447
case PDM_CLK_CTRL:
448
case PDM_HPF_CTRL:
449
case PDM_FIFO_CTRL:
450
case PDM_DMA_CTRL:
451
case PDM_INT_EN:
452
case PDM_INT_CLR:
453
case PDM_DATA_VALID:
454
return true;
455
default:
456
return false;
457
}
458
}
459
460
static bool rockchip_pdm_rd_reg(struct device *dev, unsigned int reg)
461
{
462
switch (reg) {
463
case PDM_SYSCONFIG:
464
case PDM_CTRL0:
465
case PDM_CTRL1:
466
case PDM_CLK_CTRL:
467
case PDM_HPF_CTRL:
468
case PDM_FIFO_CTRL:
469
case PDM_DMA_CTRL:
470
case PDM_INT_EN:
471
case PDM_INT_CLR:
472
case PDM_INT_ST:
473
case PDM_DATA_VALID:
474
case PDM_RXFIFO_DATA:
475
case PDM_VERSION:
476
return true;
477
default:
478
return false;
479
}
480
}
481
482
static bool rockchip_pdm_volatile_reg(struct device *dev, unsigned int reg)
483
{
484
switch (reg) {
485
case PDM_SYSCONFIG:
486
case PDM_FIFO_CTRL:
487
case PDM_INT_CLR:
488
case PDM_INT_ST:
489
case PDM_RXFIFO_DATA:
490
return true;
491
default:
492
return false;
493
}
494
}
495
496
static bool rockchip_pdm_precious_reg(struct device *dev, unsigned int reg)
497
{
498
switch (reg) {
499
case PDM_RXFIFO_DATA:
500
return true;
501
default:
502
return false;
503
}
504
}
505
506
static const struct reg_default rockchip_pdm_reg_defaults[] = {
507
{ PDM_CTRL0, 0x78000017 },
508
{ PDM_CTRL1, 0x0bb8ea60 },
509
{ PDM_CLK_CTRL, 0x0000e401 },
510
{ PDM_DMA_CTRL, 0x0000001f },
511
};
512
513
static const struct regmap_config rockchip_pdm_regmap_config = {
514
.reg_bits = 32,
515
.reg_stride = 4,
516
.val_bits = 32,
517
.max_register = PDM_VERSION,
518
.reg_defaults = rockchip_pdm_reg_defaults,
519
.num_reg_defaults = ARRAY_SIZE(rockchip_pdm_reg_defaults),
520
.writeable_reg = rockchip_pdm_wr_reg,
521
.readable_reg = rockchip_pdm_rd_reg,
522
.volatile_reg = rockchip_pdm_volatile_reg,
523
.precious_reg = rockchip_pdm_precious_reg,
524
.cache_type = REGCACHE_FLAT,
525
};
526
527
static const struct of_device_id rockchip_pdm_match[] __maybe_unused = {
528
{ .compatible = "rockchip,pdm",
529
.data = (void *)RK_PDM_RK3229 },
530
{ .compatible = "rockchip,px30-pdm",
531
.data = (void *)RK_PDM_RK3308 },
532
{ .compatible = "rockchip,rk1808-pdm",
533
.data = (void *)RK_PDM_RK3308 },
534
{ .compatible = "rockchip,rk3308-pdm",
535
.data = (void *)RK_PDM_RK3308 },
536
{ .compatible = "rockchip,rk3568-pdm",
537
.data = (void *)RK_PDM_RV1126 },
538
{ .compatible = "rockchip,rv1126-pdm",
539
.data = (void *)RK_PDM_RV1126 },
540
{},
541
};
542
MODULE_DEVICE_TABLE(of, rockchip_pdm_match);
543
544
static int rockchip_pdm_path_parse(struct rk_pdm_dev *pdm, struct device_node *node)
545
{
546
unsigned int path[PDM_PATH_MAX];
547
int cnt = 0, ret = 0, i = 0, val = 0, msk = 0;
548
549
cnt = of_count_phandle_with_args(node, "rockchip,path-map",
550
NULL);
551
if (cnt != PDM_PATH_MAX)
552
return cnt;
553
554
ret = of_property_read_u32_array(node, "rockchip,path-map",
555
path, cnt);
556
if (ret)
557
return ret;
558
559
for (i = 0; i < cnt; i++) {
560
if (path[i] >= PDM_PATH_MAX)
561
return -EINVAL;
562
msk |= PDM_PATH_MASK(i);
563
val |= PDM_PATH(i, path[i]);
564
}
565
566
regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, msk, val);
567
568
return 0;
569
}
570
571
static int rockchip_pdm_probe(struct platform_device *pdev)
572
{
573
struct device_node *node = pdev->dev.of_node;
574
struct rk_pdm_dev *pdm;
575
struct resource *res;
576
void __iomem *regs;
577
int ret;
578
579
pdm = devm_kzalloc(&pdev->dev, sizeof(*pdm), GFP_KERNEL);
580
if (!pdm)
581
return -ENOMEM;
582
583
pdm->version = (enum rk_pdm_version)device_get_match_data(&pdev->dev);
584
if (pdm->version == RK_PDM_RK3308) {
585
pdm->reset = devm_reset_control_get(&pdev->dev, "pdm-m");
586
if (IS_ERR(pdm->reset))
587
return PTR_ERR(pdm->reset);
588
}
589
590
regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
591
if (IS_ERR(regs))
592
return PTR_ERR(regs);
593
594
pdm->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
595
&rockchip_pdm_regmap_config);
596
if (IS_ERR(pdm->regmap))
597
return PTR_ERR(pdm->regmap);
598
599
pdm->capture_dma_data.addr = res->start + PDM_RXFIFO_DATA;
600
pdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
601
pdm->capture_dma_data.maxburst = PDM_DMA_BURST_SIZE;
602
603
pdm->dev = &pdev->dev;
604
dev_set_drvdata(&pdev->dev, pdm);
605
606
pdm->clk = devm_clk_get(&pdev->dev, "pdm_clk");
607
if (IS_ERR(pdm->clk))
608
return PTR_ERR(pdm->clk);
609
610
pdm->hclk = devm_clk_get(&pdev->dev, "pdm_hclk");
611
if (IS_ERR(pdm->hclk))
612
return PTR_ERR(pdm->hclk);
613
614
ret = clk_prepare_enable(pdm->hclk);
615
if (ret)
616
return ret;
617
618
pm_runtime_enable(&pdev->dev);
619
if (!pm_runtime_enabled(&pdev->dev)) {
620
ret = rockchip_pdm_runtime_resume(&pdev->dev);
621
if (ret)
622
goto err_pm_disable;
623
}
624
625
ret = devm_snd_soc_register_component(&pdev->dev,
626
&rockchip_pdm_component,
627
&rockchip_pdm_dai, 1);
628
629
if (ret) {
630
dev_err(&pdev->dev, "could not register dai: %d\n", ret);
631
goto err_suspend;
632
}
633
634
rockchip_pdm_rxctrl(pdm, 0);
635
636
ret = rockchip_pdm_path_parse(pdm, node);
637
if (ret != 0 && ret != -ENOENT)
638
goto err_suspend;
639
640
ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
641
if (ret) {
642
dev_err(&pdev->dev, "could not register pcm: %d\n", ret);
643
goto err_suspend;
644
}
645
646
return 0;
647
648
err_suspend:
649
if (!pm_runtime_status_suspended(&pdev->dev))
650
rockchip_pdm_runtime_suspend(&pdev->dev);
651
err_pm_disable:
652
pm_runtime_disable(&pdev->dev);
653
654
clk_disable_unprepare(pdm->hclk);
655
656
return ret;
657
}
658
659
static void rockchip_pdm_remove(struct platform_device *pdev)
660
{
661
struct rk_pdm_dev *pdm = dev_get_drvdata(&pdev->dev);
662
663
pm_runtime_disable(&pdev->dev);
664
if (!pm_runtime_status_suspended(&pdev->dev))
665
rockchip_pdm_runtime_suspend(&pdev->dev);
666
667
clk_disable_unprepare(pdm->clk);
668
clk_disable_unprepare(pdm->hclk);
669
}
670
671
static int rockchip_pdm_suspend(struct device *dev)
672
{
673
struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
674
675
regcache_mark_dirty(pdm->regmap);
676
677
return 0;
678
}
679
680
static int rockchip_pdm_resume(struct device *dev)
681
{
682
struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
683
int ret;
684
685
ret = pm_runtime_resume_and_get(dev);
686
if (ret < 0)
687
return ret;
688
689
ret = regcache_sync(pdm->regmap);
690
691
pm_runtime_put(dev);
692
693
return ret;
694
}
695
696
static const struct dev_pm_ops rockchip_pdm_pm_ops = {
697
RUNTIME_PM_OPS(rockchip_pdm_runtime_suspend,
698
rockchip_pdm_runtime_resume, NULL)
699
SYSTEM_SLEEP_PM_OPS(rockchip_pdm_suspend, rockchip_pdm_resume)
700
};
701
702
static struct platform_driver rockchip_pdm_driver = {
703
.probe = rockchip_pdm_probe,
704
.remove = rockchip_pdm_remove,
705
.driver = {
706
.name = "rockchip-pdm",
707
.of_match_table = of_match_ptr(rockchip_pdm_match),
708
.pm = pm_ptr(&rockchip_pdm_pm_ops),
709
},
710
};
711
712
module_platform_driver(rockchip_pdm_driver);
713
714
MODULE_AUTHOR("Sugar <[email protected]>");
715
MODULE_DESCRIPTION("Rockchip PDM Controller Driver");
716
MODULE_LICENSE("GPL v2");
717
718