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