.. | .. |
---|
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; |
---|