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 24enum rk_pdm_version { 25 RK_PDM_RK3229, 26 RK_PDM_RK3308, 27}; 28 29struct 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 39struct rk_pdm_clkref { 40 unsigned int sr; 41 unsigned int clk; 42 unsigned int clk_out; 43}; 44 45struct rk_pdm_ds_ratio { 46 unsigned int ratio; 47 unsigned int sr; 48}; 49 50static 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 58static 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 76static 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 108static 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 124static inline struct rk_pdm_dev *to_info(struct snd_soc_dai *dai) 125{ 126 return snd_soc_dai_get_drvdata(dai); 127} 128 129static 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 145static 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 258static 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 283static 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 310static 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 319static 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 331static 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 344static const struct snd_soc_component_driver rockchip_pdm_component = { 345 .name = "rockchip-pdm", 346}; 347 348static 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 358static 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 clk_disable_unprepare(pdm->clk); 372 dev_err(pdm->dev, "hclock enable failed %d\n", ret); 373 return ret; 374 } 375 376 return 0; 377} 378 379static bool rockchip_pdm_wr_reg(struct device *dev, unsigned int reg) 380{ 381 switch (reg) { 382 case PDM_SYSCONFIG: 383 case PDM_CTRL0: 384 case PDM_CTRL1: 385 case PDM_CLK_CTRL: 386 case PDM_HPF_CTRL: 387 case PDM_FIFO_CTRL: 388 case PDM_DMA_CTRL: 389 case PDM_INT_EN: 390 case PDM_INT_CLR: 391 case PDM_DATA_VALID: 392 return true; 393 default: 394 return false; 395 } 396} 397 398static bool rockchip_pdm_rd_reg(struct device *dev, unsigned int reg) 399{ 400 switch (reg) { 401 case PDM_SYSCONFIG: 402 case PDM_CTRL0: 403 case PDM_CTRL1: 404 case PDM_CLK_CTRL: 405 case PDM_HPF_CTRL: 406 case PDM_FIFO_CTRL: 407 case PDM_DMA_CTRL: 408 case PDM_INT_EN: 409 case PDM_INT_CLR: 410 case PDM_INT_ST: 411 case PDM_DATA_VALID: 412 case PDM_RXFIFO_DATA: 413 case PDM_VERSION: 414 return true; 415 default: 416 return false; 417 } 418} 419 420static bool rockchip_pdm_volatile_reg(struct device *dev, unsigned int reg) 421{ 422 switch (reg) { 423 case PDM_SYSCONFIG: 424 case PDM_FIFO_CTRL: 425 case PDM_INT_CLR: 426 case PDM_INT_ST: 427 case PDM_RXFIFO_DATA: 428 return true; 429 default: 430 return false; 431 } 432} 433 434static bool rockchip_pdm_precious_reg(struct device *dev, unsigned int reg) 435{ 436 switch (reg) { 437 case PDM_RXFIFO_DATA: 438 return true; 439 default: 440 return false; 441 } 442} 443 444static const struct reg_default rockchip_pdm_reg_defaults[] = { 445 {0x04, 0x78000017}, 446 {0x08, 0x0bb8ea60}, 447 {0x18, 0x0000001f}, 448}; 449 450static const struct regmap_config rockchip_pdm_regmap_config = { 451 .reg_bits = 32, 452 .reg_stride = 4, 453 .val_bits = 32, 454 .max_register = PDM_VERSION, 455 .reg_defaults = rockchip_pdm_reg_defaults, 456 .num_reg_defaults = ARRAY_SIZE(rockchip_pdm_reg_defaults), 457 .writeable_reg = rockchip_pdm_wr_reg, 458 .readable_reg = rockchip_pdm_rd_reg, 459 .volatile_reg = rockchip_pdm_volatile_reg, 460 .precious_reg = rockchip_pdm_precious_reg, 461 .cache_type = REGCACHE_FLAT, 462}; 463 464static const struct of_device_id rockchip_pdm_match[] = { 465 { .compatible = "rockchip,pdm", 466 .data = (void *)RK_PDM_RK3229 }, 467 { .compatible = "rockchip,px30-pdm", 468 .data = (void *)RK_PDM_RK3308 }, 469 { .compatible = "rockchip,rk1808-pdm", 470 .data = (void *)RK_PDM_RK3308 }, 471 { .compatible = "rockchip,rk3308-pdm", 472 .data = (void *)RK_PDM_RK3308 }, 473 {}, 474}; 475MODULE_DEVICE_TABLE(of, rockchip_pdm_match); 476 477static int rockchip_pdm_probe(struct platform_device *pdev) 478{ 479 const struct of_device_id *match; 480 struct rk_pdm_dev *pdm; 481 struct resource *res; 482 void __iomem *regs; 483 int ret; 484 485 pdm = devm_kzalloc(&pdev->dev, sizeof(*pdm), GFP_KERNEL); 486 if (!pdm) 487 return -ENOMEM; 488 489 match = of_match_device(rockchip_pdm_match, &pdev->dev); 490 if (match) 491 pdm->version = (enum rk_pdm_version)match->data; 492 493 if (pdm->version == RK_PDM_RK3308) { 494 pdm->reset = devm_reset_control_get(&pdev->dev, "pdm-m"); 495 if (IS_ERR(pdm->reset)) 496 return PTR_ERR(pdm->reset); 497 } 498 499 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 500 regs = devm_ioremap_resource(&pdev->dev, res); 501 if (IS_ERR(regs)) 502 return PTR_ERR(regs); 503 504 pdm->regmap = devm_regmap_init_mmio(&pdev->dev, regs, 505 &rockchip_pdm_regmap_config); 506 if (IS_ERR(pdm->regmap)) 507 return PTR_ERR(pdm->regmap); 508 509 pdm->capture_dma_data.addr = res->start + PDM_RXFIFO_DATA; 510 pdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 511 pdm->capture_dma_data.maxburst = PDM_DMA_BURST_SIZE; 512 513 pdm->dev = &pdev->dev; 514 dev_set_drvdata(&pdev->dev, pdm); 515 516 pdm->clk = devm_clk_get(&pdev->dev, "pdm_clk"); 517 if (IS_ERR(pdm->clk)) 518 return PTR_ERR(pdm->clk); 519 520 pdm->hclk = devm_clk_get(&pdev->dev, "pdm_hclk"); 521 if (IS_ERR(pdm->hclk)) 522 return PTR_ERR(pdm->hclk); 523 524 ret = clk_prepare_enable(pdm->hclk); 525 if (ret) 526 return ret; 527 528 pm_runtime_enable(&pdev->dev); 529 if (!pm_runtime_enabled(&pdev->dev)) { 530 ret = rockchip_pdm_runtime_resume(&pdev->dev); 531 if (ret) 532 goto err_pm_disable; 533 } 534 535 ret = devm_snd_soc_register_component(&pdev->dev, 536 &rockchip_pdm_component, 537 &rockchip_pdm_dai, 1); 538 539 if (ret) { 540 dev_err(&pdev->dev, "could not register dai: %d\n", ret); 541 goto err_suspend; 542 } 543 544 rockchip_pdm_rxctrl(pdm, 0); 545 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 546 if (ret) { 547 dev_err(&pdev->dev, "could not register pcm: %d\n", ret); 548 goto err_suspend; 549 } 550 551 return 0; 552 553err_suspend: 554 if (!pm_runtime_status_suspended(&pdev->dev)) 555 rockchip_pdm_runtime_suspend(&pdev->dev); 556err_pm_disable: 557 pm_runtime_disable(&pdev->dev); 558 559 clk_disable_unprepare(pdm->hclk); 560 561 return ret; 562} 563 564static int rockchip_pdm_remove(struct platform_device *pdev) 565{ 566 struct rk_pdm_dev *pdm = dev_get_drvdata(&pdev->dev); 567 568 pm_runtime_disable(&pdev->dev); 569 if (!pm_runtime_status_suspended(&pdev->dev)) 570 rockchip_pdm_runtime_suspend(&pdev->dev); 571 572 clk_disable_unprepare(pdm->clk); 573 clk_disable_unprepare(pdm->hclk); 574 575 return 0; 576} 577 578#ifdef CONFIG_PM_SLEEP 579static int rockchip_pdm_suspend(struct device *dev) 580{ 581 struct rk_pdm_dev *pdm = dev_get_drvdata(dev); 582 583 regcache_mark_dirty(pdm->regmap); 584 585 return 0; 586} 587 588static int rockchip_pdm_resume(struct device *dev) 589{ 590 struct rk_pdm_dev *pdm = dev_get_drvdata(dev); 591 int ret; 592 593 ret = pm_runtime_get_sync(dev); 594 if (ret < 0) { 595 pm_runtime_put(dev); 596 return ret; 597 } 598 599 ret = regcache_sync(pdm->regmap); 600 601 pm_runtime_put(dev); 602 603 return ret; 604} 605#endif 606 607static const struct dev_pm_ops rockchip_pdm_pm_ops = { 608 SET_RUNTIME_PM_OPS(rockchip_pdm_runtime_suspend, 609 rockchip_pdm_runtime_resume, NULL) 610 SET_SYSTEM_SLEEP_PM_OPS(rockchip_pdm_suspend, rockchip_pdm_resume) 611}; 612 613static struct platform_driver rockchip_pdm_driver = { 614 .probe = rockchip_pdm_probe, 615 .remove = rockchip_pdm_remove, 616 .driver = { 617 .name = "rockchip-pdm", 618 .of_match_table = of_match_ptr(rockchip_pdm_match), 619 .pm = &rockchip_pdm_pm_ops, 620 }, 621}; 622 623module_platform_driver(rockchip_pdm_driver); 624 625MODULE_AUTHOR("Sugar <sugar.zhang@rock-chips.com>"); 626MODULE_DESCRIPTION("Rockchip PDM Controller Driver"); 627MODULE_LICENSE("GPL v2"); 628