File Index
Files and directories
Sign in
FILE

tegra186_asrc.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/tegra/tegra186_asrc.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2// SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION. All rights reserved.
   3//
   4// tegra186_asrc.c - Tegra186 ASRC driver
   5
   6#include <linux/clk.h>
   7#include <linux/delay.h>
   8#include <linux/device.h>
   9#include <linux/io.h>
  10#include <linux/mod_devicetable.h>
  11#include <linux/module.h>
  12#include <linux/platform_device.h>
  13#include <linux/pm_runtime.h>
  14#include <linux/regmap.h>
  15#include <sound/core.h>
  16#include <sound/pcm.h>
  17#include <sound/pcm_params.h>
  18#include <sound/soc.h>
  19
  20#include "tegra186_asrc.h"
  21#include "tegra_cif.h"
  22
  23#define ASRC_STREAM_SOURCE_SELECT(id)					       \
  24	(TEGRA186_ASRC_CFG + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
  25
  26#define ASRC_STREAM_REG(reg, id) ((reg) + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
  27
  28#define ASRC_STREAM_REG_DEFAULTS(id)					       \
  29	{ ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),			       \
  30	  (((id) + 1) << 4) },						       \
  31	{ ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),		       \
  32	  0x1 },							       \
  33	{ ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),		       \
  34	  0x0 },							       \
  35	{ ASRC_STREAM_REG(TEGRA186_ASRC_MUTE_UNMUTE_DURATION, id),	       \
  36	  0x400 },							       \
  37	{ ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, id),		       \
  38	  0x7500 },							       \
  39	{ ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id),		       \
  40	  0x7500 }
  41
  42static const struct reg_default tegra186_asrc_reg_defaults[] = {
  43	ASRC_STREAM_REG_DEFAULTS(0),
  44	ASRC_STREAM_REG_DEFAULTS(1),
  45	ASRC_STREAM_REG_DEFAULTS(2),
  46	ASRC_STREAM_REG_DEFAULTS(3),
  47	ASRC_STREAM_REG_DEFAULTS(4),
  48	ASRC_STREAM_REG_DEFAULTS(5),
  49
  50	{ TEGRA186_ASRC_GLOBAL_ENB, 0},
  51	{ TEGRA186_ASRC_GLOBAL_SOFT_RESET, 0},
  52	{ TEGRA186_ASRC_GLOBAL_CG, 0x1 },
  53	{ TEGRA186_ASRC_GLOBAL_CFG, 0x0 },
  54	{ TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR, 0},
  55	{ TEGRA186_ASRC_GLOBAL_SCRATCH_CFG, 0x0c207980 },
  56	{ TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL, 0x00115500 },
  57	{ TEGRA186_ASRC_GLOBAL_INT_MASK, 0x0},
  58	{ TEGRA186_ASRC_GLOBAL_INT_SET, 0x0},
  59	{ TEGRA186_ASRC_GLOBAL_INT_CLEAR, 0x0},
  60	{ TEGRA186_ASRC_GLOBAL_APR_CTRL, 0x0},
  61	{ TEGRA186_ASRC_GLOBAL_APR_CTRL_ACCESS_CTRL, 0x0},
  62	{ TEGRA186_ASRC_GLOBAL_DISARM_APR, 0x0},
  63	{ TEGRA186_ASRC_GLOBAL_DISARM_APR_ACCESS_CTRL, 0x0},
  64	{ TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS, 0x0},
  65	{ TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS_CTRL, 0x0},
  66	{ TEGRA186_ASRC_CYA, 0x0},
  67};
  68
  69static void tegra186_asrc_lock_stream(struct tegra186_asrc *asrc,
  70				      unsigned int id)
  71{
  72	regmap_write(asrc->regmap,
  73		     ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_LOCK_STATUS,
  74				     id),
  75		     1);
  76}
  77
  78static int tegra186_asrc_runtime_suspend(struct device *dev)
  79{
  80	struct tegra186_asrc *asrc = dev_get_drvdata(dev);
  81
  82	regcache_cache_only(asrc->regmap, true);
  83	regcache_mark_dirty(asrc->regmap);
  84
  85	return 0;
  86}
  87
  88static int tegra186_asrc_runtime_resume(struct device *dev)
  89{
  90	struct tegra186_asrc *asrc = dev_get_drvdata(dev);
  91	int id;
  92
  93	regcache_cache_only(asrc->regmap, false);
  94
  95	/*
  96	 * Below sequence is recommended after a runtime PM cycle.
  97	 * This otherwise leads to transfer failures. The cache
  98	 * sync is done after this to restore other settings.
  99	 */
 100	regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR,
 101		     asrc->soc_data->aram_start_addr);
 102	regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_ENB,
 103		     TEGRA186_ASRC_GLOBAL_EN);
 104
 105	regcache_sync(asrc->regmap);
 106
 107	for (id = 0; id < TEGRA186_ASRC_STREAM_MAX; id++) {
 108		if (asrc->lane[id].ratio_source !=
 109		    TEGRA186_ASRC_RATIO_SOURCE_SW)
 110			continue;
 111
 112		regmap_write(asrc->regmap,
 113			ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
 114					id),
 115			asrc->lane[id].int_part);
 116
 117		regmap_write(asrc->regmap,
 118			ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
 119					id),
 120			asrc->lane[id].frac_part);
 121
 122		tegra186_asrc_lock_stream(asrc, id);
 123	}
 124
 125	return 0;
 126}
 127
 128static int tegra186_asrc_set_audio_cif(struct tegra186_asrc *asrc,
 129				       struct snd_pcm_hw_params *params,
 130				       unsigned int reg)
 131{
 132	int channels, audio_bits;
 133	struct tegra_cif_conf cif_conf;
 134
 135	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
 136
 137	channels = params_channels(params);
 138
 139	switch (params_format(params)) {
 140	case SNDRV_PCM_FORMAT_S16_LE:
 141		audio_bits = TEGRA_ACIF_BITS_16;
 142		break;
 143	case SNDRV_PCM_FORMAT_S24_LE:
 144	case SNDRV_PCM_FORMAT_S32_LE:
 145		audio_bits = TEGRA_ACIF_BITS_32;
 146		break;
 147	default:
 148		return -EINVAL;
 149	}
 150
 151	cif_conf.audio_ch = channels;
 152	cif_conf.client_ch = channels;
 153	cif_conf.audio_bits = audio_bits;
 154	cif_conf.client_bits = TEGRA_ACIF_BITS_24;
 155
 156	tegra_set_cif(asrc->regmap, reg, &cif_conf);
 157
 158	return 0;
 159}
 160
 161static int tegra186_asrc_in_hw_params(struct snd_pcm_substream *substream,
 162				      struct snd_pcm_hw_params *params,
 163				      struct snd_soc_dai *dai)
 164{
 165	struct device *dev = dai->dev;
 166	struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
 167	int ret, id = dai->id;
 168
 169	/* Set input threshold */
 170	regmap_write(asrc->regmap,
 171		     ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, dai->id),
 172		     asrc->lane[id].input_thresh);
 173
 174	ret = tegra186_asrc_set_audio_cif(asrc, params,
 175		ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, dai->id));
 176	if (ret) {
 177		dev_err(dev, "Can't set ASRC RX%d CIF: %d\n", dai->id, ret);
 178		return ret;
 179	}
 180
 181	return ret;
 182}
 183
 184static int tegra186_asrc_out_hw_params(struct snd_pcm_substream *substream,
 185				       struct snd_pcm_hw_params *params,
 186				       struct snd_soc_dai *dai)
 187{
 188	struct device *dev = dai->dev;
 189	struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
 190	int ret, id = dai->id - 7;
 191
 192	 /* Set output threshold */
 193	regmap_write(asrc->regmap,
 194		     ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, id),
 195		     asrc->lane[id].output_thresh);
 196
 197	ret = tegra186_asrc_set_audio_cif(asrc, params,
 198		ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id));
 199	if (ret) {
 200		dev_err(dev, "Can't set ASRC TX%d CIF: %d\n", id, ret);
 201		return ret;
 202	}
 203
 204	/* Set ENABLE_HW_RATIO_COMP */
 205	if (asrc->lane[id].hwcomp_disable) {
 206		regmap_update_bits(asrc->regmap,
 207			ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
 208			TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK,
 209			TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_DISABLE);
 210	} else {
 211		regmap_update_bits(asrc->regmap,
 212			ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
 213			TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK,
 214			TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_ENABLE);
 215
 216		regmap_write(asrc->regmap,
 217			ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_COMP, id),
 218			TEGRA186_ASRC_STREAM_DEFAULT_HW_COMP_BIAS_VALUE);
 219	}
 220
 221	/* Set lock */
 222	regmap_update_bits(asrc->regmap,
 223			   ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
 224			   1, asrc->lane[id].ratio_source);
 225
 226	if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_SW) {
 227		regmap_write(asrc->regmap,
 228			ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
 229			asrc->lane[id].int_part);
 230		regmap_write(asrc->regmap,
 231			ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
 232			asrc->lane[id].frac_part);
 233		tegra186_asrc_lock_stream(asrc, id);
 234	}
 235
 236	return ret;
 237}
 238
 239static int tegra186_asrc_get_ratio_source(struct snd_kcontrol *kcontrol,
 240					  struct snd_ctl_elem_value *ucontrol)
 241{
 242	struct soc_enum *asrc_private =
 243		(struct soc_enum  *)kcontrol->private_value;
 244	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 245	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 246	unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
 247
 248	ucontrol->value.enumerated.item[0] = asrc->lane[id].ratio_source;
 249
 250	return 0;
 251}
 252
 253static int tegra186_asrc_put_ratio_source(struct snd_kcontrol *kcontrol,
 254					  struct snd_ctl_elem_value *ucontrol)
 255{
 256	struct soc_enum *asrc_private =
 257		(struct soc_enum  *)kcontrol->private_value;
 258	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 259	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 260	unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
 261	bool change = false;
 262
 263	asrc->lane[id].ratio_source = ucontrol->value.enumerated.item[0];
 264
 265	regmap_update_bits_check(asrc->regmap, asrc_private->reg,
 266				 TEGRA186_ASRC_STREAM_RATIO_TYPE_MASK,
 267				 asrc->lane[id].ratio_source,
 268				 &change);
 269
 270	return change ? 1 : 0;
 271}
 272
 273static int tegra186_asrc_get_ratio_int(struct snd_kcontrol *kcontrol,
 274				       struct snd_ctl_elem_value *ucontrol)
 275{
 276	struct soc_mixer_control *asrc_private =
 277		(struct soc_mixer_control *)kcontrol->private_value;
 278	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 279	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 280	unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
 281
 282	regmap_read(asrc->regmap,
 283		    ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
 284		    &asrc->lane[id].int_part);
 285
 286	ucontrol->value.integer.value[0] = asrc->lane[id].int_part;
 287
 288	return 0;
 289}
 290
 291static int tegra186_asrc_put_ratio_int(struct snd_kcontrol *kcontrol,
 292				       struct snd_ctl_elem_value *ucontrol)
 293{
 294	struct soc_mixer_control *asrc_private =
 295		(struct soc_mixer_control *)kcontrol->private_value;
 296	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 297	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 298	unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
 299	bool change = false;
 300
 301	if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
 302		dev_err(cmpnt->dev,
 303			"Lane %d ratio source is ARAD, invalid SW update\n",
 304			id);
 305		return -EINVAL;
 306	}
 307
 308	asrc->lane[id].int_part = ucontrol->value.integer.value[0];
 309
 310	regmap_update_bits_check(asrc->regmap,
 311				 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
 312						 id),
 313				 TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK,
 314				 asrc->lane[id].int_part, &change);
 315
 316	tegra186_asrc_lock_stream(asrc, id);
 317
 318	return change ? 1 : 0;
 319}
 320
 321static int tegra186_asrc_get_ratio_frac(struct snd_kcontrol *kcontrol,
 322					struct snd_ctl_elem_value *ucontrol)
 323{
 324	struct soc_mreg_control *asrc_private =
 325		(struct soc_mreg_control *)kcontrol->private_value;
 326	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 327	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 328	unsigned int id = asrc_private->regbase / TEGRA186_ASRC_STREAM_STRIDE;
 329
 330	regmap_read(asrc->regmap,
 331		    ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
 332		    &asrc->lane[id].frac_part);
 333
 334	ucontrol->value.integer.value[0] = asrc->lane[id].frac_part;
 335
 336	return 0;
 337}
 338
 339static int tegra186_asrc_put_ratio_frac(struct snd_kcontrol *kcontrol,
 340					struct snd_ctl_elem_value *ucontrol)
 341{
 342	struct soc_mreg_control *asrc_private =
 343		(struct soc_mreg_control *)kcontrol->private_value;
 344	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 345	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 346	unsigned int id = asrc_private->regbase / TEGRA186_ASRC_STREAM_STRIDE;
 347	bool change = false;
 348
 349	if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
 350		dev_err(cmpnt->dev,
 351			"Lane %d ratio source is ARAD, invalid SW update\n",
 352			id);
 353		return -EINVAL;
 354	}
 355
 356	asrc->lane[id].frac_part = ucontrol->value.integer.value[0];
 357
 358	regmap_update_bits_check(asrc->regmap,
 359				 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
 360						 id),
 361				 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
 362				 asrc->lane[id].frac_part, &change);
 363
 364	tegra186_asrc_lock_stream(asrc, id);
 365
 366	return change ? 1 : 0;
 367}
 368
 369static int tegra186_asrc_get_hwcomp_disable(struct snd_kcontrol *kcontrol,
 370					    struct snd_ctl_elem_value *ucontrol)
 371{
 372	struct soc_mixer_control *asrc_private =
 373		(struct soc_mixer_control *)kcontrol->private_value;
 374	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 375	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 376	unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
 377
 378	ucontrol->value.integer.value[0] = asrc->lane[id].hwcomp_disable;
 379
 380	return 0;
 381}
 382
 383static int tegra186_asrc_put_hwcomp_disable(struct snd_kcontrol *kcontrol,
 384					    struct snd_ctl_elem_value *ucontrol)
 385{
 386	struct soc_mixer_control *asrc_private =
 387		(struct soc_mixer_control *)kcontrol->private_value;
 388	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 389	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 390	unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
 391	int value = ucontrol->value.integer.value[0];
 392
 393	if (value == asrc->lane[id].hwcomp_disable)
 394		return 0;
 395
 396	asrc->lane[id].hwcomp_disable = value;
 397
 398	return 1;
 399}
 400
 401static int tegra186_asrc_get_input_threshold(struct snd_kcontrol *kcontrol,
 402					     struct snd_ctl_elem_value *ucontrol)
 403{
 404	struct soc_mixer_control *asrc_private =
 405		(struct soc_mixer_control *)kcontrol->private_value;
 406	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 407	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 408	unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
 409
 410	ucontrol->value.integer.value[0] = (asrc->lane[id].input_thresh & 0x3);
 411
 412	return 0;
 413}
 414
 415static int tegra186_asrc_put_input_threshold(struct snd_kcontrol *kcontrol,
 416					     struct snd_ctl_elem_value *ucontrol)
 417{
 418	struct soc_mixer_control *asrc_private =
 419		(struct soc_mixer_control *)kcontrol->private_value;
 420	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 421	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 422	unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
 423	int value = (asrc->lane[id].input_thresh & ~(0x3)) |
 424		    ucontrol->value.integer.value[0];
 425
 426	if (value == asrc->lane[id].input_thresh)
 427		return 0;
 428
 429	asrc->lane[id].input_thresh = value;
 430
 431	return 1;
 432}
 433
 434static int tegra186_asrc_get_output_threshold(struct snd_kcontrol *kcontrol,
 435					      struct snd_ctl_elem_value *ucontrol)
 436{
 437	struct soc_mixer_control *asrc_private =
 438		(struct soc_mixer_control *)kcontrol->private_value;
 439	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 440	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 441	unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
 442
 443	ucontrol->value.integer.value[0] = (asrc->lane[id].output_thresh & 0x3);
 444
 445	return 0;
 446}
 447
 448static int tegra186_asrc_put_output_threshold(struct snd_kcontrol *kcontrol,
 449					      struct snd_ctl_elem_value *ucontrol)
 450{
 451	struct soc_mixer_control *asrc_private =
 452		(struct soc_mixer_control *)kcontrol->private_value;
 453	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
 454	struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
 455	unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
 456	int value = (asrc->lane[id].output_thresh & ~(0x3)) |
 457		    ucontrol->value.integer.value[0];
 458
 459	if (value == asrc->lane[id].output_thresh)
 460		return 0;
 461
 462	asrc->lane[id].output_thresh = value;
 463
 464	return 1;
 465}
 466
 467static int tegra186_asrc_widget_event(struct snd_soc_dapm_widget *w,
 468					struct snd_kcontrol *kcontrol, int event)
 469{
 470	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
 471	struct tegra186_asrc *asrc = dev_get_drvdata(cmpnt->dev);
 472	unsigned int id =
 473		(w->reg - TEGRA186_ASRC_ENABLE) / TEGRA186_ASRC_STREAM_STRIDE;
 474
 475	regmap_write(asrc->regmap,
 476		     ASRC_STREAM_REG(TEGRA186_ASRC_SOFT_RESET, id),
 477		     0x1);
 478
 479	return 0;
 480}
 481
 482static const struct snd_soc_dai_ops tegra186_asrc_in_dai_ops = {
 483	.hw_params	= tegra186_asrc_in_hw_params,
 484};
 485
 486static const struct snd_soc_dai_ops tegra186_asrc_out_dai_ops = {
 487	.hw_params	= tegra186_asrc_out_hw_params,
 488};
 489
 490#define IN_DAI(id)						\
 491	{							\
 492		.name = "ASRC-RX-CIF"#id,			\
 493		.playback = {					\
 494			.stream_name = "RX" #id "-CIF-Playback",\
 495			.channels_min = 1,			\
 496			.channels_max = 12,			\
 497			.rates = SNDRV_PCM_RATE_8000_192000,	\
 498			.formats = SNDRV_PCM_FMTBIT_S8 |	\
 499				SNDRV_PCM_FMTBIT_S16_LE |	\
 500				SNDRV_PCM_FMTBIT_S24_LE |	\
 501				SNDRV_PCM_FMTBIT_S32_LE,	\
 502		},						\
 503		.capture = {					\
 504			.stream_name = "RX" #id "-CIF-Capture", \
 505			.channels_min = 1,			\
 506			.channels_max = 12,			\
 507			.rates = SNDRV_PCM_RATE_8000_192000,	\
 508			.formats = SNDRV_PCM_FMTBIT_S8 |	\
 509				SNDRV_PCM_FMTBIT_S16_LE |	\
 510				SNDRV_PCM_FMTBIT_S24_LE |	\
 511				SNDRV_PCM_FMTBIT_S32_LE,	\
 512		},						\
 513		.ops = &tegra186_asrc_in_dai_ops,		\
 514	}
 515
 516#define OUT_DAI(id)						\
 517	{							\
 518		.name = "ASRC-TX-CIF"#id,			\
 519		.playback = {					\
 520			.stream_name = "TX" #id "-CIF-Playback",\
 521			.channels_min = 1,			\
 522			.channels_max = 12,			\
 523			.rates = SNDRV_PCM_RATE_8000_192000,	\
 524			.formats = SNDRV_PCM_FMTBIT_S8 |	\
 525				SNDRV_PCM_FMTBIT_S16_LE |	\
 526				SNDRV_PCM_FMTBIT_S24_LE |	\
 527				SNDRV_PCM_FMTBIT_S32_LE,	\
 528		},						\
 529		.capture = {					\
 530			.stream_name = "TX" #id "-CIF-Capture",	\
 531			.channels_min = 1,			\
 532			.channels_max = 12,			\
 533			.rates = SNDRV_PCM_RATE_8000_192000,	\
 534			.formats = SNDRV_PCM_FMTBIT_S8 |	\
 535				SNDRV_PCM_FMTBIT_S16_LE |	\
 536				SNDRV_PCM_FMTBIT_S24_LE |	\
 537				SNDRV_PCM_FMTBIT_S32_LE,	\
 538		},						\
 539		.ops = &tegra186_asrc_out_dai_ops,		\
 540	}
 541
 542static struct snd_soc_dai_driver tegra186_asrc_dais[] = {
 543	/* ASRC Input */
 544	IN_DAI(1),
 545	IN_DAI(2),
 546	IN_DAI(3),
 547	IN_DAI(4),
 548	IN_DAI(5),
 549	IN_DAI(6),
 550	IN_DAI(7),
 551	/* ASRC Output */
 552	OUT_DAI(1),
 553	OUT_DAI(2),
 554	OUT_DAI(3),
 555	OUT_DAI(4),
 556	OUT_DAI(5),
 557	OUT_DAI(6),
 558};
 559
 560static const struct snd_soc_dapm_widget tegra186_asrc_widgets[] = {
 561	SND_SOC_DAPM_AIF_IN("RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
 562	SND_SOC_DAPM_AIF_IN("RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
 563	SND_SOC_DAPM_AIF_IN("RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
 564	SND_SOC_DAPM_AIF_IN("RX4", NULL, 0, SND_SOC_NOPM, 0, 0),
 565	SND_SOC_DAPM_AIF_IN("RX5", NULL, 0, SND_SOC_NOPM, 0, 0),
 566	SND_SOC_DAPM_AIF_IN("RX6", NULL, 0, SND_SOC_NOPM, 0, 0),
 567	SND_SOC_DAPM_AIF_IN("RX7", NULL, 0, SND_SOC_NOPM, 0, 0),
 568
 569	SND_SOC_DAPM_AIF_OUT_E("TX1", NULL, 0,
 570			       ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 0),
 571			       TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
 572			       tegra186_asrc_widget_event,
 573			       SND_SOC_DAPM_POST_PMD),
 574
 575	SND_SOC_DAPM_AIF_OUT_E("TX2", NULL, 0,
 576			       ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 1),
 577			       TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
 578			       tegra186_asrc_widget_event,
 579			       SND_SOC_DAPM_POST_PMD),
 580
 581	SND_SOC_DAPM_AIF_OUT_E("TX3", NULL, 0,
 582			       ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 2),
 583			       TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
 584			       tegra186_asrc_widget_event,
 585			       SND_SOC_DAPM_POST_PMD),
 586
 587	SND_SOC_DAPM_AIF_OUT_E("TX4", NULL, 0,
 588			       ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 3),
 589			       TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
 590			       tegra186_asrc_widget_event,
 591			       SND_SOC_DAPM_POST_PMD),
 592
 593	SND_SOC_DAPM_AIF_OUT_E("TX5", NULL, 0,
 594			       ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 4),
 595			       TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
 596			       tegra186_asrc_widget_event,
 597			       SND_SOC_DAPM_POST_PMD),
 598
 599	SND_SOC_DAPM_AIF_OUT_E("TX6", NULL, 0,
 600			       ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 5),
 601			       TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
 602			       tegra186_asrc_widget_event,
 603			       SND_SOC_DAPM_POST_PMD),
 604
 605	SND_SOC_DAPM_SPK("Depacketizer", NULL),
 606};
 607
 608#define ASRC_STREAM_ROUTE(id, sname)					   \
 609	{ "RX" #id " XBAR-" sname,      NULL,   "RX" #id " XBAR-TX" },	   \
 610	{ "RX" #id "-CIF-" sname,       NULL,   "RX" #id " XBAR-" sname }, \
 611	{ "RX" #id,                     NULL,   "RX" #id "-CIF-" sname },  \
 612	{ "TX" #id,			NULL,   "RX" #id },		   \
 613	{ "TX" #id "-CIF-" sname,       NULL,   "TX" #id },		   \
 614	{ "TX" #id " XBAR-" sname,      NULL,   "TX" #id "-CIF-" sname },  \
 615	{ "TX" #id " XBAR-RX",          NULL,   "TX" #id " XBAR-" sname },
 616
 617#define ASRC_ROUTE(id)							   \
 618	ASRC_STREAM_ROUTE(id, "Playback")				   \
 619	ASRC_STREAM_ROUTE(id, "Capture")
 620
 621#define ASRC_RATIO_ROUTE(sname)						   \
 622	{ "RX7 XBAR-" sname,		NULL,	"RX7 XBAR-TX" },	   \
 623	{ "RX7-CIF-" sname,		NULL,	"RX7 XBAR-" sname },	   \
 624	{ "RX7",			NULL,	"RX7-CIF-" sname },	   \
 625	{ "Depacketizer",		NULL,	"RX7" },
 626
 627static const struct snd_soc_dapm_route tegra186_asrc_routes[] = {
 628	ASRC_ROUTE(1)
 629	ASRC_ROUTE(2)
 630	ASRC_ROUTE(3)
 631	ASRC_ROUTE(4)
 632	ASRC_ROUTE(5)
 633	ASRC_ROUTE(6)
 634	ASRC_RATIO_ROUTE("Playback")
 635	ASRC_RATIO_ROUTE("Capture")
 636};
 637
 638static const char * const tegra186_asrc_ratio_source_text[] = {
 639	"ARAD",
 640	"SW",
 641};
 642
 643#define ASRC_SOURCE_DECL(name, id)					\
 644	static const struct soc_enum name =				\
 645		SOC_ENUM_SINGLE(ASRC_STREAM_SOURCE_SELECT(id),		\
 646				0, 2, tegra186_asrc_ratio_source_text)
 647
 648ASRC_SOURCE_DECL(src_select1, 0);
 649ASRC_SOURCE_DECL(src_select2, 1);
 650ASRC_SOURCE_DECL(src_select3, 2);
 651ASRC_SOURCE_DECL(src_select4, 3);
 652ASRC_SOURCE_DECL(src_select5, 4);
 653ASRC_SOURCE_DECL(src_select6, 5);
 654
 655#define SOC_SINGLE_EXT_FRAC(xname, xregbase, xmax, xget, xput)		\
 656{									\
 657	.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,				\
 658	.name	= (xname),						\
 659	.info	= snd_soc_info_xr_sx,					\
 660	.get	= xget,							\
 661	.put	= xput,							\
 662									\
 663	.private_value = (unsigned long)&(struct soc_mreg_control)	\
 664	{								\
 665		.regbase	= xregbase,				\
 666		.regcount	= 1,					\
 667		.nbits		= 32,					\
 668		.invert		= 0,					\
 669		.min		= 0,					\
 670		.max		= xmax					\
 671	}								\
 672}
 673
 674static const struct snd_kcontrol_new tegra186_asrc_controls[] = {
 675	/* Controls for integer part of ratio */
 676	SOC_SINGLE_EXT("Ratio1 Integer Part",
 677		       ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 0),
 678		       0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
 679		       tegra186_asrc_get_ratio_int,
 680		       tegra186_asrc_put_ratio_int),
 681
 682	SOC_SINGLE_EXT("Ratio2 Integer Part",
 683		       ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 1),
 684		       0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
 685		       tegra186_asrc_get_ratio_int,
 686		       tegra186_asrc_put_ratio_int),
 687
 688	SOC_SINGLE_EXT("Ratio3 Integer Part",
 689		       ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 2),
 690		       0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
 691		       tegra186_asrc_get_ratio_int,
 692		       tegra186_asrc_put_ratio_int),
 693
 694	SOC_SINGLE_EXT("Ratio4 Integer Part",
 695		       ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 3),
 696		       0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
 697		       tegra186_asrc_get_ratio_int,
 698		       tegra186_asrc_put_ratio_int),
 699
 700	SOC_SINGLE_EXT("Ratio5 Integer Part",
 701		       ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 4),
 702		       0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
 703		       tegra186_asrc_get_ratio_int,
 704		       tegra186_asrc_put_ratio_int),
 705
 706	SOC_SINGLE_EXT("Ratio6 Integer Part",
 707		       ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 5),
 708		       0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
 709		       tegra186_asrc_get_ratio_int,
 710		       tegra186_asrc_put_ratio_int),
 711
 712	/* Controls for fractional part of ratio */
 713	SOC_SINGLE_EXT_FRAC("Ratio1 Fractional Part",
 714			    ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 0),
 715			    TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
 716			    tegra186_asrc_get_ratio_frac,
 717			    tegra186_asrc_put_ratio_frac),
 718
 719	SOC_SINGLE_EXT_FRAC("Ratio2 Fractional Part",
 720			    ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 1),
 721			    TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
 722			    tegra186_asrc_get_ratio_frac,
 723			    tegra186_asrc_put_ratio_frac),
 724
 725	SOC_SINGLE_EXT_FRAC("Ratio3 Fractional Part",
 726			    ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 2),
 727			    TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
 728			    tegra186_asrc_get_ratio_frac,
 729			    tegra186_asrc_put_ratio_frac),
 730
 731	SOC_SINGLE_EXT_FRAC("Ratio4 Fractional Part",
 732			    ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 3),
 733			    TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
 734			    tegra186_asrc_get_ratio_frac,
 735			    tegra186_asrc_put_ratio_frac),
 736
 737	SOC_SINGLE_EXT_FRAC("Ratio5 Fractional Part",
 738			    ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 4),
 739			    TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
 740			    tegra186_asrc_get_ratio_frac,
 741			    tegra186_asrc_put_ratio_frac),
 742
 743	SOC_SINGLE_EXT_FRAC("Ratio6 Fractional Part",
 744			    ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 5),
 745			    TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
 746			    tegra186_asrc_get_ratio_frac,
 747			    tegra186_asrc_put_ratio_frac),
 748
 749	/* Source of ratio provider */
 750	SOC_ENUM_EXT("Ratio1 Source", src_select1,
 751		     tegra186_asrc_get_ratio_source,
 752		     tegra186_asrc_put_ratio_source),
 753
 754	SOC_ENUM_EXT("Ratio2 Source", src_select2,
 755		     tegra186_asrc_get_ratio_source,
 756		     tegra186_asrc_put_ratio_source),
 757
 758	SOC_ENUM_EXT("Ratio3 Source", src_select3,
 759		     tegra186_asrc_get_ratio_source,
 760		     tegra186_asrc_put_ratio_source),
 761
 762	SOC_ENUM_EXT("Ratio4 Source", src_select4,
 763		     tegra186_asrc_get_ratio_source,
 764		     tegra186_asrc_put_ratio_source),
 765
 766	SOC_ENUM_EXT("Ratio5 Source", src_select5,
 767		     tegra186_asrc_get_ratio_source,
 768		     tegra186_asrc_put_ratio_source),
 769
 770	SOC_ENUM_EXT("Ratio6 Source", src_select6,
 771		     tegra186_asrc_get_ratio_source,
 772		     tegra186_asrc_put_ratio_source),
 773
 774	/* Disable HW managed overflow/underflow issue at input and output */
 775	SOC_SINGLE_EXT("Stream1 HW Component Disable",
 776		       ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 0), 0, 1, 0,
 777		       tegra186_asrc_get_hwcomp_disable,
 778		       tegra186_asrc_put_hwcomp_disable),
 779
 780	SOC_SINGLE_EXT("Stream2 HW Component Disable",
 781		       ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 1), 0, 1, 0,
 782		       tegra186_asrc_get_hwcomp_disable,
 783		       tegra186_asrc_put_hwcomp_disable),
 784
 785	SOC_SINGLE_EXT("Stream3 HW Component Disable",
 786		       ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 2), 0, 1, 0,
 787		       tegra186_asrc_get_hwcomp_disable,
 788		       tegra186_asrc_put_hwcomp_disable),
 789
 790	SOC_SINGLE_EXT("Stream4 HW Component Disable",
 791		       ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 3), 0, 1, 0,
 792		       tegra186_asrc_get_hwcomp_disable,
 793		       tegra186_asrc_put_hwcomp_disable),
 794
 795	SOC_SINGLE_EXT("Stream5 HW Component Disable",
 796		       ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 4), 0, 1, 0,
 797		       tegra186_asrc_get_hwcomp_disable,
 798		       tegra186_asrc_put_hwcomp_disable),
 799
 800	SOC_SINGLE_EXT("Stream6 HW Component Disable",
 801		       ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 5), 0, 1, 0,
 802		       tegra186_asrc_get_hwcomp_disable,
 803		       tegra186_asrc_put_hwcomp_disable),
 804
 805	/* Input threshold for watermark fields */
 806	SOC_SINGLE_EXT("Stream1 Input Threshold",
 807		       ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 0), 0, 3, 0,
 808		       tegra186_asrc_get_input_threshold,
 809		       tegra186_asrc_put_input_threshold),
 810
 811	SOC_SINGLE_EXT("Stream2 Input Threshold",
 812		       ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 1), 0, 3, 0,
 813		       tegra186_asrc_get_input_threshold,
 814		       tegra186_asrc_put_input_threshold),
 815
 816	SOC_SINGLE_EXT("Stream3 Input Threshold",
 817		       ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 2), 0, 3, 0,
 818		       tegra186_asrc_get_input_threshold,
 819		       tegra186_asrc_put_input_threshold),
 820
 821	SOC_SINGLE_EXT("Stream4 Input Threshold",
 822		       ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 3), 0, 3, 0,
 823		       tegra186_asrc_get_input_threshold,
 824		       tegra186_asrc_put_input_threshold),
 825
 826	SOC_SINGLE_EXT("Stream5 Input Threshold",
 827		       ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 4), 0, 3, 0,
 828		       tegra186_asrc_get_input_threshold,
 829		       tegra186_asrc_put_input_threshold),
 830
 831	SOC_SINGLE_EXT("Stream6 Input Threshold",
 832		       ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 4), 0, 3, 0,
 833		       tegra186_asrc_get_input_threshold,
 834		       tegra186_asrc_put_input_threshold),
 835
 836	/* Output threshold for watermark fields */
 837	SOC_SINGLE_EXT("Stream1 Output Threshold",
 838		       ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 0), 0, 3, 0,
 839		       tegra186_asrc_get_output_threshold,
 840		       tegra186_asrc_put_output_threshold),
 841
 842	SOC_SINGLE_EXT("Stream2 Output Threshold",
 843		       ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 1), 0, 3, 0,
 844		       tegra186_asrc_get_output_threshold,
 845		       tegra186_asrc_put_output_threshold),
 846
 847	SOC_SINGLE_EXT("Stream3 Output Threshold",
 848		       ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 2), 0, 3, 0,
 849		       tegra186_asrc_get_output_threshold,
 850		       tegra186_asrc_put_output_threshold),
 851
 852	SOC_SINGLE_EXT("Stream4 Output Threshold",
 853		       ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 3), 0, 3, 0,
 854		       tegra186_asrc_get_output_threshold,
 855		       tegra186_asrc_put_output_threshold),
 856
 857	SOC_SINGLE_EXT("Stream5 Output Threshold",
 858		       ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 4), 0, 3, 0,
 859		       tegra186_asrc_get_output_threshold,
 860		       tegra186_asrc_put_output_threshold),
 861
 862	SOC_SINGLE_EXT("Stream6 Output Threshold",
 863		       ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 5), 0, 3, 0,
 864		       tegra186_asrc_get_output_threshold,
 865		       tegra186_asrc_put_output_threshold),
 866};
 867
 868static const struct snd_soc_component_driver tegra186_asrc_cmpnt = {
 869	.dapm_widgets		= tegra186_asrc_widgets,
 870	.num_dapm_widgets	= ARRAY_SIZE(tegra186_asrc_widgets),
 871	.dapm_routes		= tegra186_asrc_routes,
 872	.num_dapm_routes	= ARRAY_SIZE(tegra186_asrc_routes),
 873	.controls		= tegra186_asrc_controls,
 874	.num_controls		= ARRAY_SIZE(tegra186_asrc_controls),
 875};
 876
 877static bool tegra186_asrc_wr_reg(struct device *dev, unsigned int reg)
 878{
 879	if (reg < TEGRA186_ASRC_STREAM_LIMIT)
 880		reg %= TEGRA186_ASRC_STREAM_STRIDE;
 881
 882	switch (reg) {
 883	case TEGRA186_ASRC_CFG ... TEGRA186_ASRC_RATIO_COMP:
 884	case TEGRA186_ASRC_RX_CIF_CTRL:
 885	case TEGRA186_ASRC_TX_CIF_CTRL:
 886	case TEGRA186_ASRC_ENABLE:
 887	case TEGRA186_ASRC_SOFT_RESET:
 888	case TEGRA186_ASRC_GLOBAL_ENB ... TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL:
 889	case TEGRA186_ASRC_GLOBAL_INT_MASK ... TEGRA186_ASRC_GLOBAL_INT_CLEAR:
 890	case TEGRA186_ASRC_GLOBAL_APR_CTRL ... TEGRA186_ASRC_CYA:
 891		return true;
 892	default:
 893		return false;
 894	}
 895}
 896
 897static bool tegra186_asrc_rd_reg(struct device *dev, unsigned int reg)
 898{
 899	if (reg < TEGRA186_ASRC_STREAM_LIMIT)
 900		reg %= TEGRA186_ASRC_STREAM_STRIDE;
 901
 902	if (tegra186_asrc_wr_reg(dev, reg))
 903		return true;
 904
 905	switch (reg) {
 906	case TEGRA186_ASRC_RX_STATUS:
 907	case TEGRA186_ASRC_TX_STATUS:
 908	case TEGRA186_ASRC_STATUS ... TEGRA186_ASRC_OUTSAMPLEBUF_CFG:
 909	case TEGRA186_ASRC_RATIO_UPD_RX_STATUS:
 910	case TEGRA186_ASRC_GLOBAL_STATUS ... TEGRA186_ASRC_GLOBAL_INT_STATUS:
 911	case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG:
 912		return true;
 913	default:
 914		return false;
 915	}
 916}
 917
 918static bool tegra186_asrc_volatile_reg(struct device *dev, unsigned int reg)
 919{
 920	if (reg < TEGRA186_ASRC_STREAM_LIMIT)
 921		reg %= TEGRA186_ASRC_STREAM_STRIDE;
 922
 923	switch (reg) {
 924	case TEGRA186_ASRC_RX_STATUS:
 925	case TEGRA186_ASRC_TX_STATUS:
 926	case TEGRA186_ASRC_SOFT_RESET:
 927	case TEGRA186_ASRC_RATIO_INT_PART:
 928	case TEGRA186_ASRC_RATIO_FRAC_PART:
 929	case TEGRA186_ASRC_STATUS:
 930	case TEGRA186_ASRC_RATIO_LOCK_STATUS:
 931	case TEGRA186_ASRC_RATIO_UPD_RX_STATUS:
 932	case TEGRA186_ASRC_GLOBAL_SOFT_RESET:
 933	case TEGRA186_ASRC_GLOBAL_STATUS:
 934	case TEGRA186_ASRC_GLOBAL_STREAM_ENABLE_STATUS:
 935	case TEGRA186_ASRC_GLOBAL_INT_STATUS:
 936	case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG:
 937		return true;
 938	default:
 939		return false;
 940	}
 941}
 942
 943static const struct regmap_config tegra186_asrc_regmap_config = {
 944	.reg_bits		= 32,
 945	.reg_stride		= 4,
 946	.val_bits		= 32,
 947	.max_register		= TEGRA186_ASRC_CYA,
 948	.writeable_reg		= tegra186_asrc_wr_reg,
 949	.readable_reg		= tegra186_asrc_rd_reg,
 950	.volatile_reg		= tegra186_asrc_volatile_reg,
 951	.reg_defaults		= tegra186_asrc_reg_defaults,
 952	.num_reg_defaults	= ARRAY_SIZE(tegra186_asrc_reg_defaults),
 953	.cache_type		= REGCACHE_FLAT,
 954};
 955
 956static const struct tegra_asrc_soc_data soc_data_tegra186 = {
 957	.aram_start_addr	= TEGRA186_ASRC_ARAM_START_ADDR,
 958};
 959
 960static const struct tegra_asrc_soc_data soc_data_tegra264 = {
 961	.aram_start_addr	= TEGRA264_ASRC_ARAM_START_ADDR,
 962};
 963
 964static const struct of_device_id tegra186_asrc_of_match[] = {
 965	{ .compatible = "nvidia,tegra186-asrc", .data = &soc_data_tegra186 },
 966	{ .compatible = "nvidia,tegra264-asrc", .data = &soc_data_tegra264 },
 967	{},
 968};
 969MODULE_DEVICE_TABLE(of, tegra186_asrc_of_match);
 970
 971static int tegra186_asrc_platform_probe(struct platform_device *pdev)
 972{
 973	struct device *dev = &pdev->dev;
 974	struct tegra186_asrc *asrc;
 975	void __iomem *regs;
 976	unsigned int i;
 977	int err;
 978
 979	asrc = devm_kzalloc(dev, sizeof(*asrc), GFP_KERNEL);
 980	if (!asrc)
 981		return -ENOMEM;
 982
 983	dev_set_drvdata(dev, asrc);
 984
 985	regs = devm_platform_ioremap_resource(pdev, 0);
 986	if (IS_ERR(regs))
 987		return PTR_ERR(regs);
 988
 989	asrc->regmap = devm_regmap_init_mmio(dev, regs,
 990					     &tegra186_asrc_regmap_config);
 991	if (IS_ERR(asrc->regmap)) {
 992		dev_err(dev, "regmap init failed\n");
 993		return PTR_ERR(asrc->regmap);
 994	}
 995
 996	asrc->soc_data = of_device_get_match_data(&pdev->dev);
 997
 998	regcache_cache_only(asrc->regmap, true);
 999
1000	regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_CFG,
1001		     TEGRA186_ASRC_GLOBAL_CFG_FRAC_32BIT_PRECISION);
1002
1003	/* Initialize default output srate */
1004	for (i = 0; i < TEGRA186_ASRC_STREAM_MAX; i++) {
1005		asrc->lane[i].ratio_source = TEGRA186_ASRC_RATIO_SOURCE_SW;
1006		asrc->lane[i].int_part = 1;
1007		asrc->lane[i].frac_part = 0;
1008		asrc->lane[i].hwcomp_disable = 0;
1009		asrc->lane[i].input_thresh =
1010			TEGRA186_ASRC_STREAM_DEFAULT_INPUT_HW_COMP_THRESH_CFG;
1011		asrc->lane[i].output_thresh =
1012			TEGRA186_ASRC_STREAM_DEFAULT_OUTPUT_HW_COMP_THRESH_CFG;
1013	}
1014
1015	err = devm_snd_soc_register_component(dev, &tegra186_asrc_cmpnt,
1016					      tegra186_asrc_dais,
1017					      ARRAY_SIZE(tegra186_asrc_dais));
1018	if (err) {
1019		dev_err(dev, "can't register ASRC component, err: %d\n", err);
1020		return err;
1021	}
1022
1023	pm_runtime_enable(dev);
1024
1025	return 0;
1026}
1027
1028static void tegra186_asrc_platform_remove(struct platform_device *pdev)
1029{
1030	pm_runtime_disable(&pdev->dev);
1031}
1032
1033static const struct dev_pm_ops tegra186_asrc_pm_ops = {
1034	RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend,
1035		       tegra186_asrc_runtime_resume, NULL)
1036	SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
1037};
1038
1039static struct platform_driver tegra186_asrc_driver = {
1040	.driver = {
1041		.name = "tegra186-asrc",
1042		.of_match_table = tegra186_asrc_of_match,
1043		.pm = pm_ptr(&tegra186_asrc_pm_ops),
1044	},
1045	.probe = tegra186_asrc_platform_probe,
1046	.remove = tegra186_asrc_platform_remove,
1047};
1048module_platform_driver(tegra186_asrc_driver)
1049
1050MODULE_AUTHOR("Junghyun Kim <juskim@nvidia.com>");
1051MODULE_DESCRIPTION("Tegra186 ASRC ASoC driver");
1052MODULE_LICENSE("GPL");
~/ Read-only file preview.