]> Git Repo - linux.git/blob - sound/soc/tegra/tegra210_admaif.c
net: dsa: flush switchdev workqueue before tearing down CPU/DSA ports
[linux.git] / sound / soc / tegra / tegra210_admaif.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // tegra210_admaif.c - Tegra ADMAIF driver
4 //
5 // Copyright (c) 2020 NVIDIA CORPORATION.  All rights reserved.
6
7 #include <linux/clk.h>
8 #include <linux/device.h>
9 #include <linux/module.h>
10 #include <linux/of_platform.h>
11 #include <linux/platform_device.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/regmap.h>
14 #include <sound/pcm_params.h>
15 #include <sound/soc.h>
16 #include "tegra210_admaif.h"
17 #include "tegra_cif.h"
18 #include "tegra_pcm.h"
19
20 #define CH_REG(offset, reg, id)                                                \
21         ((offset) + (reg) + (TEGRA_ADMAIF_CHANNEL_REG_STRIDE * (id)))
22
23 #define CH_TX_REG(reg, id) CH_REG(admaif->soc_data->tx_base, reg, id)
24
25 #define CH_RX_REG(reg, id) CH_REG(admaif->soc_data->rx_base, reg, id)
26
27 #define REG_DEFAULTS(id, rx_ctrl, tx_ctrl, tx_base, rx_base)                   \
28         { CH_REG(rx_base, TEGRA_ADMAIF_RX_INT_MASK, id), 0x00000001 },         \
29         { CH_REG(rx_base, TEGRA_ADMAIF_CH_ACIF_RX_CTRL, id), 0x00007700 },     \
30         { CH_REG(rx_base, TEGRA_ADMAIF_RX_FIFO_CTRL, id), rx_ctrl },           \
31         { CH_REG(tx_base, TEGRA_ADMAIF_TX_INT_MASK, id), 0x00000001 },         \
32         { CH_REG(tx_base, TEGRA_ADMAIF_CH_ACIF_TX_CTRL, id), 0x00007700 },     \
33         { CH_REG(tx_base, TEGRA_ADMAIF_TX_FIFO_CTRL, id), tx_ctrl }
34
35 #define ADMAIF_REG_DEFAULTS(id, chip)                                          \
36         REG_DEFAULTS((id) - 1,                                                 \
37                 chip ## _ADMAIF_RX ## id ## _FIFO_CTRL_REG_DEFAULT,            \
38                 chip ## _ADMAIF_TX ## id ## _FIFO_CTRL_REG_DEFAULT,            \
39                 chip ## _ADMAIF_TX_BASE,                                       \
40                 chip ## _ADMAIF_RX_BASE)
41
42 static const struct reg_default tegra186_admaif_reg_defaults[] = {
43         {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA186_ADMAIF_GLOBAL_BASE), 0x00000003},
44         ADMAIF_REG_DEFAULTS(1, TEGRA186),
45         ADMAIF_REG_DEFAULTS(2, TEGRA186),
46         ADMAIF_REG_DEFAULTS(3, TEGRA186),
47         ADMAIF_REG_DEFAULTS(4, TEGRA186),
48         ADMAIF_REG_DEFAULTS(5, TEGRA186),
49         ADMAIF_REG_DEFAULTS(6, TEGRA186),
50         ADMAIF_REG_DEFAULTS(7, TEGRA186),
51         ADMAIF_REG_DEFAULTS(8, TEGRA186),
52         ADMAIF_REG_DEFAULTS(9, TEGRA186),
53         ADMAIF_REG_DEFAULTS(10, TEGRA186),
54         ADMAIF_REG_DEFAULTS(11, TEGRA186),
55         ADMAIF_REG_DEFAULTS(12, TEGRA186),
56         ADMAIF_REG_DEFAULTS(13, TEGRA186),
57         ADMAIF_REG_DEFAULTS(14, TEGRA186),
58         ADMAIF_REG_DEFAULTS(15, TEGRA186),
59         ADMAIF_REG_DEFAULTS(16, TEGRA186),
60         ADMAIF_REG_DEFAULTS(17, TEGRA186),
61         ADMAIF_REG_DEFAULTS(18, TEGRA186),
62         ADMAIF_REG_DEFAULTS(19, TEGRA186),
63         ADMAIF_REG_DEFAULTS(20, TEGRA186)
64 };
65
66 static const struct reg_default tegra210_admaif_reg_defaults[] = {
67         {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA210_ADMAIF_GLOBAL_BASE), 0x00000003},
68         ADMAIF_REG_DEFAULTS(1, TEGRA210),
69         ADMAIF_REG_DEFAULTS(2, TEGRA210),
70         ADMAIF_REG_DEFAULTS(3, TEGRA210),
71         ADMAIF_REG_DEFAULTS(4, TEGRA210),
72         ADMAIF_REG_DEFAULTS(5, TEGRA210),
73         ADMAIF_REG_DEFAULTS(6, TEGRA210),
74         ADMAIF_REG_DEFAULTS(7, TEGRA210),
75         ADMAIF_REG_DEFAULTS(8, TEGRA210),
76         ADMAIF_REG_DEFAULTS(9, TEGRA210),
77         ADMAIF_REG_DEFAULTS(10, TEGRA210)
78 };
79
80 static bool tegra_admaif_wr_reg(struct device *dev, unsigned int reg)
81 {
82         struct tegra_admaif *admaif = dev_get_drvdata(dev);
83         unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
84         unsigned int num_ch = admaif->soc_data->num_ch;
85         unsigned int rx_base = admaif->soc_data->rx_base;
86         unsigned int tx_base = admaif->soc_data->tx_base;
87         unsigned int global_base = admaif->soc_data->global_base;
88         unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
89         unsigned int rx_max = rx_base + (num_ch * ch_stride);
90         unsigned int tx_max = tx_base + (num_ch * ch_stride);
91
92         if ((reg >= rx_base) && (reg < rx_max)) {
93                 reg = (reg - rx_base) % ch_stride;
94                 if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
95                     (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) ||
96                     (reg == TEGRA_ADMAIF_RX_SOFT_RESET) ||
97                     (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL))
98                         return true;
99         } else if ((reg >= tx_base) && (reg < tx_max)) {
100                 reg = (reg - tx_base) % ch_stride;
101                 if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
102                     (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) ||
103                     (reg == TEGRA_ADMAIF_TX_SOFT_RESET) ||
104                     (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL))
105                         return true;
106         } else if ((reg >= global_base) && (reg < reg_max)) {
107                 if (reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE))
108                         return true;
109         }
110
111         return false;
112 }
113
114 static bool tegra_admaif_rd_reg(struct device *dev, unsigned int reg)
115 {
116         struct tegra_admaif *admaif = dev_get_drvdata(dev);
117         unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
118         unsigned int num_ch = admaif->soc_data->num_ch;
119         unsigned int rx_base = admaif->soc_data->rx_base;
120         unsigned int tx_base = admaif->soc_data->tx_base;
121         unsigned int global_base = admaif->soc_data->global_base;
122         unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
123         unsigned int rx_max = rx_base + (num_ch * ch_stride);
124         unsigned int tx_max = tx_base + (num_ch * ch_stride);
125
126         if ((reg >= rx_base) && (reg < rx_max)) {
127                 reg = (reg - rx_base) % ch_stride;
128                 if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
129                     (reg == TEGRA_ADMAIF_RX_STATUS) ||
130                     (reg == TEGRA_ADMAIF_RX_INT_STATUS) ||
131                     (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) ||
132                     (reg == TEGRA_ADMAIF_RX_SOFT_RESET) ||
133                     (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL))
134                         return true;
135         } else if ((reg >= tx_base) && (reg < tx_max)) {
136                 reg = (reg - tx_base) % ch_stride;
137                 if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
138                     (reg == TEGRA_ADMAIF_TX_STATUS) ||
139                     (reg == TEGRA_ADMAIF_TX_INT_STATUS) ||
140                     (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) ||
141                     (reg == TEGRA_ADMAIF_TX_SOFT_RESET) ||
142                     (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL))
143                         return true;
144         } else if ((reg >= global_base) && (reg < reg_max)) {
145                 if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE)) ||
146                     (reg == (global_base + TEGRA_ADMAIF_GLOBAL_CG_0)) ||
147                     (reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) ||
148                     (reg == (global_base +
149                                 TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) ||
150                     (reg == (global_base +
151                                 TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS)))
152                         return true;
153         }
154
155         return false;
156 }
157
158 static bool tegra_admaif_volatile_reg(struct device *dev, unsigned int reg)
159 {
160         struct tegra_admaif *admaif = dev_get_drvdata(dev);
161         unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
162         unsigned int num_ch = admaif->soc_data->num_ch;
163         unsigned int rx_base = admaif->soc_data->rx_base;
164         unsigned int tx_base = admaif->soc_data->tx_base;
165         unsigned int global_base = admaif->soc_data->global_base;
166         unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
167         unsigned int rx_max = rx_base + (num_ch * ch_stride);
168         unsigned int tx_max = tx_base + (num_ch * ch_stride);
169
170         if ((reg >= rx_base) && (reg < rx_max)) {
171                 reg = (reg - rx_base) % ch_stride;
172                 if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
173                     (reg == TEGRA_ADMAIF_RX_STATUS) ||
174                     (reg == TEGRA_ADMAIF_RX_INT_STATUS) ||
175                     (reg == TEGRA_ADMAIF_RX_SOFT_RESET))
176                         return true;
177         } else if ((reg >= tx_base) && (reg < tx_max)) {
178                 reg = (reg - tx_base) % ch_stride;
179                 if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
180                     (reg == TEGRA_ADMAIF_TX_STATUS) ||
181                     (reg == TEGRA_ADMAIF_TX_INT_STATUS) ||
182                     (reg == TEGRA_ADMAIF_TX_SOFT_RESET))
183                         return true;
184         } else if ((reg >= global_base) && (reg < reg_max)) {
185                 if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) ||
186                     (reg == (global_base +
187                                 TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) ||
188                     (reg == (global_base +
189                                 TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS)))
190                         return true;
191         }
192
193         return false;
194 }
195
196 static const struct regmap_config tegra210_admaif_regmap_config = {
197         .reg_bits               = 32,
198         .reg_stride             = 4,
199         .val_bits               = 32,
200         .max_register           = TEGRA210_ADMAIF_LAST_REG,
201         .writeable_reg          = tegra_admaif_wr_reg,
202         .readable_reg           = tegra_admaif_rd_reg,
203         .volatile_reg           = tegra_admaif_volatile_reg,
204         .reg_defaults           = tegra210_admaif_reg_defaults,
205         .num_reg_defaults       = TEGRA210_ADMAIF_CHANNEL_COUNT * 6 + 1,
206         .cache_type             = REGCACHE_FLAT,
207 };
208
209 static const struct regmap_config tegra186_admaif_regmap_config = {
210         .reg_bits               = 32,
211         .reg_stride             = 4,
212         .val_bits               = 32,
213         .max_register           = TEGRA186_ADMAIF_LAST_REG,
214         .writeable_reg          = tegra_admaif_wr_reg,
215         .readable_reg           = tegra_admaif_rd_reg,
216         .volatile_reg           = tegra_admaif_volatile_reg,
217         .reg_defaults           = tegra186_admaif_reg_defaults,
218         .num_reg_defaults       = TEGRA186_ADMAIF_CHANNEL_COUNT * 6 + 1,
219         .cache_type             = REGCACHE_FLAT,
220 };
221
222 static int __maybe_unused tegra_admaif_runtime_suspend(struct device *dev)
223 {
224         struct tegra_admaif *admaif = dev_get_drvdata(dev);
225
226         regcache_cache_only(admaif->regmap, true);
227         regcache_mark_dirty(admaif->regmap);
228
229         return 0;
230 }
231
232 static int __maybe_unused tegra_admaif_runtime_resume(struct device *dev)
233 {
234         struct tegra_admaif *admaif = dev_get_drvdata(dev);
235
236         regcache_cache_only(admaif->regmap, false);
237         regcache_sync(admaif->regmap);
238
239         return 0;
240 }
241
242 static int tegra_admaif_set_pack_mode(struct regmap *map, unsigned int reg,
243                                       int valid_bit)
244 {
245         switch (valid_bit) {
246         case DATA_8BIT:
247                 regmap_update_bits(map, reg, PACK8_EN_MASK, PACK8_EN);
248                 regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
249                 break;
250         case DATA_16BIT:
251                 regmap_update_bits(map, reg, PACK16_EN_MASK, PACK16_EN);
252                 regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
253                 break;
254         case DATA_32BIT:
255                 regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
256                 regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
257                 break;
258         default:
259                 return -EINVAL;
260         }
261
262         return 0;
263 }
264
265 static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
266                                   struct snd_pcm_hw_params *params,
267                                   struct snd_soc_dai *dai)
268 {
269         struct device *dev = dai->dev;
270         struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
271         struct tegra_cif_conf cif_conf;
272         unsigned int reg, path;
273         int valid_bit, channels;
274
275         memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
276
277         switch (params_format(params)) {
278         case SNDRV_PCM_FORMAT_S8:
279                 cif_conf.audio_bits = TEGRA_ACIF_BITS_8;
280                 cif_conf.client_bits = TEGRA_ACIF_BITS_8;
281                 valid_bit = DATA_8BIT;
282                 break;
283         case SNDRV_PCM_FORMAT_S16_LE:
284                 cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
285                 cif_conf.client_bits = TEGRA_ACIF_BITS_16;
286                 valid_bit = DATA_16BIT;
287                 break;
288         case SNDRV_PCM_FORMAT_S32_LE:
289                 cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
290                 cif_conf.client_bits = TEGRA_ACIF_BITS_32;
291                 valid_bit  = DATA_32BIT;
292                 break;
293         default:
294                 dev_err(dev, "unsupported format!\n");
295                 return -EOPNOTSUPP;
296         }
297
298         channels = params_channels(params);
299         cif_conf.client_ch = channels;
300         cif_conf.audio_ch = channels;
301
302         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
303                 path = ADMAIF_TX_PATH;
304                 reg = CH_TX_REG(TEGRA_ADMAIF_CH_ACIF_TX_CTRL, dai->id);
305         } else {
306                 path = ADMAIF_RX_PATH;
307                 reg = CH_RX_REG(TEGRA_ADMAIF_CH_ACIF_RX_CTRL, dai->id);
308         }
309
310         cif_conf.mono_conv = admaif->mono_to_stereo[path][dai->id];
311         cif_conf.stereo_conv = admaif->stereo_to_mono[path][dai->id];
312
313         tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit);
314
315         tegra_set_cif(admaif->regmap, reg, &cif_conf);
316
317         return 0;
318 }
319
320 static int tegra_admaif_start(struct snd_soc_dai *dai, int direction)
321 {
322         struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
323         unsigned int reg, mask, val;
324
325         switch (direction) {
326         case SNDRV_PCM_STREAM_PLAYBACK:
327                 mask = TX_ENABLE_MASK;
328                 val = TX_ENABLE;
329                 reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
330                 break;
331         case SNDRV_PCM_STREAM_CAPTURE:
332                 mask = RX_ENABLE_MASK;
333                 val = RX_ENABLE;
334                 reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
335                 break;
336         default:
337                 return -EINVAL;
338         }
339
340         regmap_update_bits(admaif->regmap, reg, mask, val);
341
342         return 0;
343 }
344
345 static int tegra_admaif_stop(struct snd_soc_dai *dai, int direction)
346 {
347         struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
348         unsigned int enable_reg, status_reg, reset_reg, mask, val;
349         char *dir_name;
350         int err, enable;
351
352         switch (direction) {
353         case SNDRV_PCM_STREAM_PLAYBACK:
354                 mask = TX_ENABLE_MASK;
355                 enable = TX_ENABLE;
356                 dir_name = "TX";
357                 enable_reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
358                 status_reg = CH_TX_REG(TEGRA_ADMAIF_TX_STATUS, dai->id);
359                 reset_reg = CH_TX_REG(TEGRA_ADMAIF_TX_SOFT_RESET, dai->id);
360                 break;
361         case SNDRV_PCM_STREAM_CAPTURE:
362                 mask = RX_ENABLE_MASK;
363                 enable = RX_ENABLE;
364                 dir_name = "RX";
365                 enable_reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
366                 status_reg = CH_RX_REG(TEGRA_ADMAIF_RX_STATUS, dai->id);
367                 reset_reg = CH_RX_REG(TEGRA_ADMAIF_RX_SOFT_RESET, dai->id);
368                 break;
369         default:
370                 return -EINVAL;
371         }
372
373         /* Disable TX/RX channel */
374         regmap_update_bits(admaif->regmap, enable_reg, mask, ~enable);
375
376         /* Wait until ADMAIF TX/RX status is disabled */
377         err = regmap_read_poll_timeout_atomic(admaif->regmap, status_reg, val,
378                                               !(val & enable), 10, 10000);
379         if (err < 0)
380                 dev_warn(dai->dev, "timeout: failed to disable ADMAIF%d_%s\n",
381                          dai->id + 1, dir_name);
382
383         /* SW reset */
384         regmap_update_bits(admaif->regmap, reset_reg, SW_RESET_MASK, SW_RESET);
385
386         /* Wait till SW reset is complete */
387         err = regmap_read_poll_timeout_atomic(admaif->regmap, reset_reg, val,
388                                               !(val & SW_RESET_MASK & SW_RESET),
389                                               10, 10000);
390         if (err) {
391                 dev_err(dai->dev, "timeout: SW reset failed for ADMAIF%d_%s\n",
392                         dai->id + 1, dir_name);
393                 return err;
394         }
395
396         return 0;
397 }
398
399 static int tegra_admaif_trigger(struct snd_pcm_substream *substream, int cmd,
400                                 struct snd_soc_dai *dai)
401 {
402         int err;
403
404         err = snd_dmaengine_pcm_trigger(substream, cmd);
405         if (err)
406                 return err;
407
408         switch (cmd) {
409         case SNDRV_PCM_TRIGGER_START:
410         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
411         case SNDRV_PCM_TRIGGER_RESUME:
412                 return tegra_admaif_start(dai, substream->stream);
413         case SNDRV_PCM_TRIGGER_STOP:
414         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
415         case SNDRV_PCM_TRIGGER_SUSPEND:
416                 return tegra_admaif_stop(dai, substream->stream);
417         default:
418                 return -EINVAL;
419         }
420 }
421
422 static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
423         .hw_params      = tegra_admaif_hw_params,
424         .trigger        = tegra_admaif_trigger,
425 };
426
427 static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol,
428                                     struct snd_ctl_elem_value *ucontrol)
429 {
430         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
431         struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
432         struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
433         long *uctl_val = &ucontrol->value.integer.value[0];
434
435         if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
436                 *uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
437         else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
438                 *uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
439         else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
440                 *uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
441         else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
442                 *uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
443
444         return 0;
445 }
446
447 static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol,
448                                     struct snd_ctl_elem_value *ucontrol)
449 {
450         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
451         struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
452         struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
453         int value = ucontrol->value.integer.value[0];
454
455         if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
456                 admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
457         else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
458                 admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
459         else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
460                 admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
461         else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
462                 admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
463
464         return 0;
465 }
466
467 static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
468 {
469         struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
470
471         dai->capture_dma_data = &admaif->capture_dma_data[dai->id];
472         dai->playback_dma_data = &admaif->playback_dma_data[dai->id];
473
474         return 0;
475 }
476
477 #define DAI(dai_name)                                   \
478         {                                                       \
479                 .name = dai_name,                               \
480                 .probe = tegra_admaif_dai_probe,                \
481                 .playback = {                                   \
482                         .stream_name = dai_name " Playback",    \
483                         .channels_min = 1,                      \
484                         .channels_max = 16,                     \
485                         .rates = SNDRV_PCM_RATE_8000_192000,    \
486                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
487                                 SNDRV_PCM_FMTBIT_S16_LE |       \
488                                 SNDRV_PCM_FMTBIT_S32_LE,        \
489                 },                                              \
490                 .capture = {                                    \
491                         .stream_name = dai_name " Capture",     \
492                         .channels_min = 1,                      \
493                         .channels_max = 16,                     \
494                         .rates = SNDRV_PCM_RATE_8000_192000,    \
495                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
496                                 SNDRV_PCM_FMTBIT_S16_LE |       \
497                                 SNDRV_PCM_FMTBIT_S32_LE,        \
498                 },                                              \
499                 .ops = &tegra_admaif_dai_ops,                   \
500         }
501
502 static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = {
503         DAI("ADMAIF1"),
504         DAI("ADMAIF2"),
505         DAI("ADMAIF3"),
506         DAI("ADMAIF4"),
507         DAI("ADMAIF5"),
508         DAI("ADMAIF6"),
509         DAI("ADMAIF7"),
510         DAI("ADMAIF8"),
511         DAI("ADMAIF9"),
512         DAI("ADMAIF10"),
513 };
514
515 static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = {
516         DAI("ADMAIF1"),
517         DAI("ADMAIF2"),
518         DAI("ADMAIF3"),
519         DAI("ADMAIF4"),
520         DAI("ADMAIF5"),
521         DAI("ADMAIF6"),
522         DAI("ADMAIF7"),
523         DAI("ADMAIF8"),
524         DAI("ADMAIF9"),
525         DAI("ADMAIF10"),
526         DAI("ADMAIF11"),
527         DAI("ADMAIF12"),
528         DAI("ADMAIF13"),
529         DAI("ADMAIF14"),
530         DAI("ADMAIF15"),
531         DAI("ADMAIF16"),
532         DAI("ADMAIF17"),
533         DAI("ADMAIF18"),
534         DAI("ADMAIF19"),
535         DAI("ADMAIF20"),
536 };
537
538 static const char * const tegra_admaif_stereo_conv_text[] = {
539         "CH0", "CH1", "AVG",
540 };
541
542 static const char * const tegra_admaif_mono_conv_text[] = {
543         "Zero", "Copy",
544 };
545
546 /*
547  * Below macro is added to avoid looping over all ADMAIFx controls related
548  * to mono/stereo conversions in get()/put() callbacks.
549  */
550 #define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text)   \
551 {                                                                              \
552         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                                   \
553         .info = snd_soc_info_enum_double,                                      \
554         .name = xname,                                                         \
555         .get = xhandler_get,                                                   \
556         .put = xhandler_put,                                                   \
557         .private_value = (unsigned long)&(struct soc_enum)                     \
558                 SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text)   \
559 }
560
561 #define TEGRA_ADMAIF_CIF_CTRL(reg)                                             \
562         NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\
563                         tegra_admaif_get_control, tegra_admaif_put_control,    \
564                         tegra_admaif_mono_conv_text),                          \
565         NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\
566                         tegra_admaif_get_control, tegra_admaif_put_control,    \
567                         tegra_admaif_stereo_conv_text),                        \
568         NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \
569                         tegra_admaif_get_control, tegra_admaif_put_control,    \
570                         tegra_admaif_mono_conv_text),                          \
571         NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \
572                         tegra_admaif_get_control, tegra_admaif_put_control,    \
573                         tegra_admaif_stereo_conv_text)
574
575 static struct snd_kcontrol_new tegra210_admaif_controls[] = {
576         TEGRA_ADMAIF_CIF_CTRL(1),
577         TEGRA_ADMAIF_CIF_CTRL(2),
578         TEGRA_ADMAIF_CIF_CTRL(3),
579         TEGRA_ADMAIF_CIF_CTRL(4),
580         TEGRA_ADMAIF_CIF_CTRL(5),
581         TEGRA_ADMAIF_CIF_CTRL(6),
582         TEGRA_ADMAIF_CIF_CTRL(7),
583         TEGRA_ADMAIF_CIF_CTRL(8),
584         TEGRA_ADMAIF_CIF_CTRL(9),
585         TEGRA_ADMAIF_CIF_CTRL(10),
586 };
587
588 static struct snd_kcontrol_new tegra186_admaif_controls[] = {
589         TEGRA_ADMAIF_CIF_CTRL(1),
590         TEGRA_ADMAIF_CIF_CTRL(2),
591         TEGRA_ADMAIF_CIF_CTRL(3),
592         TEGRA_ADMAIF_CIF_CTRL(4),
593         TEGRA_ADMAIF_CIF_CTRL(5),
594         TEGRA_ADMAIF_CIF_CTRL(6),
595         TEGRA_ADMAIF_CIF_CTRL(7),
596         TEGRA_ADMAIF_CIF_CTRL(8),
597         TEGRA_ADMAIF_CIF_CTRL(9),
598         TEGRA_ADMAIF_CIF_CTRL(10),
599         TEGRA_ADMAIF_CIF_CTRL(11),
600         TEGRA_ADMAIF_CIF_CTRL(12),
601         TEGRA_ADMAIF_CIF_CTRL(13),
602         TEGRA_ADMAIF_CIF_CTRL(14),
603         TEGRA_ADMAIF_CIF_CTRL(15),
604         TEGRA_ADMAIF_CIF_CTRL(16),
605         TEGRA_ADMAIF_CIF_CTRL(17),
606         TEGRA_ADMAIF_CIF_CTRL(18),
607         TEGRA_ADMAIF_CIF_CTRL(19),
608         TEGRA_ADMAIF_CIF_CTRL(20),
609 };
610
611 static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
612         .controls               = tegra210_admaif_controls,
613         .num_controls           = ARRAY_SIZE(tegra210_admaif_controls),
614         .pcm_construct          = tegra_pcm_construct,
615         .open                   = tegra_pcm_open,
616         .close                  = tegra_pcm_close,
617         .hw_params              = tegra_pcm_hw_params,
618         .pointer                = tegra_pcm_pointer,
619 };
620
621 static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
622         .controls               = tegra186_admaif_controls,
623         .num_controls           = ARRAY_SIZE(tegra186_admaif_controls),
624         .pcm_construct          = tegra_pcm_construct,
625         .open                   = tegra_pcm_open,
626         .close                  = tegra_pcm_close,
627         .hw_params              = tegra_pcm_hw_params,
628         .pointer                = tegra_pcm_pointer,
629 };
630
631 static const struct tegra_admaif_soc_data soc_data_tegra210 = {
632         .num_ch         = TEGRA210_ADMAIF_CHANNEL_COUNT,
633         .cmpnt          = &tegra210_admaif_cmpnt,
634         .dais           = tegra210_admaif_cmpnt_dais,
635         .regmap_conf    = &tegra210_admaif_regmap_config,
636         .global_base    = TEGRA210_ADMAIF_GLOBAL_BASE,
637         .tx_base        = TEGRA210_ADMAIF_TX_BASE,
638         .rx_base        = TEGRA210_ADMAIF_RX_BASE,
639 };
640
641 static const struct tegra_admaif_soc_data soc_data_tegra186 = {
642         .num_ch         = TEGRA186_ADMAIF_CHANNEL_COUNT,
643         .cmpnt          = &tegra186_admaif_cmpnt,
644         .dais           = tegra186_admaif_cmpnt_dais,
645         .regmap_conf    = &tegra186_admaif_regmap_config,
646         .global_base    = TEGRA186_ADMAIF_GLOBAL_BASE,
647         .tx_base        = TEGRA186_ADMAIF_TX_BASE,
648         .rx_base        = TEGRA186_ADMAIF_RX_BASE,
649 };
650
651 static const struct of_device_id tegra_admaif_of_match[] = {
652         { .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 },
653         { .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 },
654         {},
655 };
656 MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
657
658 static int tegra_admaif_probe(struct platform_device *pdev)
659 {
660         struct tegra_admaif *admaif;
661         void __iomem *regs;
662         struct resource *res;
663         int err, i;
664
665         admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
666         if (!admaif)
667                 return -ENOMEM;
668
669         admaif->soc_data = of_device_get_match_data(&pdev->dev);
670
671         dev_set_drvdata(&pdev->dev, admaif);
672
673         admaif->capture_dma_data =
674                 devm_kcalloc(&pdev->dev,
675                              admaif->soc_data->num_ch,
676                              sizeof(struct snd_dmaengine_dai_dma_data),
677                              GFP_KERNEL);
678         if (!admaif->capture_dma_data)
679                 return -ENOMEM;
680
681         admaif->playback_dma_data =
682                 devm_kcalloc(&pdev->dev,
683                              admaif->soc_data->num_ch,
684                              sizeof(struct snd_dmaengine_dai_dma_data),
685                              GFP_KERNEL);
686         if (!admaif->playback_dma_data)
687                 return -ENOMEM;
688
689         for (i = 0; i < ADMAIF_PATHS; i++) {
690                 admaif->mono_to_stereo[i] =
691                         devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
692                                      sizeof(unsigned int), GFP_KERNEL);
693                 if (!admaif->mono_to_stereo[i])
694                         return -ENOMEM;
695
696                 admaif->stereo_to_mono[i] =
697                         devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
698                                      sizeof(unsigned int), GFP_KERNEL);
699                 if (!admaif->stereo_to_mono[i])
700                         return -ENOMEM;
701         }
702
703         regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
704         if (IS_ERR(regs))
705                 return PTR_ERR(regs);
706
707         admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
708                                                admaif->soc_data->regmap_conf);
709         if (IS_ERR(admaif->regmap)) {
710                 dev_err(&pdev->dev, "regmap init failed\n");
711                 return PTR_ERR(admaif->regmap);
712         }
713
714         regcache_cache_only(admaif->regmap, true);
715
716         regmap_update_bits(admaif->regmap, admaif->soc_data->global_base +
717                            TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1);
718
719         for (i = 0; i < admaif->soc_data->num_ch; i++) {
720                 admaif->playback_dma_data[i].addr = res->start +
721                         CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE, i);
722
723                 admaif->capture_dma_data[i].addr = res->start +
724                         CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i);
725
726                 admaif->playback_dma_data[i].addr_width = 32;
727
728                 if (of_property_read_string_index(pdev->dev.of_node,
729                                 "dma-names", (i * 2) + 1,
730                                 &admaif->playback_dma_data[i].chan_name) < 0) {
731                         dev_err(&pdev->dev,
732                                 "missing property nvidia,dma-names\n");
733
734                         return -ENODEV;
735                 }
736
737                 admaif->capture_dma_data[i].addr_width = 32;
738
739                 if (of_property_read_string_index(pdev->dev.of_node,
740                                 "dma-names",
741                                 (i * 2),
742                                 &admaif->capture_dma_data[i].chan_name) < 0) {
743                         dev_err(&pdev->dev,
744                                 "missing property nvidia,dma-names\n");
745
746                         return -ENODEV;
747                 }
748         }
749
750         err = devm_snd_soc_register_component(&pdev->dev,
751                                               admaif->soc_data->cmpnt,
752                                               admaif->soc_data->dais,
753                                               admaif->soc_data->num_ch);
754         if (err) {
755                 dev_err(&pdev->dev,
756                         "can't register ADMAIF component, err: %d\n", err);
757                 return err;
758         }
759
760         pm_runtime_enable(&pdev->dev);
761
762         return 0;
763 }
764
765 static int tegra_admaif_remove(struct platform_device *pdev)
766 {
767         pm_runtime_disable(&pdev->dev);
768
769         return 0;
770 }
771
772 static const struct dev_pm_ops tegra_admaif_pm_ops = {
773         SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend,
774                            tegra_admaif_runtime_resume, NULL)
775         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
776                                 pm_runtime_force_resume)
777 };
778
779 static struct platform_driver tegra_admaif_driver = {
780         .probe = tegra_admaif_probe,
781         .remove = tegra_admaif_remove,
782         .driver = {
783                 .name = "tegra210-admaif",
784                 .of_match_table = tegra_admaif_of_match,
785                 .pm = &tegra_admaif_pm_ops,
786         },
787 };
788 module_platform_driver(tegra_admaif_driver);
789
790 MODULE_AUTHOR("Songhee Baek <[email protected]>");
791 MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
792 MODULE_LICENSE("GPL v2");
This page took 0.070416 seconds and 4 git commands to generate.