.. | .. |
---|
61 | 61 | bool is_master_mode; |
---|
62 | 62 | const struct rk_i2s_pins *pins; |
---|
63 | 63 | unsigned int bclk_fs; |
---|
| 64 | + spinlock_t lock; /* tx/rx lock */ |
---|
64 | 65 | unsigned int clk_trcm; |
---|
65 | 66 | |
---|
66 | 67 | unsigned int mclk_root_rate; |
---|
.. | .. |
---|
69 | 70 | bool mclk_calibrate; |
---|
70 | 71 | |
---|
71 | 72 | }; |
---|
72 | | - |
---|
73 | | -/* txctrl/rxctrl lock */ |
---|
74 | | -static DEFINE_SPINLOCK(lock); |
---|
75 | 73 | |
---|
76 | 74 | static int i2s_runtime_suspend(struct device *dev) |
---|
77 | 75 | { |
---|
.. | .. |
---|
124 | 122 | regcache_sync(i2s->regmap); |
---|
125 | 123 | } |
---|
126 | 124 | |
---|
| 125 | +static int rockchip_i2s_clear(struct rk_i2s_dev *i2s) |
---|
| 126 | +{ |
---|
| 127 | + unsigned int clr = I2S_CLR_TXC | I2S_CLR_RXC; |
---|
| 128 | + unsigned int val = 0; |
---|
| 129 | + int ret; |
---|
| 130 | + |
---|
| 131 | + /* |
---|
| 132 | + * Workaround for FIFO clear on SLAVE mode: |
---|
| 133 | + * |
---|
| 134 | + * A Suggest to do reset hclk domain and then do mclk |
---|
| 135 | + * domain, especially for SLAVE mode without CLK in. |
---|
| 136 | + * at last, recovery regmap config. |
---|
| 137 | + * |
---|
| 138 | + * B Suggest to switch to MASTER, and then do FIFO clr, |
---|
| 139 | + * at last, bring back to SLAVE. |
---|
| 140 | + * |
---|
| 141 | + * Now we choose plan B here. |
---|
| 142 | + */ |
---|
| 143 | + if (!i2s->is_master_mode) |
---|
| 144 | + regmap_update_bits(i2s->regmap, I2S_CKR, |
---|
| 145 | + I2S_CKR_MSS_MASK, I2S_CKR_MSS_MASTER); |
---|
| 146 | + regmap_update_bits(i2s->regmap, I2S_CLR, clr, clr); |
---|
| 147 | + |
---|
| 148 | + ret = regmap_read_poll_timeout_atomic(i2s->regmap, I2S_CLR, val, |
---|
| 149 | + !(val & clr), 10, 100); |
---|
| 150 | + if (!i2s->is_master_mode) |
---|
| 151 | + regmap_update_bits(i2s->regmap, I2S_CKR, |
---|
| 152 | + I2S_CKR_MSS_MASK, I2S_CKR_MSS_SLAVE); |
---|
| 153 | + if (ret < 0) { |
---|
| 154 | + dev_warn(i2s->dev, "failed to clear fifo on %s mode\n", |
---|
| 155 | + i2s->is_master_mode ? "master" : "slave"); |
---|
| 156 | + goto reset; |
---|
| 157 | + } |
---|
| 158 | + |
---|
| 159 | + return 0; |
---|
| 160 | + |
---|
| 161 | +reset: |
---|
| 162 | + rockchip_i2s_reset(i2s); |
---|
| 163 | + |
---|
| 164 | + return ret; |
---|
| 165 | +} |
---|
| 166 | + |
---|
127 | 167 | static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) |
---|
128 | 168 | { |
---|
129 | | - unsigned int val = 0; |
---|
130 | | - int retry = 10; |
---|
131 | | - |
---|
132 | | - spin_lock(&lock); |
---|
| 169 | + spin_lock(&i2s->lock); |
---|
133 | 170 | if (on) { |
---|
134 | 171 | regmap_update_bits(i2s->regmap, I2S_DMACR, |
---|
135 | 172 | I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); |
---|
.. | .. |
---|
153 | 190 | I2S_XFER_RXS_STOP); |
---|
154 | 191 | |
---|
155 | 192 | udelay(150); |
---|
156 | | - regmap_update_bits(i2s->regmap, I2S_CLR, |
---|
157 | | - I2S_CLR_TXC | I2S_CLR_RXC, |
---|
158 | | - I2S_CLR_TXC | I2S_CLR_RXC); |
---|
159 | | - |
---|
160 | | - regmap_read(i2s->regmap, I2S_CLR, &val); |
---|
161 | | - |
---|
162 | | - /* Should wait for clear operation to finish */ |
---|
163 | | - while (val) { |
---|
164 | | - regmap_read(i2s->regmap, I2S_CLR, &val); |
---|
165 | | - retry--; |
---|
166 | | - if (!retry) { |
---|
167 | | - dev_warn(i2s->dev, "reset\n"); |
---|
168 | | - rockchip_i2s_reset(i2s); |
---|
169 | | - break; |
---|
170 | | - } |
---|
171 | | - } |
---|
| 193 | + rockchip_i2s_clear(i2s); |
---|
172 | 194 | } |
---|
173 | 195 | } |
---|
174 | | - spin_unlock(&lock); |
---|
| 196 | + spin_unlock(&i2s->lock); |
---|
175 | 197 | } |
---|
176 | 198 | |
---|
177 | 199 | static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) |
---|
178 | 200 | { |
---|
179 | | - unsigned int val = 0; |
---|
180 | | - int retry = 10; |
---|
181 | | - |
---|
182 | | - spin_lock(&lock); |
---|
| 201 | + spin_lock(&i2s->lock); |
---|
183 | 202 | if (on) { |
---|
184 | 203 | regmap_update_bits(i2s->regmap, I2S_DMACR, |
---|
185 | 204 | I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); |
---|
.. | .. |
---|
203 | 222 | I2S_XFER_RXS_STOP); |
---|
204 | 223 | |
---|
205 | 224 | udelay(150); |
---|
206 | | - regmap_update_bits(i2s->regmap, I2S_CLR, |
---|
207 | | - I2S_CLR_TXC | I2S_CLR_RXC, |
---|
208 | | - I2S_CLR_TXC | I2S_CLR_RXC); |
---|
209 | | - |
---|
210 | | - regmap_read(i2s->regmap, I2S_CLR, &val); |
---|
211 | | - |
---|
212 | | - /* Should wait for clear operation to finish */ |
---|
213 | | - while (val) { |
---|
214 | | - regmap_read(i2s->regmap, I2S_CLR, &val); |
---|
215 | | - retry--; |
---|
216 | | - if (!retry) { |
---|
217 | | - dev_warn(i2s->dev, "reset\n"); |
---|
218 | | - rockchip_i2s_reset(i2s); |
---|
219 | | - break; |
---|
220 | | - } |
---|
221 | | - } |
---|
| 225 | + rockchip_i2s_clear(i2s); |
---|
222 | 226 | } |
---|
223 | 227 | } |
---|
224 | | - spin_unlock(&lock); |
---|
| 228 | + spin_unlock(&i2s->lock); |
---|
225 | 229 | } |
---|
226 | 230 | |
---|
227 | 231 | static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, |
---|
.. | .. |
---|
779 | 783 | if (!i2s) |
---|
780 | 784 | return -ENOMEM; |
---|
781 | 785 | |
---|
| 786 | + spin_lock_init(&i2s->lock); |
---|
782 | 787 | i2s->dev = &pdev->dev; |
---|
783 | 788 | |
---|
784 | 789 | i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf"); |
---|
.. | .. |
---|
819 | 824 | i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk"); |
---|
820 | 825 | if (IS_ERR(i2s->mclk)) { |
---|
821 | 826 | dev_err(&pdev->dev, "Can't retrieve i2s master clock\n"); |
---|
822 | | - return PTR_ERR(i2s->mclk); |
---|
| 827 | + ret = PTR_ERR(i2s->mclk); |
---|
| 828 | + goto err_clk; |
---|
823 | 829 | } |
---|
824 | 830 | |
---|
825 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
826 | | - regs = devm_ioremap_resource(&pdev->dev, res); |
---|
827 | | - if (IS_ERR(regs)) |
---|
828 | | - return PTR_ERR(regs); |
---|
| 831 | + regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); |
---|
| 832 | + if (IS_ERR(regs)) { |
---|
| 833 | + ret = PTR_ERR(regs); |
---|
| 834 | + goto err_clk; |
---|
| 835 | + } |
---|
829 | 836 | |
---|
830 | 837 | i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, |
---|
831 | 838 | &rockchip_i2s_regmap_config); |
---|
832 | 839 | if (IS_ERR(i2s->regmap)) { |
---|
833 | 840 | dev_err(&pdev->dev, |
---|
834 | 841 | "Failed to initialise managed register map\n"); |
---|
835 | | - return PTR_ERR(i2s->regmap); |
---|
| 842 | + ret = PTR_ERR(i2s->regmap); |
---|
| 843 | + goto err_clk; |
---|
836 | 844 | } |
---|
837 | 845 | |
---|
838 | 846 | i2s->playback_dma_data.addr = res->start + I2S_TXDR; |
---|
.. | .. |
---|
901 | 909 | goto err_suspend; |
---|
902 | 910 | } |
---|
903 | 911 | |
---|
904 | | - if (of_property_read_bool(node, "rockchip,no-dmaengine")) |
---|
905 | | - return ret; |
---|
| 912 | + if (of_property_read_bool(node, "rockchip,no-dmaengine")) { |
---|
| 913 | + dev_info(&pdev->dev, "Used for Multi-DAI\n"); |
---|
| 914 | + return 0; |
---|
| 915 | + } |
---|
| 916 | + |
---|
906 | 917 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); |
---|
907 | 918 | if (ret) { |
---|
908 | 919 | dev_err(&pdev->dev, "Could not register PCM\n"); |
---|
.. | .. |
---|
916 | 927 | i2s_runtime_suspend(&pdev->dev); |
---|
917 | 928 | err_pm_disable: |
---|
918 | 929 | pm_runtime_disable(&pdev->dev); |
---|
919 | | - |
---|
| 930 | +err_clk: |
---|
| 931 | + clk_disable_unprepare(i2s->hclk); |
---|
920 | 932 | return ret; |
---|
921 | 933 | } |
---|
922 | 934 | |
---|