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        .pcm_destruct           = tegra_pcm_destruct,
 616        .open                   = tegra_pcm_open,
 617        .close                  = tegra_pcm_close,
 618        .hw_params              = tegra_pcm_hw_params,
 619        .hw_free                = tegra_pcm_hw_free,
 620        .mmap                   = tegra_pcm_mmap,
 621        .pointer                = tegra_pcm_pointer,
 622};
 623
 624static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
 625        .controls               = tegra186_admaif_controls,
 626        .num_controls           = ARRAY_SIZE(tegra186_admaif_controls),
 627        .pcm_construct          = tegra_pcm_construct,
 628        .pcm_destruct           = tegra_pcm_destruct,
 629        .open                   = tegra_pcm_open,
 630        .close                  = tegra_pcm_close,
 631        .hw_params              = tegra_pcm_hw_params,
 632        .hw_free                = tegra_pcm_hw_free,
 633        .mmap                   = tegra_pcm_mmap,
 634        .pointer                = tegra_pcm_pointer,
 635};
 636
 637static const struct tegra_admaif_soc_data soc_data_tegra210 = {
 638        .num_ch         = TEGRA210_ADMAIF_CHANNEL_COUNT,
 639        .cmpnt          = &tegra210_admaif_cmpnt,
 640        .dais           = tegra210_admaif_cmpnt_dais,
 641        .regmap_conf    = &tegra210_admaif_regmap_config,
 642        .global_base    = TEGRA210_ADMAIF_GLOBAL_BASE,
 643        .tx_base        = TEGRA210_ADMAIF_TX_BASE,
 644        .rx_base        = TEGRA210_ADMAIF_RX_BASE,
 645};
 646
 647static const struct tegra_admaif_soc_data soc_data_tegra186 = {
 648        .num_ch         = TEGRA186_ADMAIF_CHANNEL_COUNT,
 649        .cmpnt          = &tegra186_admaif_cmpnt,
 650        .dais           = tegra186_admaif_cmpnt_dais,
 651        .regmap_conf    = &tegra186_admaif_regmap_config,
 652        .global_base    = TEGRA186_ADMAIF_GLOBAL_BASE,
 653        .tx_base        = TEGRA186_ADMAIF_TX_BASE,
 654        .rx_base        = TEGRA186_ADMAIF_RX_BASE,
 655};
 656
 657static const struct of_device_id tegra_admaif_of_match[] = {
 658        { .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 },
 659        { .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 },
 660        {},
 661};
 662MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
 663
 664static int tegra_admaif_probe(struct platform_device *pdev)
 665{
 666        struct tegra_admaif *admaif;
 667        void __iomem *regs;
 668        struct resource *res;
 669        int err, i;
 670
 671        admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
 672        if (!admaif)
 673                return -ENOMEM;
 674
 675        admaif->soc_data = of_device_get_match_data(&pdev->dev);
 676
 677        dev_set_drvdata(&pdev->dev, admaif);
 678
 679        admaif->capture_dma_data =
 680                devm_kcalloc(&pdev->dev,
 681                             admaif->soc_data->num_ch,
 682                             sizeof(struct snd_dmaengine_dai_dma_data),
 683                             GFP_KERNEL);
 684        if (!admaif->capture_dma_data)
 685                return -ENOMEM;
 686
 687        admaif->playback_dma_data =
 688                devm_kcalloc(&pdev->dev,
 689                             admaif->soc_data->num_ch,
 690                             sizeof(struct snd_dmaengine_dai_dma_data),
 691                             GFP_KERNEL);
 692        if (!admaif->playback_dma_data)
 693                return -ENOMEM;
 694
 695        for (i = 0; i < ADMAIF_PATHS; i++) {
 696                admaif->mono_to_stereo[i] =
 697                        devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
 698                                     sizeof(unsigned int), GFP_KERNEL);
 699                if (!admaif->mono_to_stereo[i])
 700                        return -ENOMEM;
 701
 702                admaif->stereo_to_mono[i] =
 703                        devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
 704                                     sizeof(unsigned int), GFP_KERNEL);
 705                if (!admaif->stereo_to_mono[i])
 706                        return -ENOMEM;
 707        }
 708
 709        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 710
 711        regs = devm_ioremap_resource(&pdev->dev, res);
 712        if (IS_ERR(regs))
 713                return PTR_ERR(regs);
 714
 715        admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
 716                                               admaif->soc_data->regmap_conf);
 717        if (IS_ERR(admaif->regmap)) {
 718                dev_err(&pdev->dev, "regmap init failed\n");
 719                return PTR_ERR(admaif->regmap);
 720        }
 721
 722        regcache_cache_only(admaif->regmap, true);
 723
 724        regmap_update_bits(admaif->regmap, admaif->soc_data->global_base +
 725                           TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1);
 726
 727        for (i = 0; i < admaif->soc_data->num_ch; i++) {
 728                admaif->playback_dma_data[i].addr = res->start +
 729                        CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE, i);
 730
 731                admaif->capture_dma_data[i].addr = res->start +
 732                        CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i);
 733
 734                admaif->playback_dma_data[i].addr_width = 32;
 735
 736                if (of_property_read_string_index(pdev->dev.of_node,
 737                                "dma-names", (i * 2) + 1,
 738                                &admaif->playback_dma_data[i].chan_name) < 0) {
 739                        dev_err(&pdev->dev,
 740                                "missing property nvidia,dma-names\n");
 741
 742                        return -ENODEV;
 743                }
 744
 745                admaif->capture_dma_data[i].addr_width = 32;
 746
 747                if (of_property_read_string_index(pdev->dev.of_node,
 748                                "dma-names",
 749                                (i * 2),
 750                                &admaif->capture_dma_data[i].chan_name) < 0) {
 751                        dev_err(&pdev->dev,
 752                                "missing property nvidia,dma-names\n");
 753
 754                        return -ENODEV;
 755                }
 756        }
 757
 758        err = devm_snd_soc_register_component(&pdev->dev,
 759                                              admaif->soc_data->cmpnt,
 760                                              admaif->soc_data->dais,
 761                                              admaif->soc_data->num_ch);
 762        if (err) {
 763                dev_err(&pdev->dev,
 764                        "can't register ADMAIF component, err: %d\n", err);
 765                return err;
 766        }
 767
 768        pm_runtime_enable(&pdev->dev);
 769
 770        return 0;
 771}
 772
 773static int tegra_admaif_remove(struct platform_device *pdev)
 774{
 775        pm_runtime_disable(&pdev->dev);
 776
 777        return 0;
 778}
 779
 780static const struct dev_pm_ops tegra_admaif_pm_ops = {
 781        SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend,
 782                           tegra_admaif_runtime_resume, NULL)
 783        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
 784                                pm_runtime_force_resume)
 785};
 786
 787static struct platform_driver tegra_admaif_driver = {
 788        .probe = tegra_admaif_probe,
 789        .remove = tegra_admaif_remove,
 790        .driver = {
 791                .name = "tegra210-admaif",
 792                .of_match_table = tegra_admaif_of_match,
 793                .pm = &tegra_admaif_pm_ops,
 794        },
 795};
 796module_platform_driver(tegra_admaif_driver);
 797
 798MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
 799MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
 800MODULE_LICENSE("GPL v2");
 801