.. | .. |
---|
6 | 6 | * Author: Garlic Tseng <garlic.tseng@mediatek.com> |
---|
7 | 7 | */ |
---|
8 | 8 | |
---|
| 9 | +#include <linux/io.h> |
---|
9 | 10 | #include <linux/module.h> |
---|
10 | 11 | #include <linux/pm_runtime.h> |
---|
11 | 12 | #include <linux/regmap.h> |
---|
12 | 13 | #include <sound/soc.h> |
---|
13 | 14 | #include "mtk-afe-platform-driver.h" |
---|
| 15 | +#include <sound/pcm_params.h> |
---|
14 | 16 | #include "mtk-afe-fe-dai.h" |
---|
15 | 17 | #include "mtk-base-afe.h" |
---|
16 | 18 | |
---|
.. | .. |
---|
18 | 20 | |
---|
19 | 21 | static int mtk_regmap_update_bits(struct regmap *map, int reg, |
---|
20 | 22 | unsigned int mask, |
---|
21 | | - unsigned int val) |
---|
| 23 | + unsigned int val, int shift) |
---|
22 | 24 | { |
---|
23 | | - if (reg < 0) |
---|
| 25 | + if (reg < 0 || WARN_ON_ONCE(shift < 0)) |
---|
24 | 26 | return 0; |
---|
25 | | - return regmap_update_bits(map, reg, mask, val); |
---|
| 27 | + return regmap_update_bits(map, reg, mask << shift, val << shift); |
---|
26 | 28 | } |
---|
27 | 29 | |
---|
28 | 30 | static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val) |
---|
.. | .. |
---|
35 | 37 | int mtk_afe_fe_startup(struct snd_pcm_substream *substream, |
---|
36 | 38 | struct snd_soc_dai *dai) |
---|
37 | 39 | { |
---|
38 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
---|
| 40 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
---|
39 | 41 | struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); |
---|
40 | 42 | struct snd_pcm_runtime *runtime = substream->runtime; |
---|
41 | | - int memif_num = rtd->cpu_dai->id; |
---|
| 43 | + int memif_num = asoc_rtd_to_cpu(rtd, 0)->id; |
---|
42 | 44 | struct mtk_base_afe_memif *memif = &afe->memif[memif_num]; |
---|
43 | 45 | const struct snd_pcm_hardware *mtk_afe_hardware = afe->mtk_afe_hardware; |
---|
44 | 46 | int ret; |
---|
.. | .. |
---|
49 | 51 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16); |
---|
50 | 52 | /* enable agent */ |
---|
51 | 53 | mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg, |
---|
52 | | - 1 << memif->data->agent_disable_shift, |
---|
53 | | - 0 << memif->data->agent_disable_shift); |
---|
| 54 | + 1, 0, memif->data->agent_disable_shift); |
---|
54 | 55 | |
---|
55 | 56 | snd_soc_set_runtime_hwparams(substream, mtk_afe_hardware); |
---|
56 | 57 | |
---|
.. | .. |
---|
97 | 98 | void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream, |
---|
98 | 99 | struct snd_soc_dai *dai) |
---|
99 | 100 | { |
---|
100 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
---|
| 101 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
---|
101 | 102 | struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); |
---|
102 | | - struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; |
---|
| 103 | + struct mtk_base_afe_memif *memif = &afe->memif[asoc_rtd_to_cpu(rtd, 0)->id]; |
---|
103 | 104 | int irq_id; |
---|
104 | 105 | |
---|
105 | 106 | irq_id = memif->irq_usage; |
---|
106 | 107 | |
---|
107 | 108 | mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg, |
---|
108 | | - 1 << memif->data->agent_disable_shift, |
---|
109 | | - 1 << memif->data->agent_disable_shift); |
---|
| 109 | + 1, 1, memif->data->agent_disable_shift); |
---|
110 | 110 | |
---|
111 | 111 | if (!memif->const_irq) { |
---|
112 | 112 | mtk_dynamic_irq_release(afe, irq_id); |
---|
.. | .. |
---|
120 | 120 | struct snd_pcm_hw_params *params, |
---|
121 | 121 | struct snd_soc_dai *dai) |
---|
122 | 122 | { |
---|
123 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
---|
| 123 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
---|
124 | 124 | struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); |
---|
125 | | - struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; |
---|
126 | | - int msb_at_bit33 = 0; |
---|
127 | | - int ret, fs = 0; |
---|
| 125 | + int id = asoc_rtd_to_cpu(rtd, 0)->id; |
---|
| 126 | + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
---|
| 127 | + int ret; |
---|
| 128 | + unsigned int channels = params_channels(params); |
---|
| 129 | + unsigned int rate = params_rate(params); |
---|
| 130 | + snd_pcm_format_t format = params_format(params); |
---|
128 | 131 | |
---|
129 | | - ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); |
---|
130 | | - if (ret < 0) |
---|
| 132 | + if (afe->request_dram_resource) |
---|
| 133 | + afe->request_dram_resource(afe->dev); |
---|
| 134 | + |
---|
| 135 | + dev_dbg(afe->dev, "%s(), %s, ch %d, rate %d, fmt %d, dma_addr %pad, dma_area %p, dma_bytes 0x%zx\n", |
---|
| 136 | + __func__, memif->data->name, |
---|
| 137 | + channels, rate, format, |
---|
| 138 | + &substream->runtime->dma_addr, |
---|
| 139 | + substream->runtime->dma_area, |
---|
| 140 | + substream->runtime->dma_bytes); |
---|
| 141 | + |
---|
| 142 | + memset_io(substream->runtime->dma_area, 0, |
---|
| 143 | + substream->runtime->dma_bytes); |
---|
| 144 | + |
---|
| 145 | + /* set addr */ |
---|
| 146 | + ret = mtk_memif_set_addr(afe, id, |
---|
| 147 | + substream->runtime->dma_area, |
---|
| 148 | + substream->runtime->dma_addr, |
---|
| 149 | + substream->runtime->dma_bytes); |
---|
| 150 | + if (ret) { |
---|
| 151 | + dev_err(afe->dev, "%s(), error, id %d, set addr, ret %d\n", |
---|
| 152 | + __func__, id, ret); |
---|
131 | 153 | return ret; |
---|
132 | | - |
---|
133 | | - msb_at_bit33 = upper_32_bits(substream->runtime->dma_addr) ? 1 : 0; |
---|
134 | | - memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr); |
---|
135 | | - memif->buffer_size = substream->runtime->dma_bytes; |
---|
136 | | - |
---|
137 | | - /* start */ |
---|
138 | | - mtk_regmap_write(afe->regmap, memif->data->reg_ofs_base, |
---|
139 | | - memif->phys_buf_addr); |
---|
140 | | - /* end */ |
---|
141 | | - mtk_regmap_write(afe->regmap, |
---|
142 | | - memif->data->reg_ofs_base + AFE_BASE_END_OFFSET, |
---|
143 | | - memif->phys_buf_addr + memif->buffer_size - 1); |
---|
144 | | - |
---|
145 | | - /* set MSB to 33-bit */ |
---|
146 | | - mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg, |
---|
147 | | - 1 << memif->data->msb_shift, |
---|
148 | | - msb_at_bit33 << memif->data->msb_shift); |
---|
| 154 | + } |
---|
149 | 155 | |
---|
150 | 156 | /* set channel */ |
---|
151 | | - if (memif->data->mono_shift >= 0) { |
---|
152 | | - unsigned int mono = (params_channels(params) == 1) ? 1 : 0; |
---|
153 | | - |
---|
154 | | - mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg, |
---|
155 | | - 1 << memif->data->mono_shift, |
---|
156 | | - mono << memif->data->mono_shift); |
---|
| 157 | + ret = mtk_memif_set_channel(afe, id, channels); |
---|
| 158 | + if (ret) { |
---|
| 159 | + dev_err(afe->dev, "%s(), error, id %d, set channel %d, ret %d\n", |
---|
| 160 | + __func__, id, channels, ret); |
---|
| 161 | + return ret; |
---|
157 | 162 | } |
---|
158 | 163 | |
---|
159 | 164 | /* set rate */ |
---|
160 | | - if (memif->data->fs_shift < 0) |
---|
161 | | - return 0; |
---|
| 165 | + ret = mtk_memif_set_rate_substream(substream, id, rate); |
---|
| 166 | + if (ret) { |
---|
| 167 | + dev_err(afe->dev, "%s(), error, id %d, set rate %d, ret %d\n", |
---|
| 168 | + __func__, id, rate, ret); |
---|
| 169 | + return ret; |
---|
| 170 | + } |
---|
162 | 171 | |
---|
163 | | - fs = afe->memif_fs(substream, params_rate(params)); |
---|
164 | | - |
---|
165 | | - if (fs < 0) |
---|
166 | | - return -EINVAL; |
---|
167 | | - |
---|
168 | | - mtk_regmap_update_bits(afe->regmap, memif->data->fs_reg, |
---|
169 | | - memif->data->fs_maskbit << memif->data->fs_shift, |
---|
170 | | - fs << memif->data->fs_shift); |
---|
| 172 | + /* set format */ |
---|
| 173 | + ret = mtk_memif_set_format(afe, id, format); |
---|
| 174 | + if (ret) { |
---|
| 175 | + dev_err(afe->dev, "%s(), error, id %d, set format %d, ret %d\n", |
---|
| 176 | + __func__, id, format, ret); |
---|
| 177 | + return ret; |
---|
| 178 | + } |
---|
171 | 179 | |
---|
172 | 180 | return 0; |
---|
173 | 181 | } |
---|
.. | .. |
---|
176 | 184 | int mtk_afe_fe_hw_free(struct snd_pcm_substream *substream, |
---|
177 | 185 | struct snd_soc_dai *dai) |
---|
178 | 186 | { |
---|
179 | | - return snd_pcm_lib_free_pages(substream); |
---|
| 187 | + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); |
---|
| 188 | + |
---|
| 189 | + if (afe->release_dram_resource) |
---|
| 190 | + afe->release_dram_resource(afe->dev); |
---|
| 191 | + |
---|
| 192 | + return 0; |
---|
180 | 193 | } |
---|
181 | 194 | EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_free); |
---|
182 | 195 | |
---|
183 | 196 | int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd, |
---|
184 | 197 | struct snd_soc_dai *dai) |
---|
185 | 198 | { |
---|
186 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
---|
| 199 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
---|
187 | 200 | struct snd_pcm_runtime * const runtime = substream->runtime; |
---|
188 | 201 | struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); |
---|
189 | | - struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; |
---|
| 202 | + int id = asoc_rtd_to_cpu(rtd, 0)->id; |
---|
| 203 | + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
---|
190 | 204 | struct mtk_base_afe_irq *irqs = &afe->irqs[memif->irq_usage]; |
---|
191 | 205 | const struct mtk_base_irq_data *irq_data = irqs->irq_data; |
---|
192 | 206 | unsigned int counter = runtime->period_size; |
---|
193 | 207 | int fs; |
---|
| 208 | + int ret; |
---|
194 | 209 | |
---|
195 | 210 | dev_dbg(afe->dev, "%s %s cmd=%d\n", __func__, memif->data->name, cmd); |
---|
196 | 211 | |
---|
197 | 212 | switch (cmd) { |
---|
198 | 213 | case SNDRV_PCM_TRIGGER_START: |
---|
199 | 214 | case SNDRV_PCM_TRIGGER_RESUME: |
---|
200 | | - if (memif->data->enable_shift >= 0) |
---|
201 | | - mtk_regmap_update_bits(afe->regmap, |
---|
202 | | - memif->data->enable_reg, |
---|
203 | | - 1 << memif->data->enable_shift, |
---|
204 | | - 1 << memif->data->enable_shift); |
---|
| 215 | + ret = mtk_memif_set_enable(afe, id); |
---|
| 216 | + if (ret) { |
---|
| 217 | + dev_err(afe->dev, "%s(), error, id %d, memif enable, ret %d\n", |
---|
| 218 | + __func__, id, ret); |
---|
| 219 | + return ret; |
---|
| 220 | + } |
---|
205 | 221 | |
---|
206 | 222 | /* set irq counter */ |
---|
207 | 223 | mtk_regmap_update_bits(afe->regmap, irq_data->irq_cnt_reg, |
---|
208 | | - irq_data->irq_cnt_maskbit |
---|
209 | | - << irq_data->irq_cnt_shift, |
---|
210 | | - counter << irq_data->irq_cnt_shift); |
---|
| 224 | + irq_data->irq_cnt_maskbit, counter, |
---|
| 225 | + irq_data->irq_cnt_shift); |
---|
211 | 226 | |
---|
212 | 227 | /* set irq fs */ |
---|
213 | 228 | fs = afe->irq_fs(substream, runtime->rate); |
---|
.. | .. |
---|
216 | 231 | return -EINVAL; |
---|
217 | 232 | |
---|
218 | 233 | mtk_regmap_update_bits(afe->regmap, irq_data->irq_fs_reg, |
---|
219 | | - irq_data->irq_fs_maskbit |
---|
220 | | - << irq_data->irq_fs_shift, |
---|
221 | | - fs << irq_data->irq_fs_shift); |
---|
| 234 | + irq_data->irq_fs_maskbit, fs, |
---|
| 235 | + irq_data->irq_fs_shift); |
---|
222 | 236 | |
---|
223 | 237 | /* enable interrupt */ |
---|
224 | 238 | mtk_regmap_update_bits(afe->regmap, irq_data->irq_en_reg, |
---|
225 | | - 1 << irq_data->irq_en_shift, |
---|
226 | | - 1 << irq_data->irq_en_shift); |
---|
| 239 | + 1, 1, irq_data->irq_en_shift); |
---|
227 | 240 | |
---|
228 | 241 | return 0; |
---|
229 | 242 | case SNDRV_PCM_TRIGGER_STOP: |
---|
230 | 243 | case SNDRV_PCM_TRIGGER_SUSPEND: |
---|
231 | | - mtk_regmap_update_bits(afe->regmap, memif->data->enable_reg, |
---|
232 | | - 1 << memif->data->enable_shift, 0); |
---|
| 244 | + ret = mtk_memif_set_disable(afe, id); |
---|
| 245 | + if (ret) { |
---|
| 246 | + dev_err(afe->dev, "%s(), error, id %d, memif enable, ret %d\n", |
---|
| 247 | + __func__, id, ret); |
---|
| 248 | + } |
---|
| 249 | + |
---|
233 | 250 | /* disable interrupt */ |
---|
234 | 251 | mtk_regmap_update_bits(afe->regmap, irq_data->irq_en_reg, |
---|
235 | | - 1 << irq_data->irq_en_shift, |
---|
236 | | - 0 << irq_data->irq_en_shift); |
---|
| 252 | + 1, 0, irq_data->irq_en_shift); |
---|
237 | 253 | /* and clear pending IRQ */ |
---|
238 | 254 | mtk_regmap_write(afe->regmap, irq_data->irq_clr_reg, |
---|
239 | 255 | 1 << irq_data->irq_clr_shift); |
---|
240 | | - return 0; |
---|
| 256 | + return ret; |
---|
241 | 257 | default: |
---|
242 | 258 | return -EINVAL; |
---|
243 | 259 | } |
---|
.. | .. |
---|
247 | 263 | int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, |
---|
248 | 264 | struct snd_soc_dai *dai) |
---|
249 | 265 | { |
---|
250 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
---|
| 266 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
---|
251 | 267 | struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); |
---|
252 | | - struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; |
---|
253 | | - int hd_audio = 0; |
---|
| 268 | + int id = asoc_rtd_to_cpu(rtd, 0)->id; |
---|
| 269 | + int pbuf_size; |
---|
254 | 270 | |
---|
255 | | - /* set hd mode */ |
---|
256 | | - switch (substream->runtime->format) { |
---|
257 | | - case SNDRV_PCM_FORMAT_S16_LE: |
---|
258 | | - hd_audio = 0; |
---|
259 | | - break; |
---|
260 | | - case SNDRV_PCM_FORMAT_S32_LE: |
---|
261 | | - hd_audio = 1; |
---|
262 | | - break; |
---|
263 | | - case SNDRV_PCM_FORMAT_S24_LE: |
---|
264 | | - hd_audio = 1; |
---|
265 | | - break; |
---|
266 | | - default: |
---|
267 | | - dev_err(afe->dev, "%s() error: unsupported format %d\n", |
---|
268 | | - __func__, substream->runtime->format); |
---|
269 | | - break; |
---|
| 271 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
---|
| 272 | + if (afe->get_memif_pbuf_size) { |
---|
| 273 | + pbuf_size = afe->get_memif_pbuf_size(substream); |
---|
| 274 | + mtk_memif_set_pbuf_size(afe, id, pbuf_size); |
---|
| 275 | + } |
---|
270 | 276 | } |
---|
271 | | - |
---|
272 | | - mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg, |
---|
273 | | - 1 << memif->data->hd_shift, |
---|
274 | | - hd_audio << memif->data->hd_shift); |
---|
275 | | - |
---|
276 | 277 | return 0; |
---|
277 | 278 | } |
---|
278 | 279 | EXPORT_SYMBOL_GPL(mtk_afe_fe_prepare); |
---|
.. | .. |
---|
318 | 319 | } |
---|
319 | 320 | EXPORT_SYMBOL_GPL(mtk_dynamic_irq_release); |
---|
320 | 321 | |
---|
321 | | -int mtk_afe_dai_suspend(struct snd_soc_dai *dai) |
---|
| 322 | +int mtk_afe_suspend(struct snd_soc_component *component) |
---|
322 | 323 | { |
---|
323 | | - struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); |
---|
| 324 | + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); |
---|
324 | 325 | struct device *dev = afe->dev; |
---|
325 | 326 | struct regmap *regmap = afe->regmap; |
---|
326 | 327 | int i; |
---|
.. | .. |
---|
341 | 342 | afe->runtime_suspend(dev); |
---|
342 | 343 | return 0; |
---|
343 | 344 | } |
---|
344 | | -EXPORT_SYMBOL_GPL(mtk_afe_dai_suspend); |
---|
| 345 | +EXPORT_SYMBOL_GPL(mtk_afe_suspend); |
---|
345 | 346 | |
---|
346 | | -int mtk_afe_dai_resume(struct snd_soc_dai *dai) |
---|
| 347 | +int mtk_afe_resume(struct snd_soc_component *component) |
---|
347 | 348 | { |
---|
348 | | - struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); |
---|
| 349 | + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); |
---|
349 | 350 | struct device *dev = afe->dev; |
---|
350 | 351 | struct regmap *regmap = afe->regmap; |
---|
351 | 352 | int i = 0; |
---|
.. | .. |
---|
365 | 366 | afe->suspended = false; |
---|
366 | 367 | return 0; |
---|
367 | 368 | } |
---|
368 | | -EXPORT_SYMBOL_GPL(mtk_afe_dai_resume); |
---|
| 369 | +EXPORT_SYMBOL_GPL(mtk_afe_resume); |
---|
| 370 | + |
---|
| 371 | +int mtk_memif_set_enable(struct mtk_base_afe *afe, int id) |
---|
| 372 | +{ |
---|
| 373 | + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
---|
| 374 | + |
---|
| 375 | + if (memif->data->enable_shift < 0) { |
---|
| 376 | + dev_warn(afe->dev, "%s(), error, id %d, enable_shift < 0\n", |
---|
| 377 | + __func__, id); |
---|
| 378 | + return 0; |
---|
| 379 | + } |
---|
| 380 | + return mtk_regmap_update_bits(afe->regmap, memif->data->enable_reg, |
---|
| 381 | + 1, 1, memif->data->enable_shift); |
---|
| 382 | +} |
---|
| 383 | +EXPORT_SYMBOL_GPL(mtk_memif_set_enable); |
---|
| 384 | + |
---|
| 385 | +int mtk_memif_set_disable(struct mtk_base_afe *afe, int id) |
---|
| 386 | +{ |
---|
| 387 | + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
---|
| 388 | + |
---|
| 389 | + if (memif->data->enable_shift < 0) { |
---|
| 390 | + dev_warn(afe->dev, "%s(), error, id %d, enable_shift < 0\n", |
---|
| 391 | + __func__, id); |
---|
| 392 | + return 0; |
---|
| 393 | + } |
---|
| 394 | + return mtk_regmap_update_bits(afe->regmap, memif->data->enable_reg, |
---|
| 395 | + 1, 0, memif->data->enable_shift); |
---|
| 396 | +} |
---|
| 397 | +EXPORT_SYMBOL_GPL(mtk_memif_set_disable); |
---|
| 398 | + |
---|
| 399 | +int mtk_memif_set_addr(struct mtk_base_afe *afe, int id, |
---|
| 400 | + unsigned char *dma_area, |
---|
| 401 | + dma_addr_t dma_addr, |
---|
| 402 | + size_t dma_bytes) |
---|
| 403 | +{ |
---|
| 404 | + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
---|
| 405 | + int msb_at_bit33 = upper_32_bits(dma_addr) ? 1 : 0; |
---|
| 406 | + unsigned int phys_buf_addr = lower_32_bits(dma_addr); |
---|
| 407 | + unsigned int phys_buf_addr_upper_32 = upper_32_bits(dma_addr); |
---|
| 408 | + |
---|
| 409 | + memif->dma_area = dma_area; |
---|
| 410 | + memif->dma_addr = dma_addr; |
---|
| 411 | + memif->dma_bytes = dma_bytes; |
---|
| 412 | + |
---|
| 413 | + /* start */ |
---|
| 414 | + mtk_regmap_write(afe->regmap, memif->data->reg_ofs_base, |
---|
| 415 | + phys_buf_addr); |
---|
| 416 | + /* end */ |
---|
| 417 | + if (memif->data->reg_ofs_end) |
---|
| 418 | + mtk_regmap_write(afe->regmap, |
---|
| 419 | + memif->data->reg_ofs_end, |
---|
| 420 | + phys_buf_addr + dma_bytes - 1); |
---|
| 421 | + else |
---|
| 422 | + mtk_regmap_write(afe->regmap, |
---|
| 423 | + memif->data->reg_ofs_base + |
---|
| 424 | + AFE_BASE_END_OFFSET, |
---|
| 425 | + phys_buf_addr + dma_bytes - 1); |
---|
| 426 | + |
---|
| 427 | + /* set start, end, upper 32 bits */ |
---|
| 428 | + if (memif->data->reg_ofs_base_msb) { |
---|
| 429 | + mtk_regmap_write(afe->regmap, memif->data->reg_ofs_base_msb, |
---|
| 430 | + phys_buf_addr_upper_32); |
---|
| 431 | + mtk_regmap_write(afe->regmap, |
---|
| 432 | + memif->data->reg_ofs_end_msb, |
---|
| 433 | + phys_buf_addr_upper_32); |
---|
| 434 | + } |
---|
| 435 | + |
---|
| 436 | + /* set MSB to 33-bit */ |
---|
| 437 | + if (memif->data->msb_reg >= 0) |
---|
| 438 | + mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg, |
---|
| 439 | + 1, msb_at_bit33, memif->data->msb_shift); |
---|
| 440 | + |
---|
| 441 | + return 0; |
---|
| 442 | +} |
---|
| 443 | +EXPORT_SYMBOL_GPL(mtk_memif_set_addr); |
---|
| 444 | + |
---|
| 445 | +int mtk_memif_set_channel(struct mtk_base_afe *afe, |
---|
| 446 | + int id, unsigned int channel) |
---|
| 447 | +{ |
---|
| 448 | + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
---|
| 449 | + unsigned int mono; |
---|
| 450 | + |
---|
| 451 | + if (memif->data->mono_shift < 0) |
---|
| 452 | + return 0; |
---|
| 453 | + |
---|
| 454 | + if (memif->data->quad_ch_mask) { |
---|
| 455 | + unsigned int quad_ch = (channel == 4) ? 1 : 0; |
---|
| 456 | + |
---|
| 457 | + mtk_regmap_update_bits(afe->regmap, memif->data->quad_ch_reg, |
---|
| 458 | + memif->data->quad_ch_mask, |
---|
| 459 | + quad_ch, memif->data->quad_ch_shift); |
---|
| 460 | + } |
---|
| 461 | + |
---|
| 462 | + if (memif->data->mono_invert) |
---|
| 463 | + mono = (channel == 1) ? 0 : 1; |
---|
| 464 | + else |
---|
| 465 | + mono = (channel == 1) ? 1 : 0; |
---|
| 466 | + |
---|
| 467 | + return mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg, |
---|
| 468 | + 1, mono, memif->data->mono_shift); |
---|
| 469 | +} |
---|
| 470 | +EXPORT_SYMBOL_GPL(mtk_memif_set_channel); |
---|
| 471 | + |
---|
| 472 | +static int mtk_memif_set_rate_fs(struct mtk_base_afe *afe, |
---|
| 473 | + int id, int fs) |
---|
| 474 | +{ |
---|
| 475 | + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
---|
| 476 | + |
---|
| 477 | + if (memif->data->fs_shift >= 0) |
---|
| 478 | + mtk_regmap_update_bits(afe->regmap, memif->data->fs_reg, |
---|
| 479 | + memif->data->fs_maskbit, |
---|
| 480 | + fs, memif->data->fs_shift); |
---|
| 481 | + |
---|
| 482 | + return 0; |
---|
| 483 | +} |
---|
| 484 | + |
---|
| 485 | +int mtk_memif_set_rate(struct mtk_base_afe *afe, |
---|
| 486 | + int id, unsigned int rate) |
---|
| 487 | +{ |
---|
| 488 | + int fs = 0; |
---|
| 489 | + |
---|
| 490 | + if (!afe->get_dai_fs) { |
---|
| 491 | + dev_err(afe->dev, "%s(), error, afe->get_dai_fs == NULL\n", |
---|
| 492 | + __func__); |
---|
| 493 | + return -EINVAL; |
---|
| 494 | + } |
---|
| 495 | + |
---|
| 496 | + fs = afe->get_dai_fs(afe, id, rate); |
---|
| 497 | + |
---|
| 498 | + if (fs < 0) |
---|
| 499 | + return -EINVAL; |
---|
| 500 | + |
---|
| 501 | + return mtk_memif_set_rate_fs(afe, id, fs); |
---|
| 502 | +} |
---|
| 503 | +EXPORT_SYMBOL_GPL(mtk_memif_set_rate); |
---|
| 504 | + |
---|
| 505 | +int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream, |
---|
| 506 | + int id, unsigned int rate) |
---|
| 507 | +{ |
---|
| 508 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
---|
| 509 | + struct snd_soc_component *component = |
---|
| 510 | + snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); |
---|
| 511 | + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); |
---|
| 512 | + |
---|
| 513 | + int fs = 0; |
---|
| 514 | + |
---|
| 515 | + if (!afe->memif_fs) { |
---|
| 516 | + dev_err(afe->dev, "%s(), error, afe->memif_fs == NULL\n", |
---|
| 517 | + __func__); |
---|
| 518 | + return -EINVAL; |
---|
| 519 | + } |
---|
| 520 | + |
---|
| 521 | + fs = afe->memif_fs(substream, rate); |
---|
| 522 | + |
---|
| 523 | + if (fs < 0) |
---|
| 524 | + return -EINVAL; |
---|
| 525 | + |
---|
| 526 | + return mtk_memif_set_rate_fs(afe, id, fs); |
---|
| 527 | +} |
---|
| 528 | +EXPORT_SYMBOL_GPL(mtk_memif_set_rate_substream); |
---|
| 529 | + |
---|
| 530 | +int mtk_memif_set_format(struct mtk_base_afe *afe, |
---|
| 531 | + int id, snd_pcm_format_t format) |
---|
| 532 | +{ |
---|
| 533 | + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
---|
| 534 | + int hd_audio = 0; |
---|
| 535 | + int hd_align = 0; |
---|
| 536 | + |
---|
| 537 | + /* set hd mode */ |
---|
| 538 | + switch (format) { |
---|
| 539 | + case SNDRV_PCM_FORMAT_S16_LE: |
---|
| 540 | + case SNDRV_PCM_FORMAT_U16_LE: |
---|
| 541 | + hd_audio = 0; |
---|
| 542 | + break; |
---|
| 543 | + case SNDRV_PCM_FORMAT_S32_LE: |
---|
| 544 | + case SNDRV_PCM_FORMAT_U32_LE: |
---|
| 545 | + hd_audio = 1; |
---|
| 546 | + hd_align = 1; |
---|
| 547 | + break; |
---|
| 548 | + case SNDRV_PCM_FORMAT_S24_LE: |
---|
| 549 | + case SNDRV_PCM_FORMAT_U24_LE: |
---|
| 550 | + hd_audio = 1; |
---|
| 551 | + break; |
---|
| 552 | + default: |
---|
| 553 | + dev_err(afe->dev, "%s() error: unsupported format %d\n", |
---|
| 554 | + __func__, format); |
---|
| 555 | + break; |
---|
| 556 | + } |
---|
| 557 | + |
---|
| 558 | + mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg, |
---|
| 559 | + 1, hd_audio, memif->data->hd_shift); |
---|
| 560 | + |
---|
| 561 | + mtk_regmap_update_bits(afe->regmap, memif->data->hd_align_reg, |
---|
| 562 | + 1, hd_align, memif->data->hd_align_mshift); |
---|
| 563 | + |
---|
| 564 | + return 0; |
---|
| 565 | +} |
---|
| 566 | +EXPORT_SYMBOL_GPL(mtk_memif_set_format); |
---|
| 567 | + |
---|
| 568 | +int mtk_memif_set_pbuf_size(struct mtk_base_afe *afe, |
---|
| 569 | + int id, int pbuf_size) |
---|
| 570 | +{ |
---|
| 571 | + const struct mtk_base_memif_data *memif_data = afe->memif[id].data; |
---|
| 572 | + |
---|
| 573 | + if (memif_data->pbuf_mask == 0 || memif_data->minlen_mask == 0) |
---|
| 574 | + return 0; |
---|
| 575 | + |
---|
| 576 | + mtk_regmap_update_bits(afe->regmap, memif_data->pbuf_reg, |
---|
| 577 | + memif_data->pbuf_mask, |
---|
| 578 | + pbuf_size, memif_data->pbuf_shift); |
---|
| 579 | + |
---|
| 580 | + mtk_regmap_update_bits(afe->regmap, memif_data->minlen_reg, |
---|
| 581 | + memif_data->minlen_mask, |
---|
| 582 | + pbuf_size, memif_data->minlen_shift); |
---|
| 583 | + return 0; |
---|
| 584 | +} |
---|
| 585 | +EXPORT_SYMBOL_GPL(mtk_memif_set_pbuf_size); |
---|
369 | 586 | |
---|
370 | 587 | MODULE_DESCRIPTION("Mediatek simple fe dai operator"); |
---|
371 | 588 | MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>"); |
---|