| .. | .. |
|---|
| 21 | 21 | #include <sound/dmaengine_pcm.h> |
|---|
| 22 | 22 | |
|---|
| 23 | 23 | #include "rockchip_i2s.h" |
|---|
| 24 | +#include "rockchip_dlp_pcm.h" |
|---|
| 25 | +#include "rockchip_utils.h" |
|---|
| 24 | 26 | |
|---|
| 25 | 27 | #define DRV_NAME "rockchip-i2s" |
|---|
| 26 | 28 | |
|---|
| .. | .. |
|---|
| 333 | 335 | return ret; |
|---|
| 334 | 336 | } |
|---|
| 335 | 337 | |
|---|
| 338 | +static void rockchip_i2s_get_performance(struct snd_pcm_substream *substream, |
|---|
| 339 | + struct snd_pcm_hw_params *params, |
|---|
| 340 | + struct snd_soc_dai *dai, |
|---|
| 341 | + unsigned int csr) |
|---|
| 342 | +{ |
|---|
| 343 | + struct rk_i2s_dev *i2s = to_info(dai); |
|---|
| 344 | + unsigned int tdl; |
|---|
| 345 | + int fifo; |
|---|
| 346 | + |
|---|
| 347 | + regmap_read(i2s->regmap, I2S_DMACR, &tdl); |
|---|
| 348 | + |
|---|
| 349 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
|---|
| 350 | + fifo = I2S_DMACR_TDL_V(tdl) * I2S_TXCR_CSR_V(csr); |
|---|
| 351 | + else |
|---|
| 352 | + fifo = I2S_DMACR_RDL_V(tdl) * I2S_RXCR_CSR_V(csr); |
|---|
| 353 | + |
|---|
| 354 | + rockchip_utils_get_performance(substream, params, dai, fifo); |
|---|
| 355 | +} |
|---|
| 356 | + |
|---|
| 336 | 357 | static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, |
|---|
| 337 | 358 | struct snd_pcm_hw_params *params, |
|---|
| 338 | 359 | struct snd_soc_dai *dai) |
|---|
| .. | .. |
|---|
| 400 | 421 | return -EINVAL; |
|---|
| 401 | 422 | } |
|---|
| 402 | 423 | |
|---|
| 424 | + rockchip_i2s_get_performance(substream, params, dai, val); |
|---|
| 425 | + |
|---|
| 403 | 426 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
|---|
| 404 | 427 | regmap_update_bits(i2s->regmap, I2S_RXCR, |
|---|
| 405 | 428 | I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK, |
|---|
| .. | .. |
|---|
| 437 | 460 | I2S_DMACR_TDL(16)); |
|---|
| 438 | 461 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, |
|---|
| 439 | 462 | I2S_DMACR_RDL(16)); |
|---|
| 463 | + |
|---|
| 464 | + return 0; |
|---|
| 465 | +} |
|---|
| 466 | + |
|---|
| 467 | +static int rockchip_i2s_hw_free(struct snd_pcm_substream *substream, |
|---|
| 468 | + struct snd_soc_dai *dai) |
|---|
| 469 | +{ |
|---|
| 470 | + rockchip_utils_put_performance(substream, dai); |
|---|
| 440 | 471 | |
|---|
| 441 | 472 | return 0; |
|---|
| 442 | 473 | } |
|---|
| .. | .. |
|---|
| 571 | 602 | static int rockchip_i2s_clk_compensation_get(struct snd_kcontrol *kcontrol, |
|---|
| 572 | 603 | struct snd_ctl_elem_value *ucontrol) |
|---|
| 573 | 604 | { |
|---|
| 574 | | - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); |
|---|
| 575 | | - struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); |
|---|
| 605 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); |
|---|
| 606 | + struct rk_i2s_dev *i2s = snd_soc_component_get_drvdata(compnt); |
|---|
| 576 | 607 | |
|---|
| 577 | 608 | ucontrol->value.integer.value[0] = i2s->clk_ppm; |
|---|
| 578 | 609 | |
|---|
| .. | .. |
|---|
| 582 | 613 | static int rockchip_i2s_clk_compensation_put(struct snd_kcontrol *kcontrol, |
|---|
| 583 | 614 | struct snd_ctl_elem_value *ucontrol) |
|---|
| 584 | 615 | { |
|---|
| 585 | | - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); |
|---|
| 586 | | - struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); |
|---|
| 616 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); |
|---|
| 617 | + struct rk_i2s_dev *i2s = snd_soc_component_get_drvdata(compnt); |
|---|
| 587 | 618 | int ppm = ucontrol->value.integer.value[0]; |
|---|
| 588 | 619 | |
|---|
| 589 | 620 | if ((ucontrol->value.integer.value[0] < CLK_PPM_MIN) || |
|---|
| .. | .. |
|---|
| 646 | 677 | .startup = rockchip_i2s_startup, |
|---|
| 647 | 678 | .shutdown = rockchip_i2s_shutdown, |
|---|
| 648 | 679 | .hw_params = rockchip_i2s_hw_params, |
|---|
| 680 | + .hw_free = rockchip_i2s_hw_free, |
|---|
| 649 | 681 | .set_bclk_ratio = rockchip_i2s_set_bclk_ratio, |
|---|
| 650 | 682 | .set_sysclk = rockchip_i2s_set_sysclk, |
|---|
| 651 | 683 | .set_fmt = rockchip_i2s_set_fmt, |
|---|
| .. | .. |
|---|
| 798 | 830 | case I2S_CLR: |
|---|
| 799 | 831 | case I2S_TXDR: |
|---|
| 800 | 832 | case I2S_RXDR: |
|---|
| 801 | | - case I2S_FIFOLR: |
|---|
| 833 | + case I2S_TXFIFOLR: |
|---|
| 834 | + case I2S_RXFIFOLR: |
|---|
| 802 | 835 | case I2S_INTSR: |
|---|
| 803 | 836 | return true; |
|---|
| 804 | 837 | default: |
|---|
| .. | .. |
|---|
| 811 | 844 | switch (reg) { |
|---|
| 812 | 845 | case I2S_INTSR: |
|---|
| 813 | 846 | case I2S_CLR: |
|---|
| 814 | | - case I2S_FIFOLR: |
|---|
| 847 | + case I2S_TXFIFOLR: |
|---|
| 848 | + case I2S_RXFIFOLR: |
|---|
| 815 | 849 | case I2S_TXDR: |
|---|
| 816 | 850 | case I2S_RXDR: |
|---|
| 817 | 851 | return true; |
|---|
| .. | .. |
|---|
| 938 | 972 | i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
|---|
| 939 | 973 | i2s->playback_dma_data.maxburst = 8; |
|---|
| 940 | 974 | |
|---|
| 941 | | - if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { |
|---|
| 975 | + if (!device_property_read_u32(i2s->dev, "rockchip,playback-channels", &val)) { |
|---|
| 942 | 976 | if (val >= 2 && val <= 8) |
|---|
| 943 | 977 | dai->playback.channels_max = val; |
|---|
| 944 | 978 | } |
|---|
| .. | .. |
|---|
| 960 | 994 | i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
|---|
| 961 | 995 | i2s->capture_dma_data.maxburst = 8; |
|---|
| 962 | 996 | |
|---|
| 963 | | - if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) { |
|---|
| 997 | + if (!device_property_read_u32(i2s->dev, "rockchip,capture-channels", &val)) { |
|---|
| 964 | 998 | if (val >= 2 && val <= 8) |
|---|
| 965 | 999 | dai->capture.channels_max = val; |
|---|
| 966 | 1000 | } |
|---|
| 967 | 1001 | } |
|---|
| 968 | 1002 | |
|---|
| 969 | 1003 | i2s->clk_trcm = I2S_CKR_TRCM_TXRX; |
|---|
| 970 | | - if (!of_property_read_u32(node, "rockchip,clk-trcm", &val)) { |
|---|
| 1004 | + if (!device_property_read_u32(i2s->dev, "rockchip,clk-trcm", &val)) { |
|---|
| 971 | 1005 | if (val >= 0 && val <= 2) { |
|---|
| 972 | 1006 | i2s->clk_trcm = val << I2S_CKR_TRCM_SHIFT; |
|---|
| 973 | 1007 | if (i2s->clk_trcm) |
|---|
| .. | .. |
|---|
| 1015 | 1049 | |
|---|
| 1016 | 1050 | return 0; |
|---|
| 1017 | 1051 | } |
|---|
| 1052 | + |
|---|
| 1053 | +static int rockchip_i2s_get_fifo_count(struct device *dev, |
|---|
| 1054 | + struct snd_pcm_substream *substream) |
|---|
| 1055 | +{ |
|---|
| 1056 | + struct rk_i2s_dev *i2s = dev_get_drvdata(dev); |
|---|
| 1057 | + unsigned int tx, rx; |
|---|
| 1058 | + int val = 0; |
|---|
| 1059 | + |
|---|
| 1060 | + regmap_read(i2s->regmap, I2S_TXFIFOLR, &tx); |
|---|
| 1061 | + regmap_read(i2s->regmap, I2S_RXFIFOLR, &rx); |
|---|
| 1062 | + |
|---|
| 1063 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
|---|
| 1064 | + val = I2S_FIFOLR_XFL3(tx) + |
|---|
| 1065 | + I2S_FIFOLR_XFL2(tx) + |
|---|
| 1066 | + I2S_FIFOLR_XFL1(tx) + |
|---|
| 1067 | + I2S_FIFOLR_XFL0(tx); |
|---|
| 1068 | + else |
|---|
| 1069 | + /* XFL4 is compatible for old version */ |
|---|
| 1070 | + val = I2S_FIFOLR_XFL4(tx) + |
|---|
| 1071 | + I2S_FIFOLR_XFL3(rx) + |
|---|
| 1072 | + I2S_FIFOLR_XFL2(rx) + |
|---|
| 1073 | + I2S_FIFOLR_XFL1(rx) + |
|---|
| 1074 | + I2S_FIFOLR_XFL0(rx); |
|---|
| 1075 | + |
|---|
| 1076 | + return val; |
|---|
| 1077 | +} |
|---|
| 1078 | + |
|---|
| 1079 | +static const struct snd_dlp_config dconfig = { |
|---|
| 1080 | + .get_fifo_count = rockchip_i2s_get_fifo_count, |
|---|
| 1081 | +}; |
|---|
| 1018 | 1082 | |
|---|
| 1019 | 1083 | static int rockchip_i2s_probe(struct platform_device *pdev) |
|---|
| 1020 | 1084 | { |
|---|
| .. | .. |
|---|
| 1067 | 1131 | dev_set_drvdata(&pdev->dev, i2s); |
|---|
| 1068 | 1132 | |
|---|
| 1069 | 1133 | i2s->mclk_calibrate = |
|---|
| 1070 | | - of_property_read_bool(node, "rockchip,mclk-calibrate"); |
|---|
| 1134 | + device_property_read_bool(&pdev->dev, "rockchip,mclk-calibrate"); |
|---|
| 1071 | 1135 | if (i2s->mclk_calibrate) { |
|---|
| 1072 | 1136 | i2s->mclk_root = devm_clk_get(&pdev->dev, "i2s_clk_root"); |
|---|
| 1073 | 1137 | if (IS_ERR(i2s->mclk_root)) |
|---|
| .. | .. |
|---|
| 1136 | 1200 | goto err_suspend; |
|---|
| 1137 | 1201 | } |
|---|
| 1138 | 1202 | |
|---|
| 1139 | | - if (of_property_read_bool(node, "rockchip,no-dmaengine")) { |
|---|
| 1203 | + if (device_property_read_bool(&pdev->dev, "rockchip,no-dmaengine")) { |
|---|
| 1140 | 1204 | dev_info(&pdev->dev, "Used for Multi-DAI\n"); |
|---|
| 1141 | 1205 | return 0; |
|---|
| 1142 | 1206 | } |
|---|
| 1143 | 1207 | |
|---|
| 1144 | | - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); |
|---|
| 1208 | + if (device_property_read_bool(&pdev->dev, "rockchip,digital-loopback")) |
|---|
| 1209 | + ret = devm_snd_dmaengine_dlp_register(&pdev->dev, &dconfig); |
|---|
| 1210 | + else |
|---|
| 1211 | + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); |
|---|
| 1212 | + |
|---|
| 1145 | 1213 | if (ret) { |
|---|
| 1146 | 1214 | dev_err(&pdev->dev, "Could not register PCM\n"); |
|---|
| 1147 | 1215 | goto err_suspend; |
|---|