Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge series "Patches to update for rockchip i2s" from Sugar Zhang <sugar.zhang@rock-chips.com>:

These patches fixup or update for rockchip i2s.

Changes in v3:
- Drop property 'rockchip,playback-only', 'rockchip,capture-only'.
Implement it by 'dma-names' of DT instead.

Changes in v2:
- split property trcm into single 'trcm-sync-tx-only' and
'trcm-sync-rx-only' suggested by Nicolas.
- split property trcm into single 'trcm-sync-tx-only' and
'trcm-sync-rx-only' suggested by Nicolas.
- drop change-id

Sugar Zhang (12):
ASoC: rockchip: i2s: Add support for set bclk ratio
ASoC: rockchip: i2s: Fixup clk div error
ASoC: rockchip: i2s: Improve dma data transfer efficiency
ASoC: rockchip: i2s: Fix regmap_ops hang
ASoC: rockchip: i2s: Fix concurrency between tx/rx
ASoC: rockchip: i2s: Reset the controller if soft reset failed
ASoC: dt-bindings: rockchip: Document reset property for i2s
ASoC: rockchip: i2s: Make playback/capture optional
ASoC: rockchip: i2s: Add compatible for more SoCs
ASoC: dt-bindings: rockchip: Add compatible strings for more SoCs
ASoC: rockchip: i2s: Add support for frame inversion
ASoC: dt-bindings: rockchip: i2s: Document property TRCM

Xiaotan Luo (1):
ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B

Xing Zheng (1):
ASoC: rockchip: i2s: Add support for TRCM property

.../devicetree/bindings/sound/rockchip-i2s.yaml | 19 ++
sound/soc/rockchip/rockchip_i2s.c | 278 +++++++++++++++------
sound/soc/rockchip/rockchip_i2s.h | 10 +-
3 files changed, 224 insertions(+), 83 deletions(-)

--
2.7.4

