cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rockchip_pdm.c (16124B)


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