Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 //
0003 // tegra210_amx.c - Tegra210 AMX driver
0004 //
0005 // Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
0006 
0007 #include <linux/clk.h>
0008 #include <linux/device.h>
0009 #include <linux/io.h>
0010 #include <linux/module.h>
0011 #include <linux/of.h>
0012 #include <linux/of_device.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/pm_runtime.h>
0015 #include <linux/regmap.h>
0016 #include <sound/core.h>
0017 #include <sound/pcm.h>
0018 #include <sound/pcm_params.h>
0019 #include <sound/soc.h>
0020 
0021 #include "tegra210_amx.h"
0022 #include "tegra_cif.h"
0023 
0024 /*
0025  * The counter is in terms of AHUB clock cycles. If a frame is not
0026  * received within these clock cycles, the AMX input channel gets
0027  * automatically disabled. For now the counter is calculated as a
0028  * function of sample rate (8 kHz) and AHUB clock (49.152 MHz).
0029  * If later an accurate number is needed, the counter needs to be
0030  * calculated at runtime.
0031  *
0032  *     count = ahub_clk / sample_rate
0033  */
0034 #define TEGRA194_MAX_FRAME_IDLE_COUNT   0x1800
0035 
0036 #define AMX_CH_REG(id, reg) ((reg) + ((id) * TEGRA210_AMX_AUDIOCIF_CH_STRIDE))
0037 
0038 static const struct reg_default tegra210_amx_reg_defaults[] = {
0039     { TEGRA210_AMX_RX_INT_MASK, 0x0000000f},
0040     { TEGRA210_AMX_RX1_CIF_CTRL, 0x00007000},
0041     { TEGRA210_AMX_RX2_CIF_CTRL, 0x00007000},
0042     { TEGRA210_AMX_RX3_CIF_CTRL, 0x00007000},
0043     { TEGRA210_AMX_RX4_CIF_CTRL, 0x00007000},
0044     { TEGRA210_AMX_TX_INT_MASK, 0x00000001},
0045     { TEGRA210_AMX_TX_CIF_CTRL, 0x00007000},
0046     { TEGRA210_AMX_CG, 0x1},
0047     { TEGRA210_AMX_CFG_RAM_CTRL, 0x00004000},
0048 };
0049 
0050 static void tegra210_amx_write_map_ram(struct tegra210_amx *amx)
0051 {
0052     int i;
0053 
0054     regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_CTRL,
0055              TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
0056              TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN |
0057              TEGRA210_AMX_CFG_RAM_CTRL_RW_WRITE);
0058 
0059     for (i = 0; i < TEGRA210_AMX_RAM_DEPTH; i++)
0060         regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_DATA,
0061                  amx->map[i]);
0062 
0063     regmap_write(amx->regmap, TEGRA210_AMX_OUT_BYTE_EN0, amx->byte_mask[0]);
0064     regmap_write(amx->regmap, TEGRA210_AMX_OUT_BYTE_EN1, amx->byte_mask[1]);
0065 }
0066 
0067 static int tegra210_amx_startup(struct snd_pcm_substream *substream,
0068                 struct snd_soc_dai *dai)
0069 {
0070     struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
0071     unsigned int val;
0072     int err;
0073 
0074     /* Ensure if AMX is disabled */
0075     err = regmap_read_poll_timeout(amx->regmap, TEGRA210_AMX_STATUS, val,
0076                        !(val & 0x1), 10, 10000);
0077     if (err < 0) {
0078         dev_err(dai->dev, "failed to stop AMX, err = %d\n", err);
0079         return err;
0080     }
0081 
0082     /*
0083      * Soft Reset: Below performs module soft reset which clears
0084      * all FSM logic, flushes flow control of FIFO and resets the
0085      * state register. It also brings module back to disabled
0086      * state (without flushing the data in the pipe).
0087      */
0088     regmap_update_bits(amx->regmap, TEGRA210_AMX_SOFT_RESET,
0089                TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK,
0090                TEGRA210_AMX_SOFT_RESET_SOFT_EN);
0091 
0092     err = regmap_read_poll_timeout(amx->regmap, TEGRA210_AMX_SOFT_RESET,
0093                        val, !(val & 0x1), 10, 10000);
0094     if (err < 0) {
0095         dev_err(dai->dev, "failed to reset AMX, err = %d\n", err);
0096         return err;
0097     }
0098 
0099     return 0;
0100 }
0101 
0102 static int __maybe_unused tegra210_amx_runtime_suspend(struct device *dev)
0103 {
0104     struct tegra210_amx *amx = dev_get_drvdata(dev);
0105 
0106     regcache_cache_only(amx->regmap, true);
0107     regcache_mark_dirty(amx->regmap);
0108 
0109     return 0;
0110 }
0111 
0112 static int __maybe_unused tegra210_amx_runtime_resume(struct device *dev)
0113 {
0114     struct tegra210_amx *amx = dev_get_drvdata(dev);
0115 
0116     regcache_cache_only(amx->regmap, false);
0117     regcache_sync(amx->regmap);
0118 
0119     regmap_update_bits(amx->regmap,
0120         TEGRA210_AMX_CTRL,
0121         TEGRA210_AMX_CTRL_RX_DEP_MASK,
0122         TEGRA210_AMX_WAIT_ON_ANY << TEGRA210_AMX_CTRL_RX_DEP_SHIFT);
0123 
0124     tegra210_amx_write_map_ram(amx);
0125 
0126     return 0;
0127 }
0128 
0129 static int tegra210_amx_set_audio_cif(struct snd_soc_dai *dai,
0130                       struct snd_pcm_hw_params *params,
0131                       unsigned int reg)
0132 {
0133     struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
0134     int channels, audio_bits;
0135     struct tegra_cif_conf cif_conf;
0136 
0137     memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
0138 
0139     channels = params_channels(params);
0140 
0141     switch (params_format(params)) {
0142     case SNDRV_PCM_FORMAT_S8:
0143         audio_bits = TEGRA_ACIF_BITS_8;
0144         break;
0145     case SNDRV_PCM_FORMAT_S16_LE:
0146         audio_bits = TEGRA_ACIF_BITS_16;
0147         break;
0148     case SNDRV_PCM_FORMAT_S32_LE:
0149         audio_bits = TEGRA_ACIF_BITS_32;
0150         break;
0151     default:
0152         return -EINVAL;
0153     }
0154 
0155     cif_conf.audio_ch = channels;
0156     cif_conf.client_ch = channels;
0157     cif_conf.audio_bits = audio_bits;
0158     cif_conf.client_bits = audio_bits;
0159 
0160     tegra_set_cif(amx->regmap, reg, &cif_conf);
0161 
0162     return 0;
0163 }
0164 
0165 static int tegra210_amx_in_hw_params(struct snd_pcm_substream *substream,
0166                      struct snd_pcm_hw_params *params,
0167                      struct snd_soc_dai *dai)
0168 {
0169     struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
0170 
0171     if (amx->soc_data->auto_disable) {
0172         regmap_write(amx->regmap,
0173                  AMX_CH_REG(dai->id, TEGRA194_AMX_RX1_FRAME_PERIOD),
0174                  TEGRA194_MAX_FRAME_IDLE_COUNT);
0175         regmap_write(amx->regmap, TEGRA210_AMX_CYA, 1);
0176     }
0177 
0178     return tegra210_amx_set_audio_cif(dai, params,
0179             AMX_CH_REG(dai->id, TEGRA210_AMX_RX1_CIF_CTRL));
0180 }
0181 
0182 static int tegra210_amx_out_hw_params(struct snd_pcm_substream *substream,
0183                       struct snd_pcm_hw_params *params,
0184                       struct snd_soc_dai *dai)
0185 {
0186     return tegra210_amx_set_audio_cif(dai, params,
0187                       TEGRA210_AMX_TX_CIF_CTRL);
0188 }
0189 
0190 static int tegra210_amx_get_byte_map(struct snd_kcontrol *kcontrol,
0191                      struct snd_ctl_elem_value *ucontrol)
0192 {
0193     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0194     struct soc_mixer_control *mc =
0195         (struct soc_mixer_control *)kcontrol->private_value;
0196     struct tegra210_amx *amx = snd_soc_component_get_drvdata(cmpnt);
0197     unsigned char *bytes_map = (unsigned char *)&amx->map;
0198     int reg = mc->reg;
0199     int enabled;
0200 
0201     if (reg > 31)
0202         enabled = amx->byte_mask[1] & (1 << (reg - 32));
0203     else
0204         enabled = amx->byte_mask[0] & (1 << reg);
0205 
0206     if (enabled)
0207         ucontrol->value.integer.value[0] = bytes_map[reg];
0208     else
0209         ucontrol->value.integer.value[0] = 0;
0210 
0211     return 0;
0212 }
0213 
0214 static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol,
0215                      struct snd_ctl_elem_value *ucontrol)
0216 {
0217     struct soc_mixer_control *mc =
0218         (struct soc_mixer_control *)kcontrol->private_value;
0219     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0220     struct tegra210_amx *amx = snd_soc_component_get_drvdata(cmpnt);
0221     unsigned char *bytes_map = (unsigned char *)&amx->map;
0222     int reg = mc->reg;
0223     int value = ucontrol->value.integer.value[0];
0224 
0225     if (value == bytes_map[reg])
0226         return 0;
0227 
0228     if (value >= 0 && value <= 255) {
0229         /* Update byte map and enable slot */
0230         bytes_map[reg] = value;
0231         if (reg > 31)
0232             amx->byte_mask[1] |= (1 << (reg - 32));
0233         else
0234             amx->byte_mask[0] |= (1 << reg);
0235     } else {
0236         /* Reset byte map and disable slot */
0237         bytes_map[reg] = 0;
0238         if (reg > 31)
0239             amx->byte_mask[1] &= ~(1 << (reg - 32));
0240         else
0241             amx->byte_mask[0] &= ~(1 << reg);
0242     }
0243 
0244     return 1;
0245 }
0246 
0247 static const struct snd_soc_dai_ops tegra210_amx_out_dai_ops = {
0248     .hw_params  = tegra210_amx_out_hw_params,
0249     .startup    = tegra210_amx_startup,
0250 };
0251 
0252 static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = {
0253     .hw_params  = tegra210_amx_in_hw_params,
0254 };
0255 
0256 #define IN_DAI(id)                      \
0257     {                           \
0258         .name = "AMX-RX-CIF" #id,           \
0259         .playback = {                   \
0260             .stream_name = "RX" #id "-CIF-Playback",\
0261             .channels_min = 1,          \
0262             .channels_max = 16,         \
0263             .rates = SNDRV_PCM_RATE_8000_192000,    \
0264             .formats = SNDRV_PCM_FMTBIT_S8 |    \
0265                    SNDRV_PCM_FMTBIT_S16_LE |    \
0266                    SNDRV_PCM_FMTBIT_S32_LE, \
0267         },                      \
0268         .capture = {                    \
0269             .stream_name = "RX" #id "-CIF-Capture", \
0270             .channels_min = 1,          \
0271             .channels_max = 16,         \
0272             .rates = SNDRV_PCM_RATE_8000_192000,    \
0273             .formats = SNDRV_PCM_FMTBIT_S8 |    \
0274                    SNDRV_PCM_FMTBIT_S16_LE |    \
0275                    SNDRV_PCM_FMTBIT_S32_LE, \
0276         },                      \
0277         .ops = &tegra210_amx_in_dai_ops,        \
0278     }
0279 
0280 #define OUT_DAI                         \
0281     {                           \
0282         .name = "AMX-TX-CIF",               \
0283         .playback = {                   \
0284             .stream_name = "TX-CIF-Playback",   \
0285             .channels_min = 1,          \
0286             .channels_max = 16,         \
0287             .rates = SNDRV_PCM_RATE_8000_192000,    \
0288             .formats = SNDRV_PCM_FMTBIT_S8 |    \
0289                    SNDRV_PCM_FMTBIT_S16_LE |    \
0290                    SNDRV_PCM_FMTBIT_S32_LE, \
0291         },                      \
0292         .capture = {                    \
0293             .stream_name = "TX-CIF-Capture",    \
0294             .channels_min = 1,          \
0295             .channels_max = 16,         \
0296             .rates = SNDRV_PCM_RATE_8000_192000,    \
0297             .formats = SNDRV_PCM_FMTBIT_S8 |    \
0298                    SNDRV_PCM_FMTBIT_S16_LE |    \
0299                    SNDRV_PCM_FMTBIT_S32_LE, \
0300         },                      \
0301         .ops = &tegra210_amx_out_dai_ops,       \
0302     }
0303 
0304 static struct snd_soc_dai_driver tegra210_amx_dais[] = {
0305     IN_DAI(1),
0306     IN_DAI(2),
0307     IN_DAI(3),
0308     IN_DAI(4),
0309     OUT_DAI,
0310 };
0311 
0312 static const struct snd_soc_dapm_widget tegra210_amx_widgets[] = {
0313     SND_SOC_DAPM_AIF_IN("RX1", NULL, 0, TEGRA210_AMX_CTRL, 0, 0),
0314     SND_SOC_DAPM_AIF_IN("RX2", NULL, 0, TEGRA210_AMX_CTRL, 1, 0),
0315     SND_SOC_DAPM_AIF_IN("RX3", NULL, 0, TEGRA210_AMX_CTRL, 2, 0),
0316     SND_SOC_DAPM_AIF_IN("RX4", NULL, 0, TEGRA210_AMX_CTRL, 3, 0),
0317     SND_SOC_DAPM_AIF_OUT("TX", NULL, 0, TEGRA210_AMX_ENABLE,
0318                  TEGRA210_AMX_ENABLE_SHIFT, 0),
0319 };
0320 
0321 #define STREAM_ROUTES(id, sname)                      \
0322     { "RX" #id " XBAR-" sname,  NULL,   "RX" #id " XBAR-TX" },    \
0323     { "RX" #id "-CIF-" sname,   NULL,   "RX" #id " XBAR-" sname },\
0324     { "RX" #id,         NULL,   "RX" #id "-CIF-" sname }, \
0325     { "TX",             NULL,   "RX" #id },       \
0326     { "TX-CIF-" sname,      NULL,   "TX" },           \
0327     { "XBAR-" sname,        NULL,   "TX-CIF-" sname },    \
0328     { "XBAR-RX",            NULL,   "XBAR-" sname }
0329 
0330 #define AMX_ROUTES(id)          \
0331     STREAM_ROUTES(id, "Playback"),  \
0332     STREAM_ROUTES(id, "Capture")
0333 
0334 static const struct snd_soc_dapm_route tegra210_amx_routes[] = {
0335     AMX_ROUTES(1),
0336     AMX_ROUTES(2),
0337     AMX_ROUTES(3),
0338     AMX_ROUTES(4),
0339 };
0340 
0341 #define TEGRA210_AMX_BYTE_MAP_CTRL(reg)                 \
0342     SOC_SINGLE_EXT("Byte Map " #reg, reg, 0, 256, 0,        \
0343                tegra210_amx_get_byte_map,           \
0344                tegra210_amx_put_byte_map)
0345 
0346 static struct snd_kcontrol_new tegra210_amx_controls[] = {
0347     TEGRA210_AMX_BYTE_MAP_CTRL(0),
0348     TEGRA210_AMX_BYTE_MAP_CTRL(1),
0349     TEGRA210_AMX_BYTE_MAP_CTRL(2),
0350     TEGRA210_AMX_BYTE_MAP_CTRL(3),
0351     TEGRA210_AMX_BYTE_MAP_CTRL(4),
0352     TEGRA210_AMX_BYTE_MAP_CTRL(5),
0353     TEGRA210_AMX_BYTE_MAP_CTRL(6),
0354     TEGRA210_AMX_BYTE_MAP_CTRL(7),
0355     TEGRA210_AMX_BYTE_MAP_CTRL(8),
0356     TEGRA210_AMX_BYTE_MAP_CTRL(9),
0357     TEGRA210_AMX_BYTE_MAP_CTRL(10),
0358     TEGRA210_AMX_BYTE_MAP_CTRL(11),
0359     TEGRA210_AMX_BYTE_MAP_CTRL(12),
0360     TEGRA210_AMX_BYTE_MAP_CTRL(13),
0361     TEGRA210_AMX_BYTE_MAP_CTRL(14),
0362     TEGRA210_AMX_BYTE_MAP_CTRL(15),
0363     TEGRA210_AMX_BYTE_MAP_CTRL(16),
0364     TEGRA210_AMX_BYTE_MAP_CTRL(17),
0365     TEGRA210_AMX_BYTE_MAP_CTRL(18),
0366     TEGRA210_AMX_BYTE_MAP_CTRL(19),
0367     TEGRA210_AMX_BYTE_MAP_CTRL(20),
0368     TEGRA210_AMX_BYTE_MAP_CTRL(21),
0369     TEGRA210_AMX_BYTE_MAP_CTRL(22),
0370     TEGRA210_AMX_BYTE_MAP_CTRL(23),
0371     TEGRA210_AMX_BYTE_MAP_CTRL(24),
0372     TEGRA210_AMX_BYTE_MAP_CTRL(25),
0373     TEGRA210_AMX_BYTE_MAP_CTRL(26),
0374     TEGRA210_AMX_BYTE_MAP_CTRL(27),
0375     TEGRA210_AMX_BYTE_MAP_CTRL(28),
0376     TEGRA210_AMX_BYTE_MAP_CTRL(29),
0377     TEGRA210_AMX_BYTE_MAP_CTRL(30),
0378     TEGRA210_AMX_BYTE_MAP_CTRL(31),
0379     TEGRA210_AMX_BYTE_MAP_CTRL(32),
0380     TEGRA210_AMX_BYTE_MAP_CTRL(33),
0381     TEGRA210_AMX_BYTE_MAP_CTRL(34),
0382     TEGRA210_AMX_BYTE_MAP_CTRL(35),
0383     TEGRA210_AMX_BYTE_MAP_CTRL(36),
0384     TEGRA210_AMX_BYTE_MAP_CTRL(37),
0385     TEGRA210_AMX_BYTE_MAP_CTRL(38),
0386     TEGRA210_AMX_BYTE_MAP_CTRL(39),
0387     TEGRA210_AMX_BYTE_MAP_CTRL(40),
0388     TEGRA210_AMX_BYTE_MAP_CTRL(41),
0389     TEGRA210_AMX_BYTE_MAP_CTRL(42),
0390     TEGRA210_AMX_BYTE_MAP_CTRL(43),
0391     TEGRA210_AMX_BYTE_MAP_CTRL(44),
0392     TEGRA210_AMX_BYTE_MAP_CTRL(45),
0393     TEGRA210_AMX_BYTE_MAP_CTRL(46),
0394     TEGRA210_AMX_BYTE_MAP_CTRL(47),
0395     TEGRA210_AMX_BYTE_MAP_CTRL(48),
0396     TEGRA210_AMX_BYTE_MAP_CTRL(49),
0397     TEGRA210_AMX_BYTE_MAP_CTRL(50),
0398     TEGRA210_AMX_BYTE_MAP_CTRL(51),
0399     TEGRA210_AMX_BYTE_MAP_CTRL(52),
0400     TEGRA210_AMX_BYTE_MAP_CTRL(53),
0401     TEGRA210_AMX_BYTE_MAP_CTRL(54),
0402     TEGRA210_AMX_BYTE_MAP_CTRL(55),
0403     TEGRA210_AMX_BYTE_MAP_CTRL(56),
0404     TEGRA210_AMX_BYTE_MAP_CTRL(57),
0405     TEGRA210_AMX_BYTE_MAP_CTRL(58),
0406     TEGRA210_AMX_BYTE_MAP_CTRL(59),
0407     TEGRA210_AMX_BYTE_MAP_CTRL(60),
0408     TEGRA210_AMX_BYTE_MAP_CTRL(61),
0409     TEGRA210_AMX_BYTE_MAP_CTRL(62),
0410     TEGRA210_AMX_BYTE_MAP_CTRL(63),
0411 };
0412 
0413 static const struct snd_soc_component_driver tegra210_amx_cmpnt = {
0414     .dapm_widgets       = tegra210_amx_widgets,
0415     .num_dapm_widgets   = ARRAY_SIZE(tegra210_amx_widgets),
0416     .dapm_routes        = tegra210_amx_routes,
0417     .num_dapm_routes    = ARRAY_SIZE(tegra210_amx_routes),
0418     .controls       = tegra210_amx_controls,
0419     .num_controls       = ARRAY_SIZE(tegra210_amx_controls),
0420 };
0421 
0422 static bool tegra210_amx_wr_reg(struct device *dev, unsigned int reg)
0423 {
0424     switch (reg) {
0425     case TEGRA210_AMX_RX_INT_MASK ... TEGRA210_AMX_RX4_CIF_CTRL:
0426     case TEGRA210_AMX_TX_INT_MASK ... TEGRA210_AMX_CG:
0427     case TEGRA210_AMX_CTRL ... TEGRA210_AMX_CYA:
0428     case TEGRA210_AMX_CFG_RAM_CTRL ... TEGRA210_AMX_CFG_RAM_DATA:
0429         return true;
0430     default:
0431         return false;
0432     }
0433 }
0434 
0435 static bool tegra194_amx_wr_reg(struct device *dev, unsigned int reg)
0436 {
0437     switch (reg) {
0438     case TEGRA194_AMX_RX1_FRAME_PERIOD ... TEGRA194_AMX_RX4_FRAME_PERIOD:
0439         return true;
0440     default:
0441         return tegra210_amx_wr_reg(dev, reg);
0442     }
0443 }
0444 
0445 static bool tegra210_amx_rd_reg(struct device *dev, unsigned int reg)
0446 {
0447     switch (reg) {
0448     case TEGRA210_AMX_RX_STATUS ... TEGRA210_AMX_CFG_RAM_DATA:
0449         return true;
0450     default:
0451         return false;
0452     }
0453 }
0454 
0455 static bool tegra194_amx_rd_reg(struct device *dev, unsigned int reg)
0456 {
0457     switch (reg) {
0458     case TEGRA194_AMX_RX1_FRAME_PERIOD ... TEGRA194_AMX_RX4_FRAME_PERIOD:
0459         return true;
0460     default:
0461         return tegra210_amx_rd_reg(dev, reg);
0462     }
0463 }
0464 
0465 static bool tegra210_amx_volatile_reg(struct device *dev, unsigned int reg)
0466 {
0467     switch (reg) {
0468     case TEGRA210_AMX_RX_STATUS:
0469     case TEGRA210_AMX_RX_INT_STATUS:
0470     case TEGRA210_AMX_RX_INT_SET:
0471     case TEGRA210_AMX_TX_STATUS:
0472     case TEGRA210_AMX_TX_INT_STATUS:
0473     case TEGRA210_AMX_TX_INT_SET:
0474     case TEGRA210_AMX_SOFT_RESET:
0475     case TEGRA210_AMX_STATUS:
0476     case TEGRA210_AMX_INT_STATUS:
0477     case TEGRA210_AMX_CFG_RAM_CTRL:
0478     case TEGRA210_AMX_CFG_RAM_DATA:
0479         return true;
0480     default:
0481         break;
0482     }
0483 
0484     return false;
0485 }
0486 
0487 static const struct regmap_config tegra210_amx_regmap_config = {
0488     .reg_bits       = 32,
0489     .reg_stride     = 4,
0490     .val_bits       = 32,
0491     .max_register       = TEGRA210_AMX_CFG_RAM_DATA,
0492     .writeable_reg      = tegra210_amx_wr_reg,
0493     .readable_reg       = tegra210_amx_rd_reg,
0494     .volatile_reg       = tegra210_amx_volatile_reg,
0495     .reg_defaults       = tegra210_amx_reg_defaults,
0496     .num_reg_defaults   = ARRAY_SIZE(tegra210_amx_reg_defaults),
0497     .cache_type     = REGCACHE_FLAT,
0498 };
0499 
0500 static const struct regmap_config tegra194_amx_regmap_config = {
0501     .reg_bits       = 32,
0502     .reg_stride     = 4,
0503     .val_bits       = 32,
0504     .max_register       = TEGRA194_AMX_RX4_LAST_FRAME_PERIOD,
0505     .writeable_reg      = tegra194_amx_wr_reg,
0506     .readable_reg       = tegra194_amx_rd_reg,
0507     .volatile_reg       = tegra210_amx_volatile_reg,
0508     .reg_defaults       = tegra210_amx_reg_defaults,
0509     .num_reg_defaults   = ARRAY_SIZE(tegra210_amx_reg_defaults),
0510     .cache_type     = REGCACHE_FLAT,
0511 };
0512 
0513 static const struct tegra210_amx_soc_data soc_data_tegra210 = {
0514     .regmap_conf    = &tegra210_amx_regmap_config,
0515 };
0516 
0517 static const struct tegra210_amx_soc_data soc_data_tegra194 = {
0518     .regmap_conf    = &tegra194_amx_regmap_config,
0519     .auto_disable   = true,
0520 };
0521 
0522 static const struct of_device_id tegra210_amx_of_match[] = {
0523     { .compatible = "nvidia,tegra210-amx", .data = &soc_data_tegra210 },
0524     { .compatible = "nvidia,tegra194-amx", .data = &soc_data_tegra194 },
0525     {},
0526 };
0527 MODULE_DEVICE_TABLE(of, tegra210_amx_of_match);
0528 
0529 static int tegra210_amx_platform_probe(struct platform_device *pdev)
0530 {
0531     struct device *dev = &pdev->dev;
0532     struct tegra210_amx *amx;
0533     void __iomem *regs;
0534     int err;
0535     const struct of_device_id *match;
0536     struct tegra210_amx_soc_data *soc_data;
0537 
0538     match = of_match_device(tegra210_amx_of_match, dev);
0539 
0540     soc_data = (struct tegra210_amx_soc_data *)match->data;
0541 
0542     amx = devm_kzalloc(dev, sizeof(*amx), GFP_KERNEL);
0543     if (!amx)
0544         return -ENOMEM;
0545 
0546     amx->soc_data = soc_data;
0547 
0548     dev_set_drvdata(dev, amx);
0549 
0550     regs = devm_platform_ioremap_resource(pdev, 0);
0551     if (IS_ERR(regs))
0552         return PTR_ERR(regs);
0553 
0554     amx->regmap = devm_regmap_init_mmio(dev, regs,
0555                         soc_data->regmap_conf);
0556     if (IS_ERR(amx->regmap)) {
0557         dev_err(dev, "regmap init failed\n");
0558         return PTR_ERR(amx->regmap);
0559     }
0560 
0561     regcache_cache_only(amx->regmap, true);
0562 
0563     err = devm_snd_soc_register_component(dev, &tegra210_amx_cmpnt,
0564                           tegra210_amx_dais,
0565                           ARRAY_SIZE(tegra210_amx_dais));
0566     if (err) {
0567         dev_err(dev, "can't register AMX component, err: %d\n", err);
0568         return err;
0569     }
0570 
0571     pm_runtime_enable(dev);
0572 
0573     return 0;
0574 }
0575 
0576 static int tegra210_amx_platform_remove(struct platform_device *pdev)
0577 {
0578     pm_runtime_disable(&pdev->dev);
0579 
0580     return 0;
0581 }
0582 
0583 static const struct dev_pm_ops tegra210_amx_pm_ops = {
0584     SET_RUNTIME_PM_OPS(tegra210_amx_runtime_suspend,
0585                tegra210_amx_runtime_resume, NULL)
0586     SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
0587                 pm_runtime_force_resume)
0588 };
0589 
0590 static struct platform_driver tegra210_amx_driver = {
0591     .driver = {
0592         .name = "tegra210-amx",
0593         .of_match_table = tegra210_amx_of_match,
0594         .pm = &tegra210_amx_pm_ops,
0595     },
0596     .probe = tegra210_amx_platform_probe,
0597     .remove = tegra210_amx_platform_remove,
0598 };
0599 module_platform_driver(tegra210_amx_driver);
0600 
0601 MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
0602 MODULE_DESCRIPTION("Tegra210 AMX ASoC driver");
0603 MODULE_LICENSE("GPL v2");