+161 -72
+11
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
··· 20 20 - items: 21 21 - enum: 22 22 - rockchip,px30-i2s 23 + - rockchip,rk1808-i2s 23 24 - rockchip,rk3036-i2s 25 + - rockchip,rk3128-i2s 24 26 - rockchip,rk3188-i2s 25 27 - rockchip,rk3228-i2s 26 28 - rockchip,rk3288-i2s ··· 31 29 - rockchip,rk3366-i2s 32 30 - rockchip,rk3368-i2s 33 31 - rockchip,rk3399-i2s 32 + - rockchip,rv1126-i2s 34 33 - const: rockchip,rk3066-i2s 35 34 36 35 reg: ··· 63 60 64 61 power-domains: 65 62 maxItems: 1 63 + 64 + reset-names: 65 + items: 66 + - const: reset-m 67 + - const: reset-h 68 + 69 + resets: 70 + maxItems: 2 66 71 67 72 rockchip,capture-channels: 68 73 $ref: /schemas/types.yaml#/definitions/uint32
+144 -68
sound/soc/rockchip/rockchip_i2s.c
··· 40 40 struct regmap *regmap; 41 41 struct regmap *grf; 42 42 43 + bool has_capture; 44 + bool has_playback; 45 + 43 46 /* 44 47 * Used to indicate the tx/rx status. 45 48 * I2S controller hopes to start the tx and rx together, ··· 52 49 bool rx_start; 53 50 bool is_master_mode; 54 51 const struct rk_i2s_pins *pins; 52 + unsigned int bclk_ratio; 55 53 }; 56 54 57 55 static int i2s_runtime_suspend(struct device *dev) ··· 190 186 { 191 187 struct rk_i2s_dev *i2s = to_info(cpu_dai); 192 188 unsigned int mask = 0, val = 0; 189 + int ret = 0; 193 190 191 + pm_runtime_get_sync(cpu_dai->dev); 194 192 mask = I2S_CKR_MSS_MASK; 195 193 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 196 194 case SND_SOC_DAIFMT_CBS_CFS: ··· 205 199 i2s->is_master_mode = false; 206 200 break; 207 201 default: 208 - return -EINVAL; 202 + ret = -EINVAL; 203 + goto err_pm_put; 209 204 } 210 205 211 206 regmap_update_bits(i2s->regmap, I2S_CKR, mask, val); 212 207 213 - mask = I2S_CKR_CKP_MASK; 208 + mask = I2S_CKR_CKP_MASK | I2S_CKR_TLP_MASK | I2S_CKR_RLP_MASK; 214 209 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 215 210 case SND_SOC_DAIFMT_NB_NF: 216 - val = I2S_CKR_CKP_NEG; 211 + val = I2S_CKR_CKP_NORMAL | 212 + I2S_CKR_TLP_NORMAL | 213 + I2S_CKR_RLP_NORMAL; 214 + break; 215 + case SND_SOC_DAIFMT_NB_IF: 216 + val = I2S_CKR_CKP_NORMAL | 217 + I2S_CKR_TLP_INVERTED | 218 + I2S_CKR_RLP_INVERTED; 217 219 break; 218 220 case SND_SOC_DAIFMT_IB_NF: 219 - val = I2S_CKR_CKP_POS; 221 + val = I2S_CKR_CKP_INVERTED | 222 + I2S_CKR_TLP_NORMAL | 223 + I2S_CKR_RLP_NORMAL; 224 + break; 225 + case SND_SOC_DAIFMT_IB_IF: 226 + val = I2S_CKR_CKP_INVERTED | 227 + I2S_CKR_TLP_INVERTED | 228 + I2S_CKR_RLP_INVERTED; 220 229 break; 221 230 default: 222 - return -EINVAL; 231 + ret = -EINVAL; 232 + goto err_pm_put; 223 233 } 224 234 225 235 regmap_update_bits(i2s->regmap, I2S_CKR, mask, val); ··· 251 229 case SND_SOC_DAIFMT_I2S: 252 230 val = I2S_TXCR_IBM_NORMAL; 253 231 break; 254 - case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */ 255 - val = I2S_TXCR_TFS_PCM; 256 - break; 257 - case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */ 232 + case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */ 258 233 val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1); 259 234 break; 235 + case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */ 236 + val = I2S_TXCR_TFS_PCM; 237 + break; 260 238 default: 261 - return -EINVAL; 239 + ret = -EINVAL; 240 + goto err_pm_put; 262 241 } 263 242 264 243 regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val); ··· 275 252 case SND_SOC_DAIFMT_I2S: 276 253 val = I2S_RXCR_IBM_NORMAL; 277 254 break; 278 - case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */ 279 - val = I2S_RXCR_TFS_PCM; 280 - break; 281 - case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */ 255 + case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */ 282 256 val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1); 283 257 break; 258 + case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */ 259 + val = I2S_RXCR_TFS_PCM; 260 + break; 284 261 default: 285 - return -EINVAL; 262 + ret = -EINVAL; 263 + goto err_pm_put; 286 264 } 287 265 288 266 regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val); 289 267 290 - return 0; 268 + err_pm_put: 269 + pm_runtime_put(cpu_dai->dev); 270 + 271 + return ret; 291 272 } 292 273 293 274 static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, ··· 305 278 306 279 if (i2s->is_master_mode) { 307 280 mclk_rate = clk_get_rate(i2s->mclk); 308 - bclk_rate = 2 * 32 * params_rate(params); 309 - if (bclk_rate == 0 || mclk_rate % bclk_rate) 281 + bclk_rate = i2s->bclk_ratio * params_rate(params); 282 + if (!bclk_rate) 310 283 return -EINVAL; 311 284 312 - div_bclk = mclk_rate / bclk_rate; 285 + div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); 313 286 div_lrck = bclk_rate / params_rate(params); 314 287 regmap_update_bits(i2s->regmap, I2S_CKR, 315 288 I2S_CKR_MDIV_MASK, ··· 440 413 return ret; 441 414 } 442 415 416 + static int rockchip_i2s_set_bclk_ratio(struct snd_soc_dai *dai, 417 + unsigned int ratio) 418 + { 419 + struct rk_i2s_dev *i2s = to_info(dai); 420 + 421 + i2s->bclk_ratio = ratio; 422 + 423 + return 0; 424 + } 425 + 443 426 static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, 444 427 unsigned int freq, int dir) 445 428 { ··· 470 433 { 471 434 struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); 472 435 473 - dai->capture_dma_data = &i2s->capture_dma_data; 474 - dai->playback_dma_data = &i2s->playback_dma_data; 436 + snd_soc_dai_init_dma_data(dai, 437 + i2s->has_playback ? &i2s->playback_dma_data : NULL, 438 + i2s->has_capture ? &i2s->capture_dma_data : NULL); 475 439 476 440 return 0; 477 441 } 478 442 479 443 static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { 480 444 .hw_params = rockchip_i2s_hw_params, 445 + .set_bclk_ratio = rockchip_i2s_set_bclk_ratio, 481 446 .set_sysclk = rockchip_i2s_set_sysclk, 482 447 .set_fmt = rockchip_i2s_set_fmt, 483 448 .trigger = rockchip_i2s_trigger, ··· 487 448 488 449 static struct snd_soc_dai_driver rockchip_i2s_dai = { 489 450 .probe = rockchip_i2s_dai_probe, 490 - .playback = { 491 - .stream_name = "Playback", 492 - .channels_min = 2, 493 - .channels_max = 8, 494 - .rates = SNDRV_PCM_RATE_8000_192000, 495 - .formats = (SNDRV_PCM_FMTBIT_S8 | 496 - SNDRV_PCM_FMTBIT_S16_LE | 497 - SNDRV_PCM_FMTBIT_S20_3LE | 498 - SNDRV_PCM_FMTBIT_S24_LE | 499 - SNDRV_PCM_FMTBIT_S32_LE), 500 - }, 501 - .capture = { 502 - .stream_name = "Capture", 503 - .channels_min = 2, 504 - .channels_max = 2, 505 - .rates = SNDRV_PCM_RATE_8000_192000, 506 - .formats = (SNDRV_PCM_FMTBIT_S8 | 507 - SNDRV_PCM_FMTBIT_S16_LE | 508 - SNDRV_PCM_FMTBIT_S20_3LE | 509 - SNDRV_PCM_FMTBIT_S24_LE | 510 - SNDRV_PCM_FMTBIT_S32_LE), 511 - }, 512 451 .ops = &rockchip_i2s_dai_ops, 513 452 .symmetric_rate = 1, 514 453 }; ··· 584 567 }; 585 568 586 569 static const struct of_device_id rockchip_i2s_match[] __maybe_unused = { 570 + { .compatible = "rockchip,px30-i2s", }, 571 + { .compatible = "rockchip,rk1808-i2s", }, 572 + { .compatible = "rockchip,rk3036-i2s", }, 587 573 { .compatible = "rockchip,rk3066-i2s", }, 574 + { .compatible = "rockchip,rk3128-i2s", }, 588 575 { .compatible = "rockchip,rk3188-i2s", }, 576 + { .compatible = "rockchip,rk3228-i2s", }, 589 577 { .compatible = "rockchip,rk3288-i2s", }, 578 + { .compatible = "rockchip,rk3308-i2s", }, 579 + { .compatible = "rockchip,rk3328-i2s", }, 580 + { .compatible = "rockchip,rk3366-i2s", }, 581 + { .compatible = "rockchip,rk3368-i2s", }, 590 582 { .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins }, 583 + { .compatible = "rockchip,rv1126-i2s", }, 591 584 {}, 592 585 }; 586 + 587 + static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res, 588 + struct snd_soc_dai_driver **dp) 589 + { 590 + struct device_node *node = i2s->dev->of_node; 591 + struct snd_soc_dai_driver *dai; 592 + struct property *dma_names; 593 + const char *dma_name; 594 + unsigned int val; 595 + 596 + of_property_for_each_string(node, "dma-names", dma_names, dma_name) { 597 + if (!strcmp(dma_name, "tx")) 598 + i2s->has_playback = true; 599 + if (!strcmp(dma_name, "rx")) 600 + i2s->has_capture = true; 601 + } 602 + 603 + dai = devm_kmemdup(i2s->dev, &rockchip_i2s_dai, 604 + sizeof(*dai), GFP_KERNEL); 605 + if (!dai) 606 + return -ENOMEM; 607 + 608 + if (i2s->has_playback) { 609 + dai->playback.stream_name = "Playback"; 610 + dai->playback.channels_min = 2; 611 + dai->playback.channels_max = 8; 612 + dai->playback.rates = SNDRV_PCM_RATE_8000_192000; 613 + dai->playback.formats = SNDRV_PCM_FMTBIT_S8 | 614 + SNDRV_PCM_FMTBIT_S16_LE | 615 + SNDRV_PCM_FMTBIT_S20_3LE | 616 + SNDRV_PCM_FMTBIT_S24_LE | 617 + SNDRV_PCM_FMTBIT_S32_LE; 618 + 619 + i2s->playback_dma_data.addr = res->start + I2S_TXDR; 620 + i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 621 + i2s->playback_dma_data.maxburst = 8; 622 + 623 + if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { 624 + if (val >= 2 && val <= 8) 625 + dai->playback.channels_max = val; 626 + } 627 + } 628 + 629 + if (i2s->has_capture) { 630 + dai->capture.stream_name = "Capture"; 631 + dai->capture.channels_min = 2; 632 + dai->capture.channels_max = 8; 633 + dai->capture.rates = SNDRV_PCM_RATE_8000_192000; 634 + dai->capture.formats = SNDRV_PCM_FMTBIT_S8 | 635 + SNDRV_PCM_FMTBIT_S16_LE | 636 + SNDRV_PCM_FMTBIT_S20_3LE | 637 + SNDRV_PCM_FMTBIT_S24_LE | 638 + SNDRV_PCM_FMTBIT_S32_LE; 639 + 640 + i2s->capture_dma_data.addr = res->start + I2S_RXDR; 641 + i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 642 + i2s->capture_dma_data.maxburst = 8; 643 + 644 + if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) { 645 + if (val >= 2 && val <= 8) 646 + dai->capture.channels_max = val; 647 + } 648 + } 649 + 650 + if (dp) 651 + *dp = dai; 652 + 653 + return 0; 654 + } 593 655 594 656 static int rockchip_i2s_probe(struct platform_device *pdev) 595 657 { 596 658 struct device_node *node = pdev->dev.of_node; 597 659 const struct of_device_id *of_id; 598 660 struct rk_i2s_dev *i2s; 599 - struct snd_soc_dai_driver *soc_dai; 661 + struct snd_soc_dai_driver *dai; 600 662 struct resource *res; 601 663 void __iomem *regs; 602 664 int ret; 603 - int val; 604 665 605 666 i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); 606 667 if (!i2s) ··· 725 630 return PTR_ERR(i2s->regmap); 726 631 } 727 632 728 - i2s->playback_dma_data.addr = res->start + I2S_TXDR; 729 - i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 730 - i2s->playback_dma_data.maxburst = 4; 731 - 732 - i2s->capture_dma_data.addr = res->start + I2S_RXDR; 733 - i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 734 - i2s->capture_dma_data.maxburst = 4; 633 + i2s->bclk_ratio = 64; 735 634 736 635 dev_set_drvdata(&pdev->dev, i2s); 737 636 ··· 736 647 goto err_pm_disable; 737 648 } 738 649 739 - soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai, 740 - sizeof(*soc_dai), GFP_KERNEL); 741 - if (!soc_dai) { 742 - ret = -ENOMEM; 650 + ret = rockchip_i2s_init_dai(i2s, res, &dai); 651 + if (ret) 743 652 goto err_pm_disable; 744 - } 745 - 746 - if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { 747 - if (val >= 2 && val <= 8) 748 - soc_dai->playback.channels_max = val; 749 - } 750 - 751 - if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) { 752 - if (val >= 2 && val <= 8) 753 - soc_dai->capture.channels_max = val; 754 - } 755 653 756 654 ret = devm_snd_soc_register_component(&pdev->dev, 757 655 &rockchip_i2s_component, 758 - soc_dai, 1); 656 + dai, 1); 759 657 760 658 if (ret) { 761 659 dev_err(&pdev->dev, "Could not register DAI\n");
+6 -4
sound/soc/rockchip/rockchip_i2s.h
··· 88 88 #define I2S_CKR_MSS_SLAVE (1 << I2S_CKR_MSS_SHIFT) 89 89 #define I2S_CKR_MSS_MASK (1 << I2S_CKR_MSS_SHIFT) 90 90 #define I2S_CKR_CKP_SHIFT 26 91 - #define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT) 92 - #define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT) 91 + #define I2S_CKR_CKP_NORMAL (0 << I2S_CKR_CKP_SHIFT) 92 + #define I2S_CKR_CKP_INVERTED (1 << I2S_CKR_CKP_SHIFT) 93 93 #define I2S_CKR_CKP_MASK (1 << I2S_CKR_CKP_SHIFT) 94 94 #define I2S_CKR_RLP_SHIFT 25 95 95 #define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT) 96 - #define I2S_CKR_RLP_OPPSITE (1 << I2S_CKR_RLP_SHIFT) 96 + #define I2S_CKR_RLP_INVERTED (1 << I2S_CKR_RLP_SHIFT) 97 + #define I2S_CKR_RLP_MASK (1 << I2S_CKR_RLP_SHIFT) 97 98 #define I2S_CKR_TLP_SHIFT 24 98 99 #define I2S_CKR_TLP_NORMAL (0 << I2S_CKR_TLP_SHIFT) 99 - #define I2S_CKR_TLP_OPPSITE (1 << I2S_CKR_TLP_SHIFT) 100 + #define I2S_CKR_TLP_INVERTED (1 << I2S_CKR_TLP_SHIFT) 101 + #define I2S_CKR_TLP_MASK (1 << I2S_CKR_TLP_SHIFT) 100 102 #define I2S_CKR_MDIV_SHIFT 16 101 103 #define I2S_CKR_MDIV(x) ((x - 1) << I2S_CKR_MDIV_SHIFT) 102 104 #define I2S_CKR_MDIV_MASK (0xff << I2S_CKR_MDIV_SHIFT)