~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/tegra/tegra210_admaif.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 int tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol *kcontrol,
423         struct snd_ctl_elem_value *ucontrol)
424 {
425         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
426         struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
427         struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
428 
429         ucontrol->value.enumerated.item[0] =
430                 admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
431 
432         return 0;
433 }
434 
435 static int tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol *kcontrol,
436         struct snd_ctl_elem_value *ucontrol)
437 {
438         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
439         struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
440         struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
441         unsigned int value = ucontrol->value.enumerated.item[0];
442 
443         if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg])
444                 return 0;
445 
446         admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
447 
448         return 1;
449 }
450 
451 static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol,
452         struct snd_ctl_elem_value *ucontrol)
453 {
454         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
455         struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
456         struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
457 
458         ucontrol->value.enumerated.item[0] =
459                 admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
460 
461         return 0;
462 }
463 
464 static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol,
465         struct snd_ctl_elem_value *ucontrol)
466 {
467         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
468         struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
469         struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
470         unsigned int value = ucontrol->value.enumerated.item[0];
471 
472         if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg])
473                 return 0;
474 
475         admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
476 
477         return 1;
478 }
479 
480 static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol,
481         struct snd_ctl_elem_value *ucontrol)
482 {
483         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
484         struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
485         struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
486 
487         ucontrol->value.enumerated.item[0] =
488                 admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
489 
490         return 0;
491 }
492 
493 static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol,
494         struct snd_ctl_elem_value *ucontrol)
495 {
496         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
497         struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
498         struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
499         unsigned int value = ucontrol->value.enumerated.item[0];
500 
501         if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg])
502                 return 0;
503 
504         admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
505 
506         return 1;
507 }
508 
509 static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol,
510         struct snd_ctl_elem_value *ucontrol)
511 {
512         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
513         struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
514         struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
515 
516         ucontrol->value.enumerated.item[0] =
517                 admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
518 
519         return 0;
520 }
521 
522 static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol,
523         struct snd_ctl_elem_value *ucontrol)
524 {
525         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
526         struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
527         struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
528         unsigned int value = ucontrol->value.enumerated.item[0];
529 
530         if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg])
531                 return 0;
532 
533         admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
534 
535         return 1;
536 }
537 
538 static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
539 {
540         struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
541 
542         snd_soc_dai_init_dma_data(dai,  &admaif->playback_dma_data[dai->id],
543                                         &admaif->capture_dma_data[dai->id]);
544 
545         return 0;
546 }
547 
548 static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
549         .probe          = tegra_admaif_dai_probe,
550         .hw_params      = tegra_admaif_hw_params,
551         .trigger        = tegra_admaif_trigger,
552 };
553 
554 #define DAI(dai_name)                                   \
555         {                                                       \
556                 .name = dai_name,                               \
557                 .playback = {                                   \
558                         .stream_name = dai_name " Playback",    \
559                         .channels_min = 1,                      \
560                         .channels_max = 16,                     \
561                         .rates = SNDRV_PCM_RATE_8000_192000,    \
562                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
563                                 SNDRV_PCM_FMTBIT_S16_LE |       \
564                                 SNDRV_PCM_FMTBIT_S32_LE,        \
565                 },                                              \
566                 .capture = {                                    \
567                         .stream_name = dai_name " Capture",     \
568                         .channels_min = 1,                      \
569                         .channels_max = 16,                     \
570                         .rates = SNDRV_PCM_RATE_8000_192000,    \
571                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
572                                 SNDRV_PCM_FMTBIT_S16_LE |       \
573                                 SNDRV_PCM_FMTBIT_S32_LE,        \
574                 },                                              \
575                 .ops = &tegra_admaif_dai_ops,                   \
576         }
577 
578 static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = {
579         DAI("ADMAIF1"),
580         DAI("ADMAIF2"),
581         DAI("ADMAIF3"),
582         DAI("ADMAIF4"),
583         DAI("ADMAIF5"),
584         DAI("ADMAIF6"),
585         DAI("ADMAIF7"),
586         DAI("ADMAIF8"),
587         DAI("ADMAIF9"),
588         DAI("ADMAIF10"),
589 };
590 
591 static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = {
592         DAI("ADMAIF1"),
593         DAI("ADMAIF2"),
594         DAI("ADMAIF3"),
595         DAI("ADMAIF4"),
596         DAI("ADMAIF5"),
597         DAI("ADMAIF6"),
598         DAI("ADMAIF7"),
599         DAI("ADMAIF8"),
600         DAI("ADMAIF9"),
601         DAI("ADMAIF10"),
602         DAI("ADMAIF11"),
603         DAI("ADMAIF12"),
604         DAI("ADMAIF13"),
605         DAI("ADMAIF14"),
606         DAI("ADMAIF15"),
607         DAI("ADMAIF16"),
608         DAI("ADMAIF17"),
609         DAI("ADMAIF18"),
610         DAI("ADMAIF19"),
611         DAI("ADMAIF20"),
612 };
613 
614 static const char * const tegra_admaif_stereo_conv_text[] = {
615         "CH0", "CH1", "AVG",
616 };
617 
618 static const char * const tegra_admaif_mono_conv_text[] = {
619         "Zero", "Copy",
620 };
621 
622 /*
623  * Below macro is added to avoid looping over all ADMAIFx controls related
624  * to mono/stereo conversions in get()/put() callbacks.
625  */
626 #define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text)   \
627 {                                                                              \
628         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                                   \
629         .info = snd_soc_info_enum_double,                                      \
630         .name = xname,                                                         \
631         .get = xhandler_get,                                                   \
632         .put = xhandler_put,                                                   \
633         .private_value = (unsigned long)&(struct soc_enum)                     \
634                 SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text)   \
635 }
636 
637 #define TEGRA_ADMAIF_CIF_CTRL(reg)                                             \
638         NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,     \
639                         tegra210_admaif_pget_mono_to_stereo,                   \
640                         tegra210_admaif_pput_mono_to_stereo,                   \
641                         tegra_admaif_mono_conv_text),                          \
642         NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,     \
643                         tegra210_admaif_pget_stereo_to_mono,                   \
644                         tegra210_admaif_pput_stereo_to_mono,                   \
645                         tegra_admaif_stereo_conv_text),                        \
646         NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1,      \
647                         tegra210_admaif_cget_mono_to_stereo,                   \
648                         tegra210_admaif_cput_mono_to_stereo,                   \
649                         tegra_admaif_mono_conv_text),                          \
650         NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1,      \
651                         tegra210_admaif_cget_stereo_to_mono,                   \
652                         tegra210_admaif_cput_stereo_to_mono,                   \
653                         tegra_admaif_stereo_conv_text)
654 
655 static struct snd_kcontrol_new tegra210_admaif_controls[] = {
656         TEGRA_ADMAIF_CIF_CTRL(1),
657         TEGRA_ADMAIF_CIF_CTRL(2),
658         TEGRA_ADMAIF_CIF_CTRL(3),
659         TEGRA_ADMAIF_CIF_CTRL(4),
660         TEGRA_ADMAIF_CIF_CTRL(5),
661         TEGRA_ADMAIF_CIF_CTRL(6),
662         TEGRA_ADMAIF_CIF_CTRL(7),
663         TEGRA_ADMAIF_CIF_CTRL(8),
664         TEGRA_ADMAIF_CIF_CTRL(9),
665         TEGRA_ADMAIF_CIF_CTRL(10),
666 };
667 
668 static struct snd_kcontrol_new tegra186_admaif_controls[] = {
669         TEGRA_ADMAIF_CIF_CTRL(1),
670         TEGRA_ADMAIF_CIF_CTRL(2),
671         TEGRA_ADMAIF_CIF_CTRL(3),
672         TEGRA_ADMAIF_CIF_CTRL(4),
673         TEGRA_ADMAIF_CIF_CTRL(5),
674         TEGRA_ADMAIF_CIF_CTRL(6),
675         TEGRA_ADMAIF_CIF_CTRL(7),
676         TEGRA_ADMAIF_CIF_CTRL(8),
677         TEGRA_ADMAIF_CIF_CTRL(9),
678         TEGRA_ADMAIF_CIF_CTRL(10),
679         TEGRA_ADMAIF_CIF_CTRL(11),
680         TEGRA_ADMAIF_CIF_CTRL(12),
681         TEGRA_ADMAIF_CIF_CTRL(13),
682         TEGRA_ADMAIF_CIF_CTRL(14),
683         TEGRA_ADMAIF_CIF_CTRL(15),
684         TEGRA_ADMAIF_CIF_CTRL(16),
685         TEGRA_ADMAIF_CIF_CTRL(17),
686         TEGRA_ADMAIF_CIF_CTRL(18),
687         TEGRA_ADMAIF_CIF_CTRL(19),
688         TEGRA_ADMAIF_CIF_CTRL(20),
689 };
690 
691 static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
692         .controls               = tegra210_admaif_controls,
693         .num_controls           = ARRAY_SIZE(tegra210_admaif_controls),
694         .pcm_construct          = tegra_pcm_construct,
695         .open                   = tegra_pcm_open,
696         .close                  = tegra_pcm_close,
697         .hw_params              = tegra_pcm_hw_params,
698         .pointer                = tegra_pcm_pointer,
699 };
700 
701 static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
702         .controls               = tegra186_admaif_controls,
703         .num_controls           = ARRAY_SIZE(tegra186_admaif_controls),
704         .pcm_construct          = tegra_pcm_construct,
705         .open                   = tegra_pcm_open,
706         .close                  = tegra_pcm_close,
707         .hw_params              = tegra_pcm_hw_params,
708         .pointer                = tegra_pcm_pointer,
709 };
710 
711 static const struct tegra_admaif_soc_data soc_data_tegra210 = {
712         .num_ch         = TEGRA210_ADMAIF_CHANNEL_COUNT,
713         .cmpnt          = &tegra210_admaif_cmpnt,
714         .dais           = tegra210_admaif_cmpnt_dais,
715         .regmap_conf    = &tegra210_admaif_regmap_config,
716         .global_base    = TEGRA210_ADMAIF_GLOBAL_BASE,
717         .tx_base        = TEGRA210_ADMAIF_TX_BASE,
718         .rx_base        = TEGRA210_ADMAIF_RX_BASE,
719 };
720 
721 static const struct tegra_admaif_soc_data soc_data_tegra186 = {
722         .num_ch         = TEGRA186_ADMAIF_CHANNEL_COUNT,
723         .cmpnt          = &tegra186_admaif_cmpnt,
724         .dais           = tegra186_admaif_cmpnt_dais,
725         .regmap_conf    = &tegra186_admaif_regmap_config,
726         .global_base    = TEGRA186_ADMAIF_GLOBAL_BASE,
727         .tx_base        = TEGRA186_ADMAIF_TX_BASE,
728         .rx_base        = TEGRA186_ADMAIF_RX_BASE,
729 };
730 
731 static const struct of_device_id tegra_admaif_of_match[] = {
732         { .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 },
733         { .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 },
734         {},
735 };
736 MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
737 
738 static int tegra_admaif_probe(struct platform_device *pdev)
739 {
740         struct tegra_admaif *admaif;
741         void __iomem *regs;
742         struct resource *res;
743         int err, i;
744 
745         admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
746         if (!admaif)
747                 return -ENOMEM;
748 
749         admaif->soc_data = of_device_get_match_data(&pdev->dev);
750 
751         dev_set_drvdata(&pdev->dev, admaif);
752 
753         admaif->capture_dma_data =
754                 devm_kcalloc(&pdev->dev,
755                              admaif->soc_data->num_ch,
756                              sizeof(struct snd_dmaengine_dai_dma_data),
757                              GFP_KERNEL);
758         if (!admaif->capture_dma_data)
759                 return -ENOMEM;
760 
761         admaif->playback_dma_data =
762                 devm_kcalloc(&pdev->dev,
763                              admaif->soc_data->num_ch,
764                              sizeof(struct snd_dmaengine_dai_dma_data),
765                              GFP_KERNEL);
766         if (!admaif->playback_dma_data)
767                 return -ENOMEM;
768 
769         for (i = 0; i < ADMAIF_PATHS; i++) {
770                 admaif->mono_to_stereo[i] =
771                         devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
772                                      sizeof(unsigned int), GFP_KERNEL);
773                 if (!admaif->mono_to_stereo[i])
774                         return -ENOMEM;
775 
776                 admaif->stereo_to_mono[i] =
777                         devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
778                                      sizeof(unsigned int), GFP_KERNEL);
779                 if (!admaif->stereo_to_mono[i])
780                         return -ENOMEM;
781         }
782 
783         regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
784         if (IS_ERR(regs))
785                 return PTR_ERR(regs);
786 
787         admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
788                                                admaif->soc_data->regmap_conf);
789         if (IS_ERR(admaif->regmap)) {
790                 dev_err(&pdev->dev, "regmap init failed\n");
791                 return PTR_ERR(admaif->regmap);
792         }
793 
794         regcache_cache_only(admaif->regmap, true);
795 
796         regmap_update_bits(admaif->regmap, admaif->soc_data->global_base +
797                            TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1);
798 
799         for (i = 0; i < admaif->soc_data->num_ch; i++) {
800                 admaif->playback_dma_data[i].addr = res->start +
801                         CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE, i);
802 
803                 admaif->capture_dma_data[i].addr = res->start +
804                         CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i);
805 
806                 admaif->playback_dma_data[i].addr_width = 32;
807 
808                 if (of_property_read_string_index(pdev->dev.of_node,
809                                 "dma-names", (i * 2) + 1,
810                                 &admaif->playback_dma_data[i].chan_name) < 0) {
811                         dev_err(&pdev->dev,
812                                 "missing property nvidia,dma-names\n");
813 
814                         return -ENODEV;
815                 }
816 
817                 admaif->capture_dma_data[i].addr_width = 32;
818 
819                 if (of_property_read_string_index(pdev->dev.of_node,
820                                 "dma-names",
821                                 (i * 2),
822                                 &admaif->capture_dma_data[i].chan_name) < 0) {
823                         dev_err(&pdev->dev,
824                                 "missing property nvidia,dma-names\n");
825 
826                         return -ENODEV;
827                 }
828         }
829 
830         err = devm_snd_soc_register_component(&pdev->dev,
831                                               admaif->soc_data->cmpnt,
832                                               admaif->soc_data->dais,
833                                               admaif->soc_data->num_ch);
834         if (err) {
835                 dev_err(&pdev->dev,
836                         "can't register ADMAIF component, err: %d\n", err);
837                 return err;
838         }
839 
840         pm_runtime_enable(&pdev->dev);
841 
842         return 0;
843 }
844 
845 static void tegra_admaif_remove(struct platform_device *pdev)
846 {
847         pm_runtime_disable(&pdev->dev);
848 }
849 
850 static const struct dev_pm_ops tegra_admaif_pm_ops = {
851         SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend,
852                            tegra_admaif_runtime_resume, NULL)
853         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
854                                 pm_runtime_force_resume)
855 };
856 
857 static struct platform_driver tegra_admaif_driver = {
858         .probe = tegra_admaif_probe,
859         .remove_new = tegra_admaif_remove,
860         .driver = {
861                 .name = "tegra210-admaif",
862                 .of_match_table = tegra_admaif_of_match,
863                 .pm = &tegra_admaif_pm_ops,
864         },
865 };
866 module_platform_driver(tegra_admaif_driver);
867 
868 MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
869 MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
870 MODULE_LICENSE("GPL v2");
871 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php