File Index
Files and directories
Sign in
FILE

tegra210_admaif.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/tegra/tegra210_admaif.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2// SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES.
   3// All rights reserved.
   4//
   5// tegra210_admaif.c - Tegra ADMAIF driver
   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 "tegra_isomgr_bw.h"
  17#include "tegra210_admaif.h"
  18#include "tegra_cif.h"
  19#include "tegra_pcm.h"
  20
  21#define CH_REG(offset, reg, id)						       \
  22	((offset) + (reg) + (TEGRA_ADMAIF_CHANNEL_REG_STRIDE * (id)))
  23
  24#define CH_TX_REG(reg, id) CH_REG(admaif->soc_data->tx_base, reg, id)
  25
  26#define CH_RX_REG(reg, id) CH_REG(admaif->soc_data->rx_base, reg, id)
  27
  28#define REG_DEFAULTS(id, rx_ctrl, tx_ctrl, tx_base, rx_base, cif_ctrl)	       \
  29	{ CH_REG(rx_base, TEGRA_ADMAIF_RX_INT_MASK, id), 0x00000001 },	       \
  30	{ CH_REG(rx_base, TEGRA_ADMAIF_CH_ACIF_RX_CTRL, id), cif_ctrl },     \
  31	{ CH_REG(rx_base, TEGRA_ADMAIF_RX_FIFO_CTRL, id), rx_ctrl },	       \
  32	{ CH_REG(tx_base, TEGRA_ADMAIF_TX_INT_MASK, id), 0x00000001 },	       \
  33	{ CH_REG(tx_base, TEGRA_ADMAIF_CH_ACIF_TX_CTRL, id), cif_ctrl },     \
  34	{ CH_REG(tx_base, TEGRA_ADMAIF_TX_FIFO_CTRL, id), tx_ctrl }
  35
  36#define ADMAIF_REG_DEFAULTS(id, chip)					       \
  37	REG_DEFAULTS((id) - 1,						       \
  38		chip ## _ADMAIF_RX ## id ## _FIFO_CTRL_REG_DEFAULT,	       \
  39		chip ## _ADMAIF_TX ## id ## _FIFO_CTRL_REG_DEFAULT,	       \
  40		chip ## _ADMAIF_TX_BASE,				       \
  41		chip ## _ADMAIF_RX_BASE,				       \
  42		chip ## _ADMAIF_CIF_REG_DEFAULT)
  43
  44static const struct reg_default tegra186_admaif_reg_defaults[] = {
  45	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA186_ADMAIF_GLOBAL_BASE), 0x00000003},
  46	ADMAIF_REG_DEFAULTS(1, TEGRA186),
  47	ADMAIF_REG_DEFAULTS(2, TEGRA186),
  48	ADMAIF_REG_DEFAULTS(3, TEGRA186),
  49	ADMAIF_REG_DEFAULTS(4, TEGRA186),
  50	ADMAIF_REG_DEFAULTS(5, TEGRA186),
  51	ADMAIF_REG_DEFAULTS(6, TEGRA186),
  52	ADMAIF_REG_DEFAULTS(7, TEGRA186),
  53	ADMAIF_REG_DEFAULTS(8, TEGRA186),
  54	ADMAIF_REG_DEFAULTS(9, TEGRA186),
  55	ADMAIF_REG_DEFAULTS(10, TEGRA186),
  56	ADMAIF_REG_DEFAULTS(11, TEGRA186),
  57	ADMAIF_REG_DEFAULTS(12, TEGRA186),
  58	ADMAIF_REG_DEFAULTS(13, TEGRA186),
  59	ADMAIF_REG_DEFAULTS(14, TEGRA186),
  60	ADMAIF_REG_DEFAULTS(15, TEGRA186),
  61	ADMAIF_REG_DEFAULTS(16, TEGRA186),
  62	ADMAIF_REG_DEFAULTS(17, TEGRA186),
  63	ADMAIF_REG_DEFAULTS(18, TEGRA186),
  64	ADMAIF_REG_DEFAULTS(19, TEGRA186),
  65	ADMAIF_REG_DEFAULTS(20, TEGRA186)
  66};
  67
  68static const struct reg_default tegra210_admaif_reg_defaults[] = {
  69	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA210_ADMAIF_GLOBAL_BASE), 0x00000003},
  70	ADMAIF_REG_DEFAULTS(1, TEGRA210),
  71	ADMAIF_REG_DEFAULTS(2, TEGRA210),
  72	ADMAIF_REG_DEFAULTS(3, TEGRA210),
  73	ADMAIF_REG_DEFAULTS(4, TEGRA210),
  74	ADMAIF_REG_DEFAULTS(5, TEGRA210),
  75	ADMAIF_REG_DEFAULTS(6, TEGRA210),
  76	ADMAIF_REG_DEFAULTS(7, TEGRA210),
  77	ADMAIF_REG_DEFAULTS(8, TEGRA210),
  78	ADMAIF_REG_DEFAULTS(9, TEGRA210),
  79	ADMAIF_REG_DEFAULTS(10, TEGRA210)
  80};
  81
  82static const struct reg_default tegra264_admaif_reg_defaults[] = {
  83	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA264_ADMAIF_GLOBAL_BASE), 0x00000003},
  84	ADMAIF_REG_DEFAULTS(1, TEGRA264),
  85	ADMAIF_REG_DEFAULTS(2, TEGRA264),
  86	ADMAIF_REG_DEFAULTS(3, TEGRA264),
  87	ADMAIF_REG_DEFAULTS(4, TEGRA264),
  88	ADMAIF_REG_DEFAULTS(5, TEGRA264),
  89	ADMAIF_REG_DEFAULTS(6, TEGRA264),
  90	ADMAIF_REG_DEFAULTS(7, TEGRA264),
  91	ADMAIF_REG_DEFAULTS(8, TEGRA264),
  92	ADMAIF_REG_DEFAULTS(9, TEGRA264),
  93	ADMAIF_REG_DEFAULTS(10, TEGRA264),
  94	ADMAIF_REG_DEFAULTS(11, TEGRA264),
  95	ADMAIF_REG_DEFAULTS(12, TEGRA264),
  96	ADMAIF_REG_DEFAULTS(13, TEGRA264),
  97	ADMAIF_REG_DEFAULTS(14, TEGRA264),
  98	ADMAIF_REG_DEFAULTS(15, TEGRA264),
  99	ADMAIF_REG_DEFAULTS(16, TEGRA264),
 100	ADMAIF_REG_DEFAULTS(17, TEGRA264),
 101	ADMAIF_REG_DEFAULTS(18, TEGRA264),
 102	ADMAIF_REG_DEFAULTS(19, TEGRA264),
 103	ADMAIF_REG_DEFAULTS(20, TEGRA264),
 104	ADMAIF_REG_DEFAULTS(21, TEGRA264),
 105	ADMAIF_REG_DEFAULTS(22, TEGRA264),
 106	ADMAIF_REG_DEFAULTS(23, TEGRA264),
 107	ADMAIF_REG_DEFAULTS(24, TEGRA264),
 108	ADMAIF_REG_DEFAULTS(25, TEGRA264),
 109	ADMAIF_REG_DEFAULTS(26, TEGRA264),
 110	ADMAIF_REG_DEFAULTS(27, TEGRA264),
 111	ADMAIF_REG_DEFAULTS(28, TEGRA264),
 112	ADMAIF_REG_DEFAULTS(29, TEGRA264),
 113	ADMAIF_REG_DEFAULTS(30, TEGRA264),
 114	ADMAIF_REG_DEFAULTS(31, TEGRA264),
 115	ADMAIF_REG_DEFAULTS(32, TEGRA264)
 116};
 117
 118static bool tegra_admaif_wr_reg(struct device *dev, unsigned int reg)
 119{
 120	struct tegra_admaif *admaif = dev_get_drvdata(dev);
 121	unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
 122	unsigned int num_ch = admaif->soc_data->num_ch;
 123	unsigned int rx_base = admaif->soc_data->rx_base;
 124	unsigned int tx_base = admaif->soc_data->tx_base;
 125	unsigned int global_base = admaif->soc_data->global_base;
 126	unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
 127	unsigned int rx_max = rx_base + (num_ch * ch_stride);
 128	unsigned int tx_max = tx_base + (num_ch * ch_stride);
 129
 130	if ((reg >= rx_base) && (reg < rx_max)) {
 131		reg = (reg - rx_base) % ch_stride;
 132		if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
 133		    (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) ||
 134		    (reg == TEGRA_ADMAIF_RX_SOFT_RESET) ||
 135		    (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL))
 136			return true;
 137	} else if ((reg >= tx_base) && (reg < tx_max)) {
 138		reg = (reg - tx_base) % ch_stride;
 139		if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
 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			return true;
 147	}
 148
 149	return false;
 150}
 151
 152static bool tegra_admaif_rd_reg(struct device *dev, unsigned int reg)
 153{
 154	struct tegra_admaif *admaif = dev_get_drvdata(dev);
 155	unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
 156	unsigned int num_ch = admaif->soc_data->num_ch;
 157	unsigned int rx_base = admaif->soc_data->rx_base;
 158	unsigned int tx_base = admaif->soc_data->tx_base;
 159	unsigned int global_base = admaif->soc_data->global_base;
 160	unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
 161	unsigned int rx_max = rx_base + (num_ch * ch_stride);
 162	unsigned int tx_max = tx_base + (num_ch * ch_stride);
 163
 164	if ((reg >= rx_base) && (reg < rx_max)) {
 165		reg = (reg - rx_base) % ch_stride;
 166		if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
 167		    (reg == TEGRA_ADMAIF_RX_STATUS) ||
 168		    (reg == TEGRA_ADMAIF_RX_INT_STATUS) ||
 169		    (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) ||
 170		    (reg == TEGRA_ADMAIF_RX_SOFT_RESET) ||
 171		    (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL))
 172			return true;
 173	} else if ((reg >= tx_base) && (reg < tx_max)) {
 174		reg = (reg - tx_base) % ch_stride;
 175		if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
 176		    (reg == TEGRA_ADMAIF_TX_STATUS) ||
 177		    (reg == TEGRA_ADMAIF_TX_INT_STATUS) ||
 178		    (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) ||
 179		    (reg == TEGRA_ADMAIF_TX_SOFT_RESET) ||
 180		    (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL))
 181			return true;
 182	} else if ((reg >= global_base) && (reg < reg_max)) {
 183		if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE)) ||
 184		    (reg == (global_base + TEGRA_ADMAIF_GLOBAL_CG_0)) ||
 185		    (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 bool tegra_admaif_volatile_reg(struct device *dev, unsigned int reg)
 197{
 198	struct tegra_admaif *admaif = dev_get_drvdata(dev);
 199	unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
 200	unsigned int num_ch = admaif->soc_data->num_ch;
 201	unsigned int rx_base = admaif->soc_data->rx_base;
 202	unsigned int tx_base = admaif->soc_data->tx_base;
 203	unsigned int global_base = admaif->soc_data->global_base;
 204	unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
 205	unsigned int rx_max = rx_base + (num_ch * ch_stride);
 206	unsigned int tx_max = tx_base + (num_ch * ch_stride);
 207
 208	if ((reg >= rx_base) && (reg < rx_max)) {
 209		reg = (reg - rx_base) % ch_stride;
 210		if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
 211		    (reg == TEGRA_ADMAIF_RX_STATUS) ||
 212		    (reg == TEGRA_ADMAIF_RX_INT_STATUS) ||
 213		    (reg == TEGRA_ADMAIF_RX_SOFT_RESET))
 214			return true;
 215	} else if ((reg >= tx_base) && (reg < tx_max)) {
 216		reg = (reg - tx_base) % ch_stride;
 217		if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
 218		    (reg == TEGRA_ADMAIF_TX_STATUS) ||
 219		    (reg == TEGRA_ADMAIF_TX_INT_STATUS) ||
 220		    (reg == TEGRA_ADMAIF_TX_SOFT_RESET))
 221			return true;
 222	} else if ((reg >= global_base) && (reg < reg_max)) {
 223		if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) ||
 224		    (reg == (global_base +
 225				TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) ||
 226		    (reg == (global_base +
 227				TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS)))
 228			return true;
 229	}
 230
 231	return false;
 232}
 233
 234static const struct regmap_config tegra210_admaif_regmap_config = {
 235	.reg_bits		= 32,
 236	.reg_stride		= 4,
 237	.val_bits		= 32,
 238	.max_register		= TEGRA210_ADMAIF_LAST_REG,
 239	.writeable_reg		= tegra_admaif_wr_reg,
 240	.readable_reg		= tegra_admaif_rd_reg,
 241	.volatile_reg		= tegra_admaif_volatile_reg,
 242	.reg_defaults		= tegra210_admaif_reg_defaults,
 243	.num_reg_defaults	= TEGRA210_ADMAIF_CHANNEL_COUNT * 6 + 1,
 244	.cache_type		= REGCACHE_FLAT,
 245};
 246
 247static const struct regmap_config tegra186_admaif_regmap_config = {
 248	.reg_bits		= 32,
 249	.reg_stride		= 4,
 250	.val_bits		= 32,
 251	.max_register		= TEGRA186_ADMAIF_LAST_REG,
 252	.writeable_reg		= tegra_admaif_wr_reg,
 253	.readable_reg		= tegra_admaif_rd_reg,
 254	.volatile_reg		= tegra_admaif_volatile_reg,
 255	.reg_defaults		= tegra186_admaif_reg_defaults,
 256	.num_reg_defaults	= TEGRA186_ADMAIF_CHANNEL_COUNT * 6 + 1,
 257	.cache_type		= REGCACHE_FLAT,
 258};
 259
 260static const struct regmap_config tegra264_admaif_regmap_config = {
 261	.reg_bits		= 32,
 262	.reg_stride		= 4,
 263	.val_bits		= 32,
 264	.max_register		= TEGRA264_ADMAIF_LAST_REG,
 265	.writeable_reg		= tegra_admaif_wr_reg,
 266	.readable_reg		= tegra_admaif_rd_reg,
 267	.volatile_reg		= tegra_admaif_volatile_reg,
 268	.reg_defaults		= tegra264_admaif_reg_defaults,
 269	.num_reg_defaults	= TEGRA264_ADMAIF_CHANNEL_COUNT * 6 + 1,
 270	.cache_type		= REGCACHE_FLAT,
 271};
 272
 273static int tegra_admaif_runtime_suspend(struct device *dev)
 274{
 275	struct tegra_admaif *admaif = dev_get_drvdata(dev);
 276
 277	regcache_cache_only(admaif->regmap, true);
 278	regcache_mark_dirty(admaif->regmap);
 279
 280	return 0;
 281}
 282
 283static int tegra_admaif_runtime_resume(struct device *dev)
 284{
 285	struct tegra_admaif *admaif = dev_get_drvdata(dev);
 286
 287	regcache_cache_only(admaif->regmap, false);
 288	regcache_sync(admaif->regmap);
 289
 290	return 0;
 291}
 292
 293static int tegra_admaif_set_pack_mode(struct regmap *map, unsigned int reg,
 294				      int valid_bit)
 295{
 296	switch (valid_bit) {
 297	case DATA_8BIT:
 298		regmap_update_bits(map, reg, PACK8_EN_MASK, PACK8_EN);
 299		regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
 300		break;
 301	case DATA_16BIT:
 302		regmap_update_bits(map, reg, PACK16_EN_MASK, PACK16_EN);
 303		regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
 304		break;
 305	case DATA_32BIT:
 306		regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
 307		regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
 308		break;
 309	default:
 310		return -EINVAL;
 311	}
 312
 313	return 0;
 314}
 315
 316static int tegra_admaif_prepare(struct snd_pcm_substream *substream,
 317				struct snd_soc_dai *dai)
 318{
 319	return tegra_isomgr_adma_setbw(substream, dai, true);
 320}
 321
 322static void tegra_admaif_shutdown(struct snd_pcm_substream *substream,
 323				  struct snd_soc_dai *dai)
 324{
 325	tegra_isomgr_adma_setbw(substream, dai, false);
 326}
 327
 328static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
 329				  struct snd_pcm_hw_params *params,
 330				  struct snd_soc_dai *dai)
 331{
 332	struct device *dev = dai->dev;
 333	struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
 334	struct tegra_cif_conf cif_conf;
 335	unsigned int reg, path;
 336	int valid_bit, channels;
 337
 338	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
 339
 340	switch (params_format(params)) {
 341	case SNDRV_PCM_FORMAT_S8:
 342		cif_conf.audio_bits = TEGRA_ACIF_BITS_8;
 343		cif_conf.client_bits = TEGRA_ACIF_BITS_8;
 344		valid_bit = DATA_8BIT;
 345		break;
 346	case SNDRV_PCM_FORMAT_S16_LE:
 347		cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
 348		cif_conf.client_bits = TEGRA_ACIF_BITS_16;
 349		valid_bit = DATA_16BIT;
 350		break;
 351	case SNDRV_PCM_FORMAT_S24_LE:
 352		cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
 353		cif_conf.client_bits = TEGRA_ACIF_BITS_24;
 354		valid_bit = DATA_32BIT;
 355		break;
 356	case SNDRV_PCM_FORMAT_S32_LE:
 357		cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
 358		cif_conf.client_bits = TEGRA_ACIF_BITS_32;
 359		valid_bit  = DATA_32BIT;
 360		break;
 361	default:
 362		dev_err(dev, "unsupported format!\n");
 363		return -EOPNOTSUPP;
 364	}
 365
 366	channels = params_channels(params);
 367	cif_conf.client_ch = channels;
 368	cif_conf.audio_ch = channels;
 369
 370	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 371		path = ADMAIF_TX_PATH;
 372		reg = CH_TX_REG(TEGRA_ADMAIF_CH_ACIF_TX_CTRL, dai->id);
 373	} else {
 374		path = ADMAIF_RX_PATH;
 375		reg = CH_RX_REG(TEGRA_ADMAIF_CH_ACIF_RX_CTRL, dai->id);
 376	}
 377
 378	cif_conf.mono_conv = admaif->mono_to_stereo[path][dai->id];
 379	cif_conf.stereo_conv = admaif->stereo_to_mono[path][dai->id];
 380
 381	tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit);
 382
 383	if (admaif->soc_data->max_stream_ch == TEGRA264_ADMAIF_MAX_CHANNEL)
 384		tegra264_set_cif(admaif->regmap, reg, &cif_conf);
 385	else
 386		tegra_set_cif(admaif->regmap, reg, &cif_conf);
 387
 388	return 0;
 389}
 390
 391static int tegra_admaif_start(struct snd_soc_dai *dai, int direction)
 392{
 393	struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
 394	unsigned int reg, mask, val;
 395
 396	switch (direction) {
 397	case SNDRV_PCM_STREAM_PLAYBACK:
 398		mask = TX_ENABLE_MASK;
 399		val = TX_ENABLE;
 400		reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
 401		break;
 402	case SNDRV_PCM_STREAM_CAPTURE:
 403		mask = RX_ENABLE_MASK;
 404		val = RX_ENABLE;
 405		reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
 406		break;
 407	default:
 408		return -EINVAL;
 409	}
 410
 411	regmap_update_bits(admaif->regmap, reg, mask, val);
 412
 413	return 0;
 414}
 415
 416static int tegra_admaif_stop(struct snd_soc_dai *dai, int direction)
 417{
 418	struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
 419	unsigned int enable_reg, status_reg, reset_reg, mask, val;
 420	char *dir_name;
 421	int err, enable;
 422
 423	switch (direction) {
 424	case SNDRV_PCM_STREAM_PLAYBACK:
 425		mask = TX_ENABLE_MASK;
 426		enable = TX_ENABLE;
 427		dir_name = "TX";
 428		enable_reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
 429		status_reg = CH_TX_REG(TEGRA_ADMAIF_TX_STATUS, dai->id);
 430		reset_reg = CH_TX_REG(TEGRA_ADMAIF_TX_SOFT_RESET, dai->id);
 431		break;
 432	case SNDRV_PCM_STREAM_CAPTURE:
 433		mask = RX_ENABLE_MASK;
 434		enable = RX_ENABLE;
 435		dir_name = "RX";
 436		enable_reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
 437		status_reg = CH_RX_REG(TEGRA_ADMAIF_RX_STATUS, dai->id);
 438		reset_reg = CH_RX_REG(TEGRA_ADMAIF_RX_SOFT_RESET, dai->id);
 439		break;
 440	default:
 441		return -EINVAL;
 442	}
 443
 444	/* Disable TX/RX channel */
 445	regmap_update_bits(admaif->regmap, enable_reg, mask, ~enable);
 446
 447	/* Wait until ADMAIF TX/RX status is disabled */
 448	err = regmap_read_poll_timeout_atomic(admaif->regmap, status_reg, val,
 449					      !(val & enable), 10, 10000);
 450	if (err < 0)
 451		dev_warn(dai->dev, "timeout: failed to disable ADMAIF%d_%s\n",
 452			 dai->id + 1, dir_name);
 453
 454	/* SW reset */
 455	regmap_update_bits(admaif->regmap, reset_reg, SW_RESET_MASK, SW_RESET);
 456
 457	/* Wait till SW reset is complete */
 458	err = regmap_read_poll_timeout_atomic(admaif->regmap, reset_reg, val,
 459					      !(val & SW_RESET_MASK & SW_RESET),
 460					      10, 10000);
 461	if (err) {
 462		dev_err(dai->dev, "timeout: SW reset failed for ADMAIF%d_%s\n",
 463			dai->id + 1, dir_name);
 464		return err;
 465	}
 466
 467	return 0;
 468}
 469
 470static int tegra_admaif_trigger(struct snd_pcm_substream *substream, int cmd,
 471				struct snd_soc_dai *dai)
 472{
 473	int err;
 474
 475	err = snd_dmaengine_pcm_trigger(substream, cmd);
 476	if (err)
 477		return err;
 478
 479	switch (cmd) {
 480	case SNDRV_PCM_TRIGGER_START:
 481	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 482	case SNDRV_PCM_TRIGGER_RESUME:
 483		return tegra_admaif_start(dai, substream->stream);
 484	case SNDRV_PCM_TRIGGER_STOP:
 485	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 486	case SNDRV_PCM_TRIGGER_SUSPEND:
 487		return tegra_admaif_stop(dai, substream->stream);
 488	default:
 489		return -EINVAL;
 490	}
 491}
 492
 493static int tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol *kcontrol,
 494	struct snd_ctl_elem_value *ucontrol)
 495{
 496	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 497	struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
 498	struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
 499
 500	ucontrol->value.enumerated.item[0] =
 501		admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
 502
 503	return 0;
 504}
 505
 506static int tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol *kcontrol,
 507	struct snd_ctl_elem_value *ucontrol)
 508{
 509	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 510	struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
 511	struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
 512	unsigned int value = ucontrol->value.enumerated.item[0];
 513
 514	if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg])
 515		return 0;
 516
 517	admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
 518
 519	return 1;
 520}
 521
 522static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol,
 523	struct snd_ctl_elem_value *ucontrol)
 524{
 525	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 526	struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
 527	struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
 528
 529	ucontrol->value.enumerated.item[0] =
 530		admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
 531
 532	return 0;
 533}
 534
 535static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol,
 536	struct snd_ctl_elem_value *ucontrol)
 537{
 538	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 539	struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
 540	struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
 541	unsigned int value = ucontrol->value.enumerated.item[0];
 542
 543	if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg])
 544		return 0;
 545
 546	admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
 547
 548	return 1;
 549}
 550
 551static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol,
 552	struct snd_ctl_elem_value *ucontrol)
 553{
 554	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 555	struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
 556	struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
 557
 558	ucontrol->value.enumerated.item[0] =
 559		admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
 560
 561	return 0;
 562}
 563
 564static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol,
 565	struct snd_ctl_elem_value *ucontrol)
 566{
 567	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 568	struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
 569	struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
 570	unsigned int value = ucontrol->value.enumerated.item[0];
 571
 572	if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg])
 573		return 0;
 574
 575	admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
 576
 577	return 1;
 578}
 579
 580static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol,
 581	struct snd_ctl_elem_value *ucontrol)
 582{
 583	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 584	struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
 585	struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
 586
 587	ucontrol->value.enumerated.item[0] =
 588		admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
 589
 590	return 0;
 591}
 592
 593static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol,
 594	struct snd_ctl_elem_value *ucontrol)
 595{
 596	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 597	struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
 598	struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
 599	unsigned int value = ucontrol->value.enumerated.item[0];
 600
 601	if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg])
 602		return 0;
 603
 604	admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
 605
 606	return 1;
 607}
 608
 609static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
 610{
 611	struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
 612
 613	snd_soc_dai_init_dma_data(dai,	&admaif->playback_dma_data[dai->id],
 614					&admaif->capture_dma_data[dai->id]);
 615
 616	return 0;
 617}
 618
 619static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
 620	.probe		= tegra_admaif_dai_probe,
 621	.hw_params	= tegra_admaif_hw_params,
 622	.trigger	= tegra_admaif_trigger,
 623	.shutdown	= tegra_admaif_shutdown,
 624	.prepare	= tegra_admaif_prepare,
 625};
 626
 627#define DAI(dai_name, channel)					\
 628	{							\
 629		.name = dai_name,				\
 630		.playback = {					\
 631			.stream_name = dai_name " Playback",	\
 632			.channels_min = 1,			\
 633			.channels_max = channel,		\
 634			.rates = SNDRV_PCM_RATE_8000_192000,	\
 635			.formats = SNDRV_PCM_FMTBIT_S8 |	\
 636				SNDRV_PCM_FMTBIT_S16_LE |	\
 637				SNDRV_PCM_FMTBIT_S24_LE |	\
 638				SNDRV_PCM_FMTBIT_S32_LE,	\
 639		},						\
 640		.capture = {					\
 641			.stream_name = dai_name " Capture",	\
 642			.channels_min = 1,			\
 643			.channels_max = channel,		\
 644			.rates = SNDRV_PCM_RATE_8000_192000,	\
 645			.formats = SNDRV_PCM_FMTBIT_S8 |	\
 646				SNDRV_PCM_FMTBIT_S16_LE |	\
 647				SNDRV_PCM_FMTBIT_S24_LE |	\
 648				SNDRV_PCM_FMTBIT_S32_LE,	\
 649		},						\
 650		.ops = &tegra_admaif_dai_ops,			\
 651	}
 652
 653static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = {
 654	DAI("ADMAIF1", TEGRA210_ADMAIF_MAX_CHANNEL),
 655	DAI("ADMAIF2", TEGRA210_ADMAIF_MAX_CHANNEL),
 656	DAI("ADMAIF3", TEGRA210_ADMAIF_MAX_CHANNEL),
 657	DAI("ADMAIF4", TEGRA210_ADMAIF_MAX_CHANNEL),
 658	DAI("ADMAIF5", TEGRA210_ADMAIF_MAX_CHANNEL),
 659	DAI("ADMAIF6", TEGRA210_ADMAIF_MAX_CHANNEL),
 660	DAI("ADMAIF7", TEGRA210_ADMAIF_MAX_CHANNEL),
 661	DAI("ADMAIF8", TEGRA210_ADMAIF_MAX_CHANNEL),
 662	DAI("ADMAIF9", TEGRA210_ADMAIF_MAX_CHANNEL),
 663	DAI("ADMAIF10", TEGRA210_ADMAIF_MAX_CHANNEL),
 664};
 665
 666static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = {
 667	DAI("ADMAIF1", TEGRA186_ADMAIF_MAX_CHANNEL),
 668	DAI("ADMAIF2", TEGRA186_ADMAIF_MAX_CHANNEL),
 669	DAI("ADMAIF3", TEGRA186_ADMAIF_MAX_CHANNEL),
 670	DAI("ADMAIF4", TEGRA186_ADMAIF_MAX_CHANNEL),
 671	DAI("ADMAIF5", TEGRA186_ADMAIF_MAX_CHANNEL),
 672	DAI("ADMAIF6", TEGRA186_ADMAIF_MAX_CHANNEL),
 673	DAI("ADMAIF7", TEGRA186_ADMAIF_MAX_CHANNEL),
 674	DAI("ADMAIF8", TEGRA186_ADMAIF_MAX_CHANNEL),
 675	DAI("ADMAIF9", TEGRA186_ADMAIF_MAX_CHANNEL),
 676	DAI("ADMAIF10", TEGRA186_ADMAIF_MAX_CHANNEL),
 677	DAI("ADMAIF11", TEGRA186_ADMAIF_MAX_CHANNEL),
 678	DAI("ADMAIF12", TEGRA186_ADMAIF_MAX_CHANNEL),
 679	DAI("ADMAIF13", TEGRA186_ADMAIF_MAX_CHANNEL),
 680	DAI("ADMAIF14", TEGRA186_ADMAIF_MAX_CHANNEL),
 681	DAI("ADMAIF15", TEGRA186_ADMAIF_MAX_CHANNEL),
 682	DAI("ADMAIF16", TEGRA186_ADMAIF_MAX_CHANNEL),
 683	DAI("ADMAIF17", TEGRA186_ADMAIF_MAX_CHANNEL),
 684	DAI("ADMAIF18", TEGRA186_ADMAIF_MAX_CHANNEL),
 685	DAI("ADMAIF19", TEGRA186_ADMAIF_MAX_CHANNEL),
 686	DAI("ADMAIF20", TEGRA186_ADMAIF_MAX_CHANNEL),
 687};
 688
 689static struct snd_soc_dai_driver tegra264_admaif_cmpnt_dais[] = {
 690	DAI("ADMAIF1", TEGRA264_ADMAIF_MAX_CHANNEL),
 691	DAI("ADMAIF2", TEGRA264_ADMAIF_MAX_CHANNEL),
 692	DAI("ADMAIF3", TEGRA264_ADMAIF_MAX_CHANNEL),
 693	DAI("ADMAIF4", TEGRA264_ADMAIF_MAX_CHANNEL),
 694	DAI("ADMAIF5", TEGRA264_ADMAIF_MAX_CHANNEL),
 695	DAI("ADMAIF6", TEGRA264_ADMAIF_MAX_CHANNEL),
 696	DAI("ADMAIF7", TEGRA264_ADMAIF_MAX_CHANNEL),
 697	DAI("ADMAIF8", TEGRA264_ADMAIF_MAX_CHANNEL),
 698	DAI("ADMAIF9", TEGRA264_ADMAIF_MAX_CHANNEL),
 699	DAI("ADMAIF10", TEGRA264_ADMAIF_MAX_CHANNEL),
 700	DAI("ADMAIF11", TEGRA264_ADMAIF_MAX_CHANNEL),
 701	DAI("ADMAIF12", TEGRA264_ADMAIF_MAX_CHANNEL),
 702	DAI("ADMAIF13", TEGRA264_ADMAIF_MAX_CHANNEL),
 703	DAI("ADMAIF14", TEGRA264_ADMAIF_MAX_CHANNEL),
 704	DAI("ADMAIF15", TEGRA264_ADMAIF_MAX_CHANNEL),
 705	DAI("ADMAIF16", TEGRA264_ADMAIF_MAX_CHANNEL),
 706	DAI("ADMAIF17", TEGRA264_ADMAIF_MAX_CHANNEL),
 707	DAI("ADMAIF18", TEGRA264_ADMAIF_MAX_CHANNEL),
 708	DAI("ADMAIF19", TEGRA264_ADMAIF_MAX_CHANNEL),
 709	DAI("ADMAIF20", TEGRA264_ADMAIF_MAX_CHANNEL),
 710	DAI("ADMAIF21", TEGRA264_ADMAIF_MAX_CHANNEL),
 711	DAI("ADMAIF22", TEGRA264_ADMAIF_MAX_CHANNEL),
 712	DAI("ADMAIF23", TEGRA264_ADMAIF_MAX_CHANNEL),
 713	DAI("ADMAIF24", TEGRA264_ADMAIF_MAX_CHANNEL),
 714	DAI("ADMAIF25", TEGRA264_ADMAIF_MAX_CHANNEL),
 715	DAI("ADMAIF26", TEGRA264_ADMAIF_MAX_CHANNEL),
 716	DAI("ADMAIF27", TEGRA264_ADMAIF_MAX_CHANNEL),
 717	DAI("ADMAIF28", TEGRA264_ADMAIF_MAX_CHANNEL),
 718	DAI("ADMAIF29", TEGRA264_ADMAIF_MAX_CHANNEL),
 719	DAI("ADMAIF30", TEGRA264_ADMAIF_MAX_CHANNEL),
 720	DAI("ADMAIF31", TEGRA264_ADMAIF_MAX_CHANNEL),
 721	DAI("ADMAIF32", TEGRA264_ADMAIF_MAX_CHANNEL),
 722};
 723
 724static const char * const tegra_admaif_stereo_conv_text[] = {
 725	"CH0", "CH1", "AVG",
 726};
 727
 728static const char * const tegra_admaif_mono_conv_text[] = {
 729	"Zero", "Copy",
 730};
 731
 732/*
 733 * Below macro is added to avoid looping over all ADMAIFx controls related
 734 * to mono/stereo conversions in get()/put() callbacks.
 735 */
 736#define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text)   \
 737{									       \
 738	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,				       \
 739	.info = snd_soc_info_enum_double,				       \
 740	.name = xname,							       \
 741	.get = xhandler_get,						       \
 742	.put = xhandler_put,						       \
 743	.private_value = (unsigned long)&(struct soc_enum)		       \
 744		SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text)   \
 745}
 746
 747#define TEGRA_ADMAIF_CIF_CTRL(reg)					       \
 748	NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,     \
 749			tegra210_admaif_pget_mono_to_stereo,		       \
 750			tegra210_admaif_pput_mono_to_stereo,		       \
 751			tegra_admaif_mono_conv_text),			       \
 752	NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,     \
 753			tegra210_admaif_pget_stereo_to_mono,		       \
 754			tegra210_admaif_pput_stereo_to_mono,		       \
 755			tegra_admaif_stereo_conv_text),			       \
 756	NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1,      \
 757			tegra210_admaif_cget_mono_to_stereo,		       \
 758			tegra210_admaif_cput_mono_to_stereo,		       \
 759			tegra_admaif_mono_conv_text),			       \
 760	NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1,      \
 761			tegra210_admaif_cget_stereo_to_mono,		       \
 762			tegra210_admaif_cput_stereo_to_mono,		       \
 763			tegra_admaif_stereo_conv_text)
 764
 765static struct snd_kcontrol_new tegra210_admaif_controls[] = {
 766	TEGRA_ADMAIF_CIF_CTRL(1),
 767	TEGRA_ADMAIF_CIF_CTRL(2),
 768	TEGRA_ADMAIF_CIF_CTRL(3),
 769	TEGRA_ADMAIF_CIF_CTRL(4),
 770	TEGRA_ADMAIF_CIF_CTRL(5),
 771	TEGRA_ADMAIF_CIF_CTRL(6),
 772	TEGRA_ADMAIF_CIF_CTRL(7),
 773	TEGRA_ADMAIF_CIF_CTRL(8),
 774	TEGRA_ADMAIF_CIF_CTRL(9),
 775	TEGRA_ADMAIF_CIF_CTRL(10),
 776};
 777
 778static struct snd_kcontrol_new tegra186_admaif_controls[] = {
 779	TEGRA_ADMAIF_CIF_CTRL(1),
 780	TEGRA_ADMAIF_CIF_CTRL(2),
 781	TEGRA_ADMAIF_CIF_CTRL(3),
 782	TEGRA_ADMAIF_CIF_CTRL(4),
 783	TEGRA_ADMAIF_CIF_CTRL(5),
 784	TEGRA_ADMAIF_CIF_CTRL(6),
 785	TEGRA_ADMAIF_CIF_CTRL(7),
 786	TEGRA_ADMAIF_CIF_CTRL(8),
 787	TEGRA_ADMAIF_CIF_CTRL(9),
 788	TEGRA_ADMAIF_CIF_CTRL(10),
 789	TEGRA_ADMAIF_CIF_CTRL(11),
 790	TEGRA_ADMAIF_CIF_CTRL(12),
 791	TEGRA_ADMAIF_CIF_CTRL(13),
 792	TEGRA_ADMAIF_CIF_CTRL(14),
 793	TEGRA_ADMAIF_CIF_CTRL(15),
 794	TEGRA_ADMAIF_CIF_CTRL(16),
 795	TEGRA_ADMAIF_CIF_CTRL(17),
 796	TEGRA_ADMAIF_CIF_CTRL(18),
 797	TEGRA_ADMAIF_CIF_CTRL(19),
 798	TEGRA_ADMAIF_CIF_CTRL(20),
 799};
 800
 801static struct snd_kcontrol_new tegra264_admaif_controls[] = {
 802	TEGRA_ADMAIF_CIF_CTRL(1),
 803	TEGRA_ADMAIF_CIF_CTRL(2),
 804	TEGRA_ADMAIF_CIF_CTRL(3),
 805	TEGRA_ADMAIF_CIF_CTRL(4),
 806	TEGRA_ADMAIF_CIF_CTRL(5),
 807	TEGRA_ADMAIF_CIF_CTRL(6),
 808	TEGRA_ADMAIF_CIF_CTRL(7),
 809	TEGRA_ADMAIF_CIF_CTRL(8),
 810	TEGRA_ADMAIF_CIF_CTRL(9),
 811	TEGRA_ADMAIF_CIF_CTRL(10),
 812	TEGRA_ADMAIF_CIF_CTRL(11),
 813	TEGRA_ADMAIF_CIF_CTRL(12),
 814	TEGRA_ADMAIF_CIF_CTRL(13),
 815	TEGRA_ADMAIF_CIF_CTRL(14),
 816	TEGRA_ADMAIF_CIF_CTRL(15),
 817	TEGRA_ADMAIF_CIF_CTRL(16),
 818	TEGRA_ADMAIF_CIF_CTRL(17),
 819	TEGRA_ADMAIF_CIF_CTRL(18),
 820	TEGRA_ADMAIF_CIF_CTRL(19),
 821	TEGRA_ADMAIF_CIF_CTRL(20),
 822	TEGRA_ADMAIF_CIF_CTRL(21),
 823	TEGRA_ADMAIF_CIF_CTRL(22),
 824	TEGRA_ADMAIF_CIF_CTRL(23),
 825	TEGRA_ADMAIF_CIF_CTRL(24),
 826	TEGRA_ADMAIF_CIF_CTRL(25),
 827	TEGRA_ADMAIF_CIF_CTRL(26),
 828	TEGRA_ADMAIF_CIF_CTRL(27),
 829	TEGRA_ADMAIF_CIF_CTRL(28),
 830	TEGRA_ADMAIF_CIF_CTRL(29),
 831	TEGRA_ADMAIF_CIF_CTRL(30),
 832	TEGRA_ADMAIF_CIF_CTRL(31),
 833	TEGRA_ADMAIF_CIF_CTRL(32),
 834};
 835
 836static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
 837	.controls		= tegra210_admaif_controls,
 838	.num_controls		= ARRAY_SIZE(tegra210_admaif_controls),
 839	.pcm_construct		= tegra_pcm_construct,
 840	.open			= tegra_pcm_open,
 841	.close			= tegra_pcm_close,
 842	.hw_params		= tegra_pcm_hw_params,
 843	.pointer		= tegra_pcm_pointer,
 844};
 845
 846static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
 847	.controls		= tegra186_admaif_controls,
 848	.num_controls		= ARRAY_SIZE(tegra186_admaif_controls),
 849	.pcm_construct		= tegra_pcm_construct,
 850	.open			= tegra_pcm_open,
 851	.close			= tegra_pcm_close,
 852	.hw_params		= tegra_pcm_hw_params,
 853	.pointer		= tegra_pcm_pointer,
 854};
 855
 856static const struct snd_soc_component_driver tegra264_admaif_cmpnt = {
 857	.controls		= tegra264_admaif_controls,
 858	.num_controls		= ARRAY_SIZE(tegra264_admaif_controls),
 859	.pcm_construct		= tegra_pcm_construct,
 860	.open			= tegra_pcm_open,
 861	.close			= tegra_pcm_close,
 862	.hw_params		= tegra_pcm_hw_params,
 863	.pointer		= tegra_pcm_pointer,
 864};
 865
 866static const struct tegra_admaif_soc_data soc_data_tegra210 = {
 867	.num_ch		= TEGRA210_ADMAIF_CHANNEL_COUNT,
 868	.max_stream_ch	= TEGRA210_ADMAIF_MAX_CHANNEL,
 869	.cmpnt		= &tegra210_admaif_cmpnt,
 870	.dais		= tegra210_admaif_cmpnt_dais,
 871	.regmap_conf	= &tegra210_admaif_regmap_config,
 872	.global_base	= TEGRA210_ADMAIF_GLOBAL_BASE,
 873	.tx_base	= TEGRA210_ADMAIF_TX_BASE,
 874	.rx_base	= TEGRA210_ADMAIF_RX_BASE,
 875};
 876
 877static const struct tegra_admaif_soc_data soc_data_tegra186 = {
 878	.num_ch		= TEGRA186_ADMAIF_CHANNEL_COUNT,
 879	.max_stream_ch	= TEGRA186_ADMAIF_MAX_CHANNEL,
 880	.cmpnt		= &tegra186_admaif_cmpnt,
 881	.dais		= tegra186_admaif_cmpnt_dais,
 882	.regmap_conf	= &tegra186_admaif_regmap_config,
 883	.global_base	= TEGRA186_ADMAIF_GLOBAL_BASE,
 884	.tx_base	= TEGRA186_ADMAIF_TX_BASE,
 885	.rx_base	= TEGRA186_ADMAIF_RX_BASE,
 886};
 887
 888static const struct tegra_admaif_soc_data soc_data_tegra264 = {
 889	.num_ch		= TEGRA264_ADMAIF_CHANNEL_COUNT,
 890	.max_stream_ch	= TEGRA264_ADMAIF_MAX_CHANNEL,
 891	.cmpnt		= &tegra264_admaif_cmpnt,
 892	.dais		= tegra264_admaif_cmpnt_dais,
 893	.regmap_conf	= &tegra264_admaif_regmap_config,
 894	.global_base	= TEGRA264_ADMAIF_GLOBAL_BASE,
 895	.tx_base	= TEGRA264_ADMAIF_TX_BASE,
 896	.rx_base	= TEGRA264_ADMAIF_RX_BASE,
 897};
 898
 899static const struct of_device_id tegra_admaif_of_match[] = {
 900	{ .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 },
 901	{ .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 },
 902	{ .compatible = "nvidia,tegra264-admaif", .data = &soc_data_tegra264 },
 903	{},
 904};
 905MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
 906
 907static int tegra_admaif_probe(struct platform_device *pdev)
 908{
 909	struct tegra_admaif *admaif;
 910	void __iomem *regs;
 911	struct resource *res;
 912	int err, i;
 913
 914	admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
 915	if (!admaif)
 916		return -ENOMEM;
 917
 918	admaif->soc_data = of_device_get_match_data(&pdev->dev);
 919
 920	dev_set_drvdata(&pdev->dev, admaif);
 921
 922	admaif->capture_dma_data =
 923		devm_kcalloc(&pdev->dev,
 924			     admaif->soc_data->num_ch,
 925			     sizeof(struct snd_dmaengine_dai_dma_data),
 926			     GFP_KERNEL);
 927	if (!admaif->capture_dma_data)
 928		return -ENOMEM;
 929
 930	admaif->playback_dma_data =
 931		devm_kcalloc(&pdev->dev,
 932			     admaif->soc_data->num_ch,
 933			     sizeof(struct snd_dmaengine_dai_dma_data),
 934			     GFP_KERNEL);
 935	if (!admaif->playback_dma_data)
 936		return -ENOMEM;
 937
 938	for (i = 0; i < ADMAIF_PATHS; i++) {
 939		admaif->mono_to_stereo[i] =
 940			devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
 941				     sizeof(unsigned int), GFP_KERNEL);
 942		if (!admaif->mono_to_stereo[i])
 943			return -ENOMEM;
 944
 945		admaif->stereo_to_mono[i] =
 946			devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
 947				     sizeof(unsigned int), GFP_KERNEL);
 948		if (!admaif->stereo_to_mono[i])
 949			return -ENOMEM;
 950	}
 951
 952	regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 953	if (IS_ERR(regs))
 954		return PTR_ERR(regs);
 955
 956	admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
 957					       admaif->soc_data->regmap_conf);
 958	if (IS_ERR(admaif->regmap)) {
 959		dev_err(&pdev->dev, "regmap init failed\n");
 960		return PTR_ERR(admaif->regmap);
 961	}
 962
 963	regcache_cache_only(admaif->regmap, true);
 964
 965	err = tegra_isomgr_adma_register(&pdev->dev);
 966	if (err) {
 967		dev_err(&pdev->dev, "Failed to add interconnect path\n");
 968		return err;
 969	}
 970
 971	regmap_update_bits(admaif->regmap, admaif->soc_data->global_base +
 972			   TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1);
 973
 974	for (i = 0; i < admaif->soc_data->num_ch; i++) {
 975		admaif->playback_dma_data[i].addr = res->start +
 976			CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE, i);
 977
 978		admaif->capture_dma_data[i].addr = res->start +
 979			CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i);
 980
 981		admaif->playback_dma_data[i].addr_width = 32;
 982
 983		if (of_property_read_string_index(pdev->dev.of_node,
 984				"dma-names", (i * 2) + 1,
 985				&admaif->playback_dma_data[i].chan_name) < 0) {
 986			dev_err(&pdev->dev,
 987				"missing property nvidia,dma-names\n");
 988
 989			return -ENODEV;
 990		}
 991
 992		admaif->capture_dma_data[i].addr_width = 32;
 993
 994		if (of_property_read_string_index(pdev->dev.of_node,
 995				"dma-names",
 996				(i * 2),
 997				&admaif->capture_dma_data[i].chan_name) < 0) {
 998			dev_err(&pdev->dev,
 999				"missing property nvidia,dma-names\n");
1000
1001			return -ENODEV;
1002		}
1003	}
1004
1005	err = devm_snd_soc_register_component(&pdev->dev,
1006					      admaif->soc_data->cmpnt,
1007					      admaif->soc_data->dais,
1008					      admaif->soc_data->num_ch);
1009	if (err) {
1010		dev_err(&pdev->dev,
1011			"can't register ADMAIF component, err: %d\n", err);
1012		return err;
1013	}
1014
1015	pm_runtime_enable(&pdev->dev);
1016
1017	return 0;
1018}
1019
1020static void tegra_admaif_remove(struct platform_device *pdev)
1021{
1022	tegra_isomgr_adma_unregister(&pdev->dev);
1023	pm_runtime_disable(&pdev->dev);
1024}
1025
1026static const struct dev_pm_ops tegra_admaif_pm_ops = {
1027	RUNTIME_PM_OPS(tegra_admaif_runtime_suspend,
1028		       tegra_admaif_runtime_resume, NULL)
1029	SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
1030};
1031
1032static struct platform_driver tegra_admaif_driver = {
1033	.probe = tegra_admaif_probe,
1034	.remove = tegra_admaif_remove,
1035	.driver = {
1036		.name = "tegra210-admaif",
1037		.of_match_table = tegra_admaif_of_match,
1038		.pm = pm_ptr(&tegra_admaif_pm_ops),
1039	},
1040};
1041module_platform_driver(tegra_admaif_driver);
1042
1043MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
1044MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
1045MODULE_LICENSE("GPL v2");
~/ Read-only file preview.