| .. | .. |
|---|
| 28 | 28 | #include <sound/dmaengine_pcm.h> |
|---|
| 29 | 29 | |
|---|
| 30 | 30 | #include "rockchip_i2s_tdm.h" |
|---|
| 31 | | -#include "rockchip_dlp.h" |
|---|
| 31 | +#include "rockchip_dlp_pcm.h" |
|---|
| 32 | +#include "rockchip_utils.h" |
|---|
| 32 | 33 | |
|---|
| 33 | 34 | #define DRV_NAME "rockchip-i2s-tdm" |
|---|
| 34 | 35 | |
|---|
| .. | .. |
|---|
| 1678 | 1679 | return ret; |
|---|
| 1679 | 1680 | } |
|---|
| 1680 | 1681 | |
|---|
| 1682 | +static void rockchip_i2s_tdm_get_performance(struct snd_pcm_substream *substream, |
|---|
| 1683 | + struct snd_pcm_hw_params *params, |
|---|
| 1684 | + struct snd_soc_dai *dai, |
|---|
| 1685 | + unsigned int csr) |
|---|
| 1686 | +{ |
|---|
| 1687 | + struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai); |
|---|
| 1688 | + unsigned int tdl; |
|---|
| 1689 | + int fifo; |
|---|
| 1690 | + |
|---|
| 1691 | + regmap_read(i2s_tdm->regmap, I2S_DMACR, &tdl); |
|---|
| 1692 | + |
|---|
| 1693 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
|---|
| 1694 | + fifo = I2S_DMACR_TDL_V(tdl) * I2S_TXCR_CSR_V(csr); |
|---|
| 1695 | + else |
|---|
| 1696 | + fifo = I2S_DMACR_RDL_V(tdl) * I2S_RXCR_CSR_V(csr); |
|---|
| 1697 | + |
|---|
| 1698 | + rockchip_utils_get_performance(substream, params, dai, fifo); |
|---|
| 1699 | +} |
|---|
| 1700 | + |
|---|
| 1681 | 1701 | static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, |
|---|
| 1682 | 1702 | struct snd_pcm_hw_params *params, |
|---|
| 1683 | 1703 | struct snd_soc_dai *dai) |
|---|
| .. | .. |
|---|
| 1740 | 1760 | if (ret < 0) |
|---|
| 1741 | 1761 | goto err; |
|---|
| 1742 | 1762 | |
|---|
| 1763 | + rockchip_i2s_tdm_get_performance(substream, params, dai, ret); |
|---|
| 1764 | + |
|---|
| 1743 | 1765 | val |= ret; |
|---|
| 1744 | 1766 | if (!is_params_dirty(substream, dai, div_bclk, div_lrck, val)) |
|---|
| 1745 | 1767 | return 0; |
|---|
| .. | .. |
|---|
| 1753 | 1775 | |
|---|
| 1754 | 1776 | err: |
|---|
| 1755 | 1777 | return ret; |
|---|
| 1778 | +} |
|---|
| 1779 | +static int rockchip_i2s_tdm_hw_free(struct snd_pcm_substream *substream, |
|---|
| 1780 | + struct snd_soc_dai *dai) |
|---|
| 1781 | +{ |
|---|
| 1782 | + rockchip_utils_put_performance(substream, dai); |
|---|
| 1783 | + |
|---|
| 1784 | + return 0; |
|---|
| 1756 | 1785 | } |
|---|
| 1757 | 1786 | |
|---|
| 1758 | 1787 | static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream, |
|---|
| .. | .. |
|---|
| 1817 | 1846 | static int rockchip_i2s_tdm_clk_compensation_get(struct snd_kcontrol *kcontrol, |
|---|
| 1818 | 1847 | struct snd_ctl_elem_value *ucontrol) |
|---|
| 1819 | 1848 | { |
|---|
| 1820 | | - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); |
|---|
| 1821 | | - struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai); |
|---|
| 1849 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
|---|
| 1850 | + struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_component_get_drvdata(component); |
|---|
| 1822 | 1851 | |
|---|
| 1823 | 1852 | ucontrol->value.integer.value[0] = i2s_tdm->clk_ppm; |
|---|
| 1824 | 1853 | |
|---|
| .. | .. |
|---|
| 1828 | 1857 | static int rockchip_i2s_tdm_clk_compensation_put(struct snd_kcontrol *kcontrol, |
|---|
| 1829 | 1858 | struct snd_ctl_elem_value *ucontrol) |
|---|
| 1830 | 1859 | { |
|---|
| 1831 | | - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); |
|---|
| 1832 | | - struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai); |
|---|
| 1860 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
|---|
| 1861 | + struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_component_get_drvdata(component); |
|---|
| 1833 | 1862 | int ret = 0, ppm = 0; |
|---|
| 1834 | 1863 | |
|---|
| 1835 | 1864 | if ((ucontrol->value.integer.value[0] < CLK_PPM_MIN) || |
|---|
| .. | .. |
|---|
| 2119 | 2148 | .startup = rockchip_i2s_tdm_startup, |
|---|
| 2120 | 2149 | .shutdown = rockchip_i2s_tdm_shutdown, |
|---|
| 2121 | 2150 | .hw_params = rockchip_i2s_tdm_hw_params, |
|---|
| 2151 | + .hw_free = rockchip_i2s_tdm_hw_free, |
|---|
| 2122 | 2152 | .set_sysclk = rockchip_i2s_tdm_set_sysclk, |
|---|
| 2123 | 2153 | .set_fmt = rockchip_i2s_tdm_set_fmt, |
|---|
| 2124 | 2154 | .set_tdm_slot = rockchip_dai_tdm_slot, |
|---|
| .. | .. |
|---|
| 2548 | 2578 | return rockchip_i2s_tdm_path_prepare(i2s_tdm, np, 1); |
|---|
| 2549 | 2579 | } |
|---|
| 2550 | 2580 | |
|---|
| 2551 | | -static int rockchip_i2s_tdm_get_fifo_count(struct device *dev, int stream) |
|---|
| 2581 | +static int rockchip_i2s_tdm_get_fifo_count(struct device *dev, |
|---|
| 2582 | + struct snd_pcm_substream *substream) |
|---|
| 2552 | 2583 | { |
|---|
| 2553 | 2584 | struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); |
|---|
| 2554 | 2585 | int val = 0; |
|---|
| 2555 | 2586 | |
|---|
| 2556 | | - if (stream == SNDRV_PCM_STREAM_PLAYBACK) |
|---|
| 2587 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
|---|
| 2557 | 2588 | regmap_read(i2s_tdm->regmap, I2S_TXFIFOLR, &val); |
|---|
| 2558 | 2589 | else |
|---|
| 2559 | 2590 | regmap_read(i2s_tdm->regmap, I2S_RXFIFOLR, &val); |
|---|
| .. | .. |
|---|
| 2640 | 2671 | mclk_rate, bclk_rate, DEFAULT_FS); |
|---|
| 2641 | 2672 | |
|---|
| 2642 | 2673 | return 0; |
|---|
| 2674 | +} |
|---|
| 2675 | + |
|---|
| 2676 | +static int rockchip_i2s_tdm_register_platform(struct device *dev) |
|---|
| 2677 | +{ |
|---|
| 2678 | + int ret = 0; |
|---|
| 2679 | + |
|---|
| 2680 | + if (device_property_read_bool(dev, "rockchip,no-dmaengine")) { |
|---|
| 2681 | + dev_info(dev, "Used for Multi-DAI\n"); |
|---|
| 2682 | + return 0; |
|---|
| 2683 | + } |
|---|
| 2684 | + |
|---|
| 2685 | + if (device_property_read_bool(dev, "rockchip,digital-loopback")) { |
|---|
| 2686 | + ret = devm_snd_dmaengine_dlp_register(dev, &dconfig); |
|---|
| 2687 | + if (ret) |
|---|
| 2688 | + dev_err(dev, "Could not register DLP\n"); |
|---|
| 2689 | + return ret; |
|---|
| 2690 | + } |
|---|
| 2691 | + |
|---|
| 2692 | + ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0); |
|---|
| 2693 | + if (ret) |
|---|
| 2694 | + dev_err(dev, "Could not register PCM\n"); |
|---|
| 2695 | + |
|---|
| 2696 | + return ret; |
|---|
| 2643 | 2697 | } |
|---|
| 2644 | 2698 | |
|---|
| 2645 | 2699 | static int rockchip_i2s_tdm_probe(struct platform_device *pdev) |
|---|
| .. | .. |
|---|
| 2919 | 2973 | goto err_pm_disable; |
|---|
| 2920 | 2974 | } |
|---|
| 2921 | 2975 | |
|---|
| 2976 | + ret = rockchip_i2s_tdm_register_platform(&pdev->dev); |
|---|
| 2977 | + if (ret) |
|---|
| 2978 | + goto err_suspend; |
|---|
| 2979 | + |
|---|
| 2922 | 2980 | ret = devm_snd_soc_register_component(&pdev->dev, |
|---|
| 2923 | 2981 | &rockchip_i2s_tdm_component, |
|---|
| 2924 | 2982 | soc_dai, 1); |
|---|
| 2925 | | - |
|---|
| 2926 | 2983 | if (ret) { |
|---|
| 2927 | 2984 | dev_err(&pdev->dev, "Could not register DAI\n"); |
|---|
| 2928 | 2985 | goto err_suspend; |
|---|
| 2929 | | - } |
|---|
| 2930 | | - |
|---|
| 2931 | | - if (of_property_read_bool(node, "rockchip,no-dmaengine")) { |
|---|
| 2932 | | - dev_info(&pdev->dev, "Used for Multi-DAI\n"); |
|---|
| 2933 | | - return 0; |
|---|
| 2934 | | - } |
|---|
| 2935 | | - |
|---|
| 2936 | | - if (of_property_read_bool(node, "rockchip,digital-loopback")) |
|---|
| 2937 | | - ret = devm_snd_dmaengine_dlp_register(&pdev->dev, &dconfig); |
|---|
| 2938 | | - else |
|---|
| 2939 | | - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); |
|---|
| 2940 | | - |
|---|
| 2941 | | - if (ret) { |
|---|
| 2942 | | - dev_err(&pdev->dev, "Could not register PCM\n"); |
|---|
| 2943 | | - return ret; |
|---|
| 2944 | 2986 | } |
|---|
| 2945 | 2987 | |
|---|
| 2946 | 2988 | return 0; |
|---|