root/sound/soc/rockchip/rockchip_pdm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_pdm_clk
  2. get_pdm_ds_ratio
  3. to_info
  4. rockchip_pdm_rxctrl
  5. rockchip_pdm_hw_params
  6. rockchip_pdm_set_fmt
  7. rockchip_pdm_trigger
  8. rockchip_pdm_dai_probe
  9. rockchip_pdm_runtime_suspend
  10. rockchip_pdm_runtime_resume
  11. rockchip_pdm_wr_reg
  12. rockchip_pdm_rd_reg
  13. rockchip_pdm_volatile_reg
  14. rockchip_pdm_precious_reg
  15. rockchip_pdm_probe
  16. rockchip_pdm_remove
  17. rockchip_pdm_suspend
  18. rockchip_pdm_resume

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

/* [<][>][^][v][top][bottom][index][help] */