linux/sound/soc/tegra/tegra210_admaif.c
<<
>>
Prefs
   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
  42static 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
  66static 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
  80static 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
 114static 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
 158static 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
 196static 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
 209static 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
 222static 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
 232static 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
 242static 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
 265static 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
 320static 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
 345static 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
 399static 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
 422static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
 423        .hw_params      = tegra_admaif_hw_params,
 424        .trigger        = tegra_admaif_trigger,
 425};
 426
 427static 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
 447static 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
 467static 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
 502static 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
 515static 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
 538static const char * const tegra_admaif_stereo_conv_text[] = {
 539        "CH0", "CH1", "AVG",
 540};
 541
 542static 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
 575static 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
 588static 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
 611static 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
 621static 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
 631static 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
 641static 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
 651static 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};
 656MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
 657
 658static 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
 765static int tegra_admaif_remove(struct platform_device *pdev)
 766{
 767        pm_runtime_disable(&pdev->dev);
 768
 769        return 0;
 770}
 771
 772static 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
 779static 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};
 788module_platform_driver(tegra_admaif_driver);
 789
 790MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
 791MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
 792MODULE_LICENSE("GPL v2");
 793