File Index
Files and directories
Sign in
FILE

madera.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/codecs/madera.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2//
   3// Cirrus Logic Madera class codecs common support
   4//
   5// Copyright (C) 2015-2019 Cirrus Logic, Inc. and
   6//                         Cirrus Logic International Semiconductor Ltd.
   7//
   8
   9#include <linux/delay.h>
  10#include <linux/gcd.h>
  11#include <linux/module.h>
  12#include <linux/pm_runtime.h>
  13#include <linux/slab.h>
  14#include <linux/string_choices.h>
  15#include <sound/pcm.h>
  16#include <sound/pcm_params.h>
  17#include <sound/tlv.h>
  18
  19#include <linux/irqchip/irq-madera.h>
  20#include <linux/mfd/madera/core.h>
  21#include <linux/mfd/madera/registers.h>
  22#include <linux/mfd/madera/pdata.h>
  23#include <sound/madera-pdata.h>
  24
  25#include <dt-bindings/sound/madera.h>
  26
  27#include "madera.h"
  28
  29#define MADERA_AIF_BCLK_CTRL			0x00
  30#define MADERA_AIF_TX_PIN_CTRL			0x01
  31#define MADERA_AIF_RX_PIN_CTRL			0x02
  32#define MADERA_AIF_RATE_CTRL			0x03
  33#define MADERA_AIF_FORMAT			0x04
  34#define MADERA_AIF_RX_BCLK_RATE			0x06
  35#define MADERA_AIF_FRAME_CTRL_1			0x07
  36#define MADERA_AIF_FRAME_CTRL_2			0x08
  37#define MADERA_AIF_FRAME_CTRL_3			0x09
  38#define MADERA_AIF_FRAME_CTRL_4			0x0A
  39#define MADERA_AIF_FRAME_CTRL_5			0x0B
  40#define MADERA_AIF_FRAME_CTRL_6			0x0C
  41#define MADERA_AIF_FRAME_CTRL_7			0x0D
  42#define MADERA_AIF_FRAME_CTRL_8			0x0E
  43#define MADERA_AIF_FRAME_CTRL_9			0x0F
  44#define MADERA_AIF_FRAME_CTRL_10		0x10
  45#define MADERA_AIF_FRAME_CTRL_11		0x11
  46#define MADERA_AIF_FRAME_CTRL_12		0x12
  47#define MADERA_AIF_FRAME_CTRL_13		0x13
  48#define MADERA_AIF_FRAME_CTRL_14		0x14
  49#define MADERA_AIF_FRAME_CTRL_15		0x15
  50#define MADERA_AIF_FRAME_CTRL_16		0x16
  51#define MADERA_AIF_FRAME_CTRL_17		0x17
  52#define MADERA_AIF_FRAME_CTRL_18		0x18
  53#define MADERA_AIF_TX_ENABLES			0x19
  54#define MADERA_AIF_RX_ENABLES			0x1A
  55#define MADERA_AIF_FORCE_WRITE			0x1B
  56
  57#define MADERA_DSP_CONFIG_1_OFFS		0x00
  58#define MADERA_DSP_CONFIG_2_OFFS		0x02
  59
  60#define MADERA_DSP_CLK_SEL_MASK			0x70000
  61#define MADERA_DSP_CLK_SEL_SHIFT		16
  62
  63#define MADERA_DSP_RATE_MASK			0x7800
  64#define MADERA_DSP_RATE_SHIFT			11
  65
  66#define MADERA_SYSCLK_6MHZ			0
  67#define MADERA_SYSCLK_12MHZ			1
  68#define MADERA_SYSCLK_24MHZ			2
  69#define MADERA_SYSCLK_49MHZ			3
  70#define MADERA_SYSCLK_98MHZ			4
  71
  72#define MADERA_DSPCLK_9MHZ			0
  73#define MADERA_DSPCLK_18MHZ			1
  74#define MADERA_DSPCLK_36MHZ			2
  75#define MADERA_DSPCLK_73MHZ			3
  76#define MADERA_DSPCLK_147MHZ			4
  77
  78#define MADERA_FLL_VCO_CORNER			141900000
  79#define MADERA_FLL_MAX_FREF			13500000
  80#define MADERA_FLL_MAX_N			1023
  81#define MADERA_FLL_MIN_FOUT			90000000
  82#define MADERA_FLL_MAX_FOUT			100000000
  83#define MADERA_FLL_MAX_FRATIO			16
  84#define MADERA_FLL_MAX_REFDIV			8
  85#define MADERA_FLL_OUTDIV			3
  86#define MADERA_FLL_VCO_MULT			3
  87#define MADERA_FLLAO_MAX_FREF			12288000
  88#define MADERA_FLLAO_MIN_N			4
  89#define MADERA_FLLAO_MAX_N			1023
  90#define MADERA_FLLAO_MAX_FBDIV			254
  91#define MADERA_FLLHJ_INT_MAX_N			1023
  92#define MADERA_FLLHJ_INT_MIN_N			1
  93#define MADERA_FLLHJ_FRAC_MAX_N			255
  94#define MADERA_FLLHJ_FRAC_MIN_N			4
  95#define MADERA_FLLHJ_LOW_THRESH			192000
  96#define MADERA_FLLHJ_MID_THRESH			1152000
  97#define MADERA_FLLHJ_MAX_THRESH			13000000
  98#define MADERA_FLLHJ_LOW_GAINS			0x23f0
  99#define MADERA_FLLHJ_MID_GAINS			0x22f2
 100#define MADERA_FLLHJ_HIGH_GAINS			0x21f0
 101
 102#define MADERA_FLL_SYNCHRONISER_OFFS		0x10
 103#define CS47L35_FLL_SYNCHRONISER_OFFS		0xE
 104#define MADERA_FLL_CONTROL_1_OFFS		0x1
 105#define MADERA_FLL_CONTROL_2_OFFS		0x2
 106#define MADERA_FLL_CONTROL_3_OFFS		0x3
 107#define MADERA_FLL_CONTROL_4_OFFS		0x4
 108#define MADERA_FLL_CONTROL_5_OFFS		0x5
 109#define MADERA_FLL_CONTROL_6_OFFS		0x6
 110#define MADERA_FLL_GAIN_OFFS			0x8
 111#define MADERA_FLL_CONTROL_7_OFFS		0x9
 112#define MADERA_FLL_EFS_2_OFFS			0xA
 113#define MADERA_FLL_SYNCHRONISER_1_OFFS		0x1
 114#define MADERA_FLL_SYNCHRONISER_2_OFFS		0x2
 115#define MADERA_FLL_SYNCHRONISER_3_OFFS		0x3
 116#define MADERA_FLL_SYNCHRONISER_4_OFFS		0x4
 117#define MADERA_FLL_SYNCHRONISER_5_OFFS		0x5
 118#define MADERA_FLL_SYNCHRONISER_6_OFFS		0x6
 119#define MADERA_FLL_SYNCHRONISER_7_OFFS		0x7
 120#define MADERA_FLL_SPREAD_SPECTRUM_OFFS		0x9
 121#define MADERA_FLL_GPIO_CLOCK_OFFS		0xA
 122#define MADERA_FLL_CONTROL_10_OFFS		0xA
 123#define MADERA_FLL_CONTROL_11_OFFS		0xB
 124#define MADERA_FLL1_DIGITAL_TEST_1_OFFS		0xD
 125
 126#define MADERA_FLLAO_CONTROL_1_OFFS		0x1
 127#define MADERA_FLLAO_CONTROL_2_OFFS		0x2
 128#define MADERA_FLLAO_CONTROL_3_OFFS		0x3
 129#define MADERA_FLLAO_CONTROL_4_OFFS		0x4
 130#define MADERA_FLLAO_CONTROL_5_OFFS		0x5
 131#define MADERA_FLLAO_CONTROL_6_OFFS		0x6
 132#define MADERA_FLLAO_CONTROL_7_OFFS		0x8
 133#define MADERA_FLLAO_CONTROL_8_OFFS		0xA
 134#define MADERA_FLLAO_CONTROL_9_OFFS		0xB
 135#define MADERA_FLLAO_CONTROL_10_OFFS		0xC
 136#define MADERA_FLLAO_CONTROL_11_OFFS		0xD
 137
 138#define MADERA_FMT_DSP_MODE_A			0
 139#define MADERA_FMT_DSP_MODE_B			1
 140#define MADERA_FMT_I2S_MODE			2
 141#define MADERA_FMT_LEFT_JUSTIFIED_MODE		3
 142
 143#define madera_fll_err(_fll, fmt, ...) \
 144	dev_err(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
 145#define madera_fll_warn(_fll, fmt, ...) \
 146	dev_warn(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
 147#define madera_fll_dbg(_fll, fmt, ...) \
 148	dev_dbg(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
 149
 150#define madera_aif_err(_dai, fmt, ...) \
 151	dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
 152#define madera_aif_warn(_dai, fmt, ...) \
 153	dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
 154#define madera_aif_dbg(_dai, fmt, ...) \
 155	dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
 156
 157static const int madera_dsp_bus_error_irqs[MADERA_MAX_ADSP] = {
 158	MADERA_IRQ_DSP1_BUS_ERR,
 159	MADERA_IRQ_DSP2_BUS_ERR,
 160	MADERA_IRQ_DSP3_BUS_ERR,
 161	MADERA_IRQ_DSP4_BUS_ERR,
 162	MADERA_IRQ_DSP5_BUS_ERR,
 163	MADERA_IRQ_DSP6_BUS_ERR,
 164	MADERA_IRQ_DSP7_BUS_ERR,
 165};
 166
 167int madera_clk_ev(struct snd_soc_dapm_widget *w,
 168		  struct snd_kcontrol *kcontrol, int event)
 169{
 170	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 171	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 172	struct madera *madera = priv->madera;
 173	unsigned int val;
 174	int clk_idx;
 175	int ret;
 176
 177	ret = regmap_read(madera->regmap, w->reg, &val);
 178	if (ret) {
 179		dev_err(madera->dev, "Failed to check clock source: %d\n", ret);
 180		return ret;
 181	}
 182
 183	switch ((val & MADERA_SYSCLK_SRC_MASK) >> MADERA_SYSCLK_SRC_SHIFT) {
 184	case MADERA_CLK_SRC_MCLK1:
 185		clk_idx = MADERA_MCLK1;
 186		break;
 187	case MADERA_CLK_SRC_MCLK2:
 188		clk_idx = MADERA_MCLK2;
 189		break;
 190	case MADERA_CLK_SRC_MCLK3:
 191		clk_idx = MADERA_MCLK3;
 192		break;
 193	default:
 194		return 0;
 195	}
 196
 197	switch (event) {
 198	case SND_SOC_DAPM_PRE_PMU:
 199		return clk_prepare_enable(madera->mclk[clk_idx].clk);
 200	case SND_SOC_DAPM_POST_PMD:
 201		clk_disable_unprepare(madera->mclk[clk_idx].clk);
 202		return 0;
 203	default:
 204		return 0;
 205	}
 206}
 207EXPORT_SYMBOL_GPL(madera_clk_ev);
 208
 209static void madera_spin_sysclk(struct madera_priv *priv)
 210{
 211	struct madera *madera = priv->madera;
 212	unsigned int val;
 213	int ret, i;
 214
 215	/* Skip this if the chip is down */
 216	if (pm_runtime_suspended(madera->dev))
 217		return;
 218
 219	/*
 220	 * Just read a register a few times to ensure the internal
 221	 * oscillator sends out a few clocks.
 222	 */
 223	for (i = 0; i < 4; i++) {
 224		ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &val);
 225		if (ret)
 226			dev_err(madera->dev,
 227				"Failed to read sysclk spin %d: %d\n", i, ret);
 228	}
 229
 230	udelay(300);
 231}
 232
 233int madera_sysclk_ev(struct snd_soc_dapm_widget *w,
 234		     struct snd_kcontrol *kcontrol, int event)
 235{
 236	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 237	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 238
 239	switch (event) {
 240	case SND_SOC_DAPM_POST_PMU:
 241	case SND_SOC_DAPM_PRE_PMD:
 242		madera_spin_sysclk(priv);
 243		break;
 244	default:
 245		break;
 246	}
 247
 248	return madera_clk_ev(w, kcontrol, event);
 249}
 250EXPORT_SYMBOL_GPL(madera_sysclk_ev);
 251
 252static int madera_check_speaker_overheat(struct madera *madera,
 253					 bool *warn, bool *shutdown)
 254{
 255	unsigned int val;
 256	int ret;
 257
 258	ret = regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_15, &val);
 259	if (ret) {
 260		dev_err(madera->dev, "Failed to read thermal status: %d\n",
 261			ret);
 262		return ret;
 263	}
 264
 265	*warn = val & MADERA_SPK_OVERHEAT_WARN_STS1;
 266	*shutdown = val & MADERA_SPK_OVERHEAT_STS1;
 267
 268	return 0;
 269}
 270
 271int madera_spk_ev(struct snd_soc_dapm_widget *w,
 272		  struct snd_kcontrol *kcontrol, int event)
 273{
 274	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 275	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 276	struct madera *madera = priv->madera;
 277	bool warn, shutdown;
 278	int ret;
 279
 280	switch (event) {
 281	case SND_SOC_DAPM_POST_PMU:
 282		ret = madera_check_speaker_overheat(madera, &warn, &shutdown);
 283		if (ret)
 284			return ret;
 285
 286		if (shutdown) {
 287			dev_crit(madera->dev,
 288				 "Speaker not enabled due to temperature\n");
 289			return -EBUSY;
 290		}
 291
 292		regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
 293				   1 << w->shift, 1 << w->shift);
 294		break;
 295	case SND_SOC_DAPM_PRE_PMD:
 296		regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
 297				   1 << w->shift, 0);
 298		break;
 299	default:
 300		break;
 301	}
 302
 303	return 0;
 304}
 305EXPORT_SYMBOL_GPL(madera_spk_ev);
 306
 307static irqreturn_t madera_thermal_warn(int irq, void *data)
 308{
 309	struct madera *madera = data;
 310	bool warn, shutdown;
 311	int ret;
 312
 313	ret = madera_check_speaker_overheat(madera, &warn, &shutdown);
 314	if (ret || shutdown) { /* for safety attempt to shutdown on error */
 315		dev_crit(madera->dev, "Thermal shutdown\n");
 316		ret = regmap_update_bits(madera->regmap,
 317					 MADERA_OUTPUT_ENABLES_1,
 318					 MADERA_OUT4L_ENA |
 319					 MADERA_OUT4R_ENA, 0);
 320		if (ret != 0)
 321			dev_crit(madera->dev,
 322				 "Failed to disable speaker outputs: %d\n",
 323				 ret);
 324	} else if (warn) {
 325		dev_alert(madera->dev, "Thermal warning\n");
 326	} else {
 327		dev_info(madera->dev, "Spurious thermal warning\n");
 328		return IRQ_NONE;
 329	}
 330
 331	return IRQ_HANDLED;
 332}
 333
 334int madera_init_overheat(struct madera_priv *priv)
 335{
 336	struct madera *madera = priv->madera;
 337	struct device *dev = madera->dev;
 338	int ret;
 339
 340	ret = madera_request_irq(madera, MADERA_IRQ_SPK_OVERHEAT_WARN,
 341				 "Thermal warning", madera_thermal_warn,
 342				 madera);
 343	if (ret)
 344		dev_err(dev, "Failed to get thermal warning IRQ: %d\n", ret);
 345
 346	ret = madera_request_irq(madera, MADERA_IRQ_SPK_OVERHEAT,
 347				 "Thermal shutdown", madera_thermal_warn,
 348				 madera);
 349	if (ret)
 350		dev_err(dev, "Failed to get thermal shutdown IRQ: %d\n", ret);
 351
 352	return 0;
 353}
 354EXPORT_SYMBOL_GPL(madera_init_overheat);
 355
 356int madera_free_overheat(struct madera_priv *priv)
 357{
 358	struct madera *madera = priv->madera;
 359
 360	madera_free_irq(madera, MADERA_IRQ_SPK_OVERHEAT_WARN, madera);
 361	madera_free_irq(madera, MADERA_IRQ_SPK_OVERHEAT, madera);
 362
 363	return 0;
 364}
 365EXPORT_SYMBOL_GPL(madera_free_overheat);
 366
 367static int madera_get_variable_u32_array(struct device *dev,
 368					 const char *propname,
 369					 u32 *dest, int n_max,
 370					 int multiple)
 371{
 372	int n, ret;
 373
 374	n = device_property_count_u32(dev, propname);
 375	if (n < 0) {
 376		if (n == -EINVAL)
 377			return 0;	/* missing, ignore */
 378
 379		dev_warn(dev, "%s malformed (%d)\n", propname, n);
 380
 381		return n;
 382	} else if ((n % multiple) != 0) {
 383		dev_warn(dev, "%s not a multiple of %d entries\n",
 384			 propname, multiple);
 385
 386		return -EINVAL;
 387	}
 388
 389	if (n > n_max)
 390		n = n_max;
 391
 392	ret = device_property_read_u32_array(dev, propname, dest, n);
 393	if (ret < 0)
 394		return ret;
 395
 396	return n;
 397}
 398
 399static void madera_prop_get_inmode(struct madera_priv *priv)
 400{
 401	struct madera *madera = priv->madera;
 402	struct madera_codec_pdata *pdata = &madera->pdata.codec;
 403	u32 tmp[MADERA_MAX_INPUT * MADERA_MAX_MUXED_CHANNELS];
 404	int n, i, in_idx, ch_idx;
 405
 406	BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode) != MADERA_MAX_INPUT);
 407	BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode[0]) != MADERA_MAX_MUXED_CHANNELS);
 408
 409	n = madera_get_variable_u32_array(madera->dev, "cirrus,inmode",
 410					  tmp, ARRAY_SIZE(tmp),
 411					  MADERA_MAX_MUXED_CHANNELS);
 412	if (n < 0)
 413		return;
 414
 415	in_idx = 0;
 416	ch_idx = 0;
 417	for (i = 0; i < n; ++i) {
 418		pdata->inmode[in_idx][ch_idx] = tmp[i];
 419
 420		if (++ch_idx == MADERA_MAX_MUXED_CHANNELS) {
 421			ch_idx = 0;
 422			++in_idx;
 423		}
 424	}
 425}
 426
 427static void madera_prop_get_pdata(struct madera_priv *priv)
 428{
 429	struct madera *madera = priv->madera;
 430	struct madera_codec_pdata *pdata = &madera->pdata.codec;
 431	u32 out_mono[ARRAY_SIZE(pdata->out_mono)];
 432	int i, n;
 433
 434	madera_prop_get_inmode(priv);
 435
 436	n = madera_get_variable_u32_array(madera->dev, "cirrus,out-mono",
 437					  out_mono, ARRAY_SIZE(out_mono), 1);
 438	if (n > 0)
 439		for (i = 0; i < n; ++i)
 440			pdata->out_mono[i] = !!out_mono[i];
 441
 442	madera_get_variable_u32_array(madera->dev,
 443				      "cirrus,max-channels-clocked",
 444				      pdata->max_channels_clocked,
 445				      ARRAY_SIZE(pdata->max_channels_clocked),
 446				      1);
 447
 448	madera_get_variable_u32_array(madera->dev, "cirrus,pdm-fmt",
 449				      pdata->pdm_fmt,
 450				      ARRAY_SIZE(pdata->pdm_fmt), 1);
 451
 452	madera_get_variable_u32_array(madera->dev, "cirrus,pdm-mute",
 453				      pdata->pdm_mute,
 454				      ARRAY_SIZE(pdata->pdm_mute), 1);
 455
 456	madera_get_variable_u32_array(madera->dev, "cirrus,dmic-ref",
 457				      pdata->dmic_ref,
 458				      ARRAY_SIZE(pdata->dmic_ref), 1);
 459}
 460
 461int madera_core_init(struct madera_priv *priv)
 462{
 463	int i;
 464
 465	/* trap undersized array initializers */
 466	BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]);
 467	BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]);
 468
 469	if (!dev_get_platdata(priv->madera->dev))
 470		madera_prop_get_pdata(priv);
 471
 472	mutex_init(&priv->rate_lock);
 473
 474	for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++)
 475		priv->madera->out_clamp[i] = true;
 476
 477	return 0;
 478}
 479EXPORT_SYMBOL_GPL(madera_core_init);
 480
 481int madera_core_free(struct madera_priv *priv)
 482{
 483	mutex_destroy(&priv->rate_lock);
 484
 485	return 0;
 486}
 487EXPORT_SYMBOL_GPL(madera_core_free);
 488
 489static void madera_debug_dump_domain_groups(const struct madera_priv *priv)
 490{
 491	struct madera *madera = priv->madera;
 492	int i;
 493
 494	for (i = 0; i < ARRAY_SIZE(priv->domain_group_ref); ++i)
 495		dev_dbg(madera->dev, "domain_grp_ref[%d]=%d\n", i,
 496			priv->domain_group_ref[i]);
 497}
 498
 499int madera_domain_clk_ev(struct snd_soc_dapm_widget *w,
 500			 struct snd_kcontrol *kcontrol,
 501			 int event)
 502{
 503	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 504	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 505	int dom_grp = w->shift;
 506
 507	if (dom_grp >= ARRAY_SIZE(priv->domain_group_ref)) {
 508		WARN(true, "%s dom_grp exceeds array size\n", __func__);
 509		return -EINVAL;
 510	}
 511
 512	/*
 513	 * We can't rely on the DAPM mutex for locking because we need a lock
 514	 * that can safely be called in hw_params
 515	 */
 516	mutex_lock(&priv->rate_lock);
 517
 518	switch (event) {
 519	case SND_SOC_DAPM_PRE_PMU:
 520		dev_dbg(priv->madera->dev, "Inc ref on domain group %d\n",
 521			dom_grp);
 522		++priv->domain_group_ref[dom_grp];
 523		break;
 524	case SND_SOC_DAPM_POST_PMD:
 525		dev_dbg(priv->madera->dev, "Dec ref on domain group %d\n",
 526			dom_grp);
 527		--priv->domain_group_ref[dom_grp];
 528		break;
 529	default:
 530		break;
 531	}
 532
 533	madera_debug_dump_domain_groups(priv);
 534
 535	mutex_unlock(&priv->rate_lock);
 536
 537	return 0;
 538}
 539EXPORT_SYMBOL_GPL(madera_domain_clk_ev);
 540
 541int madera_out1_demux_put(struct snd_kcontrol *kcontrol,
 542			  struct snd_ctl_elem_value *ucontrol)
 543{
 544	struct snd_soc_component *component = snd_soc_dapm_kcontrol_to_component(kcontrol);
 545	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
 546	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 547	struct madera *madera = priv->madera;
 548	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 549	unsigned int ep_sel, mux, change;
 550	bool out_mono;
 551	int ret;
 552
 553	if (ucontrol->value.enumerated.item[0] > e->items - 1)
 554		return -EINVAL;
 555
 556	mux = ucontrol->value.enumerated.item[0];
 557
 558	snd_soc_dapm_mutex_lock(dapm);
 559
 560	ep_sel = mux << MADERA_EP_SEL_SHIFT;
 561
 562	change = snd_soc_component_test_bits(component, MADERA_OUTPUT_ENABLES_1,
 563					     MADERA_EP_SEL_MASK,
 564					     ep_sel);
 565	if (!change)
 566		goto end;
 567
 568	/* EP_SEL should not be modified while HP or EP driver is enabled */
 569	ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
 570				 MADERA_OUT1L_ENA | MADERA_OUT1R_ENA, 0);
 571	if (ret)
 572		dev_warn(madera->dev, "Failed to disable outputs: %d\n", ret);
 573
 574	usleep_range(2000, 3000); /* wait for wseq to complete */
 575
 576	/* change demux setting */
 577	ret = 0;
 578	if (madera->out_clamp[0])
 579		ret = regmap_update_bits(madera->regmap,
 580					 MADERA_OUTPUT_ENABLES_1,
 581					 MADERA_EP_SEL_MASK, ep_sel);
 582	if (ret) {
 583		dev_err(madera->dev, "Failed to set OUT1 demux: %d\n", ret);
 584	} else {
 585		/* apply correct setting for mono mode */
 586		if (!ep_sel && !madera->pdata.codec.out_mono[0])
 587			out_mono = false; /* stereo HP */
 588		else
 589			out_mono = true; /* EP or mono HP */
 590
 591		ret = madera_set_output_mode(component, 1, out_mono);
 592		if (ret)
 593			dev_warn(madera->dev,
 594				 "Failed to set output mode: %d\n", ret);
 595	}
 596
 597	/*
 598	 * if HPDET has disabled the clamp while switching to HPOUT
 599	 * OUT1 should remain disabled
 600	 */
 601	if (ep_sel ||
 602	    (madera->out_clamp[0] && !madera->out_shorted[0])) {
 603		ret = regmap_update_bits(madera->regmap,
 604					 MADERA_OUTPUT_ENABLES_1,
 605					 MADERA_OUT1L_ENA | MADERA_OUT1R_ENA,
 606					 madera->hp_ena);
 607		if (ret)
 608			dev_warn(madera->dev,
 609				 "Failed to restore earpiece outputs: %d\n",
 610				 ret);
 611		else if (madera->hp_ena)
 612			msleep(34); /* wait for enable wseq */
 613		else
 614			usleep_range(2000, 3000); /* wait for disable wseq */
 615	}
 616
 617end:
 618	snd_soc_dapm_mutex_unlock(dapm);
 619
 620	ret = snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
 621	if (ret < 0) {
 622		dev_err(madera->dev, "Failed to update demux power state: %d\n", ret);
 623		return ret;
 624	}
 625
 626	return change;
 627}
 628EXPORT_SYMBOL_GPL(madera_out1_demux_put);
 629
 630int madera_out1_demux_get(struct snd_kcontrol *kcontrol,
 631			  struct snd_ctl_elem_value *ucontrol)
 632{
 633	struct snd_soc_component *component = snd_soc_dapm_kcontrol_to_component(kcontrol);
 634	unsigned int val;
 635
 636	val = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1);
 637	val &= MADERA_EP_SEL_MASK;
 638	val >>= MADERA_EP_SEL_SHIFT;
 639	ucontrol->value.enumerated.item[0] = val;
 640
 641	return 0;
 642}
 643EXPORT_SYMBOL_GPL(madera_out1_demux_get);
 644
 645static int madera_inmux_put(struct snd_kcontrol *kcontrol,
 646			    struct snd_ctl_elem_value *ucontrol)
 647{
 648	struct snd_soc_component *component = snd_soc_dapm_kcontrol_to_component(kcontrol);
 649	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
 650	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 651	struct madera *madera = priv->madera;
 652	struct regmap *regmap = madera->regmap;
 653	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 654	unsigned int mux, val, mask;
 655	unsigned int inmode;
 656	bool changed;
 657	int ret;
 658
 659	mux = ucontrol->value.enumerated.item[0];
 660	if (mux > 1)
 661		return -EINVAL;
 662
 663	val = mux << e->shift_l;
 664	mask = (e->mask << e->shift_l) | MADERA_IN1L_SRC_SE_MASK;
 665
 666	switch (e->reg) {
 667	case MADERA_ADC_DIGITAL_VOLUME_1L:
 668		inmode = madera->pdata.codec.inmode[0][2 * mux];
 669		break;
 670	case MADERA_ADC_DIGITAL_VOLUME_1R:
 671		inmode = madera->pdata.codec.inmode[0][1 + (2 * mux)];
 672		break;
 673	case MADERA_ADC_DIGITAL_VOLUME_2L:
 674		inmode = madera->pdata.codec.inmode[1][2 * mux];
 675		break;
 676	case MADERA_ADC_DIGITAL_VOLUME_2R:
 677		inmode = madera->pdata.codec.inmode[1][1 + (2 * mux)];
 678		break;
 679	default:
 680		return -EINVAL;
 681	}
 682
 683	if (inmode & MADERA_INMODE_SE)
 684		val |= 1 << MADERA_IN1L_SRC_SE_SHIFT;
 685
 686	dev_dbg(madera->dev, "mux=%u reg=0x%x inmode=0x%x mask=0x%x val=0x%x\n",
 687		mux, e->reg, inmode, mask, val);
 688
 689	ret = regmap_update_bits_check(regmap, e->reg, mask, val, &changed);
 690	if (ret < 0)
 691		return ret;
 692
 693	if (changed)
 694		return snd_soc_dapm_mux_update_power(dapm, kcontrol,
 695						     mux, e, NULL);
 696	else
 697		return 0;
 698}
 699
 700static const char * const madera_inmux_texts[] = {
 701	"A",
 702	"B",
 703};
 704
 705static SOC_ENUM_SINGLE_DECL(madera_in1muxl_enum,
 706			    MADERA_ADC_DIGITAL_VOLUME_1L,
 707			    MADERA_IN1L_SRC_SHIFT,
 708			    madera_inmux_texts);
 709
 710static SOC_ENUM_SINGLE_DECL(madera_in1muxr_enum,
 711			    MADERA_ADC_DIGITAL_VOLUME_1R,
 712			    MADERA_IN1R_SRC_SHIFT,
 713			    madera_inmux_texts);
 714
 715static SOC_ENUM_SINGLE_DECL(madera_in2muxl_enum,
 716			    MADERA_ADC_DIGITAL_VOLUME_2L,
 717			    MADERA_IN2L_SRC_SHIFT,
 718			    madera_inmux_texts);
 719
 720static SOC_ENUM_SINGLE_DECL(madera_in2muxr_enum,
 721			    MADERA_ADC_DIGITAL_VOLUME_2R,
 722			    MADERA_IN2R_SRC_SHIFT,
 723			    madera_inmux_texts);
 724
 725const struct snd_kcontrol_new madera_inmux[] = {
 726	SOC_DAPM_ENUM_EXT("IN1L Mux", madera_in1muxl_enum,
 727			  snd_soc_dapm_get_enum_double, madera_inmux_put),
 728	SOC_DAPM_ENUM_EXT("IN1R Mux", madera_in1muxr_enum,
 729			  snd_soc_dapm_get_enum_double, madera_inmux_put),
 730	SOC_DAPM_ENUM_EXT("IN2L Mux", madera_in2muxl_enum,
 731			  snd_soc_dapm_get_enum_double, madera_inmux_put),
 732	SOC_DAPM_ENUM_EXT("IN2R Mux", madera_in2muxr_enum,
 733			  snd_soc_dapm_get_enum_double, madera_inmux_put),
 734};
 735EXPORT_SYMBOL_GPL(madera_inmux);
 736
 737static const char * const madera_dmode_texts[] = {
 738	"Analog",
 739	"Digital",
 740};
 741
 742static SOC_ENUM_SINGLE_DECL(madera_in1dmode_enum,
 743			    MADERA_IN1L_CONTROL,
 744			    MADERA_IN1_MODE_SHIFT,
 745			    madera_dmode_texts);
 746
 747static SOC_ENUM_SINGLE_DECL(madera_in2dmode_enum,
 748			    MADERA_IN2L_CONTROL,
 749			    MADERA_IN2_MODE_SHIFT,
 750			    madera_dmode_texts);
 751
 752static SOC_ENUM_SINGLE_DECL(madera_in3dmode_enum,
 753			    MADERA_IN3L_CONTROL,
 754			    MADERA_IN3_MODE_SHIFT,
 755			    madera_dmode_texts);
 756
 757const struct snd_kcontrol_new madera_inmode[] = {
 758	SOC_DAPM_ENUM("IN1 Mode", madera_in1dmode_enum),
 759	SOC_DAPM_ENUM("IN2 Mode", madera_in2dmode_enum),
 760	SOC_DAPM_ENUM("IN3 Mode", madera_in3dmode_enum),
 761};
 762EXPORT_SYMBOL_GPL(madera_inmode);
 763
 764static bool madera_can_change_grp_rate(const struct madera_priv *priv,
 765				       unsigned int reg)
 766{
 767	int count;
 768
 769	switch (reg) {
 770	case MADERA_FX_CTRL1:
 771		count = priv->domain_group_ref[MADERA_DOM_GRP_FX];
 772		break;
 773	case MADERA_ASRC1_RATE1:
 774	case MADERA_ASRC1_RATE2:
 775		count = priv->domain_group_ref[MADERA_DOM_GRP_ASRC1];
 776		break;
 777	case MADERA_ASRC2_RATE1:
 778	case MADERA_ASRC2_RATE2:
 779		count = priv->domain_group_ref[MADERA_DOM_GRP_ASRC2];
 780		break;
 781	case MADERA_ISRC_1_CTRL_1:
 782	case MADERA_ISRC_1_CTRL_2:
 783		count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC1];
 784		break;
 785	case MADERA_ISRC_2_CTRL_1:
 786	case MADERA_ISRC_2_CTRL_2:
 787		count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC2];
 788		break;
 789	case MADERA_ISRC_3_CTRL_1:
 790	case MADERA_ISRC_3_CTRL_2:
 791		count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC3];
 792		break;
 793	case MADERA_ISRC_4_CTRL_1:
 794	case MADERA_ISRC_4_CTRL_2:
 795		count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC4];
 796		break;
 797	case MADERA_OUTPUT_RATE_1:
 798		count = priv->domain_group_ref[MADERA_DOM_GRP_OUT];
 799		break;
 800	case MADERA_SPD1_TX_CONTROL:
 801		count = priv->domain_group_ref[MADERA_DOM_GRP_SPD];
 802		break;
 803	case MADERA_DSP1_CONFIG_1:
 804	case MADERA_DSP1_CONFIG_2:
 805		count = priv->domain_group_ref[MADERA_DOM_GRP_DSP1];
 806		break;
 807	case MADERA_DSP2_CONFIG_1:
 808	case MADERA_DSP2_CONFIG_2:
 809		count = priv->domain_group_ref[MADERA_DOM_GRP_DSP2];
 810		break;
 811	case MADERA_DSP3_CONFIG_1:
 812	case MADERA_DSP3_CONFIG_2:
 813		count = priv->domain_group_ref[MADERA_DOM_GRP_DSP3];
 814		break;
 815	case MADERA_DSP4_CONFIG_1:
 816	case MADERA_DSP4_CONFIG_2:
 817		count = priv->domain_group_ref[MADERA_DOM_GRP_DSP4];
 818		break;
 819	case MADERA_DSP5_CONFIG_1:
 820	case MADERA_DSP5_CONFIG_2:
 821		count = priv->domain_group_ref[MADERA_DOM_GRP_DSP5];
 822		break;
 823	case MADERA_DSP6_CONFIG_1:
 824	case MADERA_DSP6_CONFIG_2:
 825		count = priv->domain_group_ref[MADERA_DOM_GRP_DSP6];
 826		break;
 827	case MADERA_DSP7_CONFIG_1:
 828	case MADERA_DSP7_CONFIG_2:
 829		count = priv->domain_group_ref[MADERA_DOM_GRP_DSP7];
 830		break;
 831	case MADERA_AIF1_RATE_CTRL:
 832		count = priv->domain_group_ref[MADERA_DOM_GRP_AIF1];
 833		break;
 834	case MADERA_AIF2_RATE_CTRL:
 835		count = priv->domain_group_ref[MADERA_DOM_GRP_AIF2];
 836		break;
 837	case MADERA_AIF3_RATE_CTRL:
 838		count = priv->domain_group_ref[MADERA_DOM_GRP_AIF3];
 839		break;
 840	case MADERA_AIF4_RATE_CTRL:
 841		count = priv->domain_group_ref[MADERA_DOM_GRP_AIF4];
 842		break;
 843	case MADERA_SLIMBUS_RATES_1:
 844	case MADERA_SLIMBUS_RATES_2:
 845	case MADERA_SLIMBUS_RATES_3:
 846	case MADERA_SLIMBUS_RATES_4:
 847	case MADERA_SLIMBUS_RATES_5:
 848	case MADERA_SLIMBUS_RATES_6:
 849	case MADERA_SLIMBUS_RATES_7:
 850	case MADERA_SLIMBUS_RATES_8:
 851		count = priv->domain_group_ref[MADERA_DOM_GRP_SLIMBUS];
 852		break;
 853	case MADERA_PWM_DRIVE_1:
 854		count = priv->domain_group_ref[MADERA_DOM_GRP_PWM];
 855		break;
 856	default:
 857		return false;
 858	}
 859
 860	dev_dbg(priv->madera->dev, "Rate reg 0x%x group ref %d\n", reg, count);
 861
 862	if (count)
 863		return false;
 864	else
 865		return true;
 866}
 867
 868static int madera_adsp_rate_get(struct snd_kcontrol *kcontrol,
 869				struct snd_ctl_elem_value *ucontrol)
 870{
 871	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 872	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 873	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 874	unsigned int cached_rate;
 875	const int adsp_num = e->shift_l;
 876	int item;
 877
 878	mutex_lock(&priv->rate_lock);
 879	cached_rate = priv->adsp_rate_cache[adsp_num];
 880	mutex_unlock(&priv->rate_lock);
 881
 882	item = snd_soc_enum_val_to_item(e, cached_rate);
 883	ucontrol->value.enumerated.item[0] = item;
 884
 885	return 0;
 886}
 887
 888static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
 889				struct snd_ctl_elem_value *ucontrol)
 890{
 891	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 892	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 893	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 894	const int adsp_num = e->shift_l;
 895	const unsigned int item = ucontrol->value.enumerated.item[0];
 896	int ret = 0;
 897
 898	if (item >= e->items)
 899		return -EINVAL;
 900
 901	/*
 902	 * We don't directly write the rate register here but we want to
 903	 * maintain consistent behaviour that rate domains cannot be changed
 904	 * while in use since this is a hardware requirement
 905	 */
 906	mutex_lock(&priv->rate_lock);
 907
 908	if (!madera_can_change_grp_rate(priv, priv->adsp[adsp_num].cs_dsp.base)) {
 909		dev_warn(priv->madera->dev,
 910			 "Cannot change '%s' while in use by active audio paths\n",
 911			 kcontrol->id.name);
 912		ret = -EBUSY;
 913	} else if (priv->adsp_rate_cache[adsp_num] != e->values[item]) {
 914		/* Volatile register so defer until the codec is powered up */
 915		priv->adsp_rate_cache[adsp_num] = e->values[item];
 916		ret = 1;
 917	}
 918
 919	mutex_unlock(&priv->rate_lock);
 920
 921	return ret;
 922}
 923
 924static const struct soc_enum madera_adsp_rate_enum[] = {
 925	SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 0xf, MADERA_RATE_ENUM_SIZE,
 926			      madera_rate_text, madera_rate_val),
 927	SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 1, 0xf, MADERA_RATE_ENUM_SIZE,
 928			      madera_rate_text, madera_rate_val),
 929	SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 2, 0xf, MADERA_RATE_ENUM_SIZE,
 930			      madera_rate_text, madera_rate_val),
 931	SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 3, 0xf, MADERA_RATE_ENUM_SIZE,
 932			      madera_rate_text, madera_rate_val),
 933	SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 4, 0xf, MADERA_RATE_ENUM_SIZE,
 934			      madera_rate_text, madera_rate_val),
 935	SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 5, 0xf, MADERA_RATE_ENUM_SIZE,
 936			      madera_rate_text, madera_rate_val),
 937	SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 6, 0xf, MADERA_RATE_ENUM_SIZE,
 938			      madera_rate_text, madera_rate_val),
 939};
 940
 941const struct snd_kcontrol_new madera_adsp_rate_controls[] = {
 942	SOC_ENUM_EXT("DSP1 Rate", madera_adsp_rate_enum[0],
 943		     madera_adsp_rate_get, madera_adsp_rate_put),
 944	SOC_ENUM_EXT("DSP2 Rate", madera_adsp_rate_enum[1],
 945		     madera_adsp_rate_get, madera_adsp_rate_put),
 946	SOC_ENUM_EXT("DSP3 Rate", madera_adsp_rate_enum[2],
 947		     madera_adsp_rate_get, madera_adsp_rate_put),
 948	SOC_ENUM_EXT("DSP4 Rate", madera_adsp_rate_enum[3],
 949		     madera_adsp_rate_get, madera_adsp_rate_put),
 950	SOC_ENUM_EXT("DSP5 Rate", madera_adsp_rate_enum[4],
 951		     madera_adsp_rate_get, madera_adsp_rate_put),
 952	SOC_ENUM_EXT("DSP6 Rate", madera_adsp_rate_enum[5],
 953		     madera_adsp_rate_get, madera_adsp_rate_put),
 954	SOC_ENUM_EXT("DSP7 Rate", madera_adsp_rate_enum[6],
 955		     madera_adsp_rate_get, madera_adsp_rate_put),
 956};
 957EXPORT_SYMBOL_GPL(madera_adsp_rate_controls);
 958
 959static int madera_write_adsp_clk_setting(struct madera_priv *priv,
 960					 struct wm_adsp *dsp,
 961					 unsigned int freq)
 962{
 963	unsigned int val;
 964	unsigned int mask = MADERA_DSP_RATE_MASK;
 965	int ret;
 966
 967	val = priv->adsp_rate_cache[dsp->cs_dsp.num - 1] << MADERA_DSP_RATE_SHIFT;
 968
 969	switch (priv->madera->type) {
 970	case CS47L35:
 971	case CS47L85:
 972	case WM1840:
 973		/* use legacy frequency registers */
 974		mask |= MADERA_DSP_CLK_SEL_MASK;
 975		val |= (freq << MADERA_DSP_CLK_SEL_SHIFT);
 976		break;
 977	default:
 978		/* Configure exact dsp frequency */
 979		dev_dbg(priv->madera->dev, "Set DSP frequency to 0x%x\n", freq);
 980
 981		ret = regmap_write(dsp->cs_dsp.regmap,
 982				   dsp->cs_dsp.base + MADERA_DSP_CONFIG_2_OFFS, freq);
 983		if (ret)
 984			goto err;
 985		break;
 986	}
 987
 988	ret = regmap_update_bits(dsp->cs_dsp.regmap,
 989				 dsp->cs_dsp.base + MADERA_DSP_CONFIG_1_OFFS,
 990				 mask, val);
 991	if (ret)
 992		goto err;
 993
 994	dev_dbg(priv->madera->dev, "Set DSP clocking to 0x%x\n", val);
 995
 996	return 0;
 997
 998err:
 999	dev_err(dsp->cs_dsp.dev, "Failed to set DSP%d clock: %d\n", dsp->cs_dsp.num, ret);
1000
1001	return ret;
1002}
1003
1004int madera_set_adsp_clk(struct madera_priv *priv, int dsp_num,
1005			unsigned int freq)
1006{
1007	struct wm_adsp *dsp = &priv->adsp[dsp_num];
1008	struct madera *madera = priv->madera;
1009	unsigned int cur, new;
1010	int ret;
1011
1012	/*
1013	 * This is called at a higher DAPM priority than the mux widgets so
1014	 * the muxes are still off at this point and it's safe to change
1015	 * the rate domain control.
1016	 * Also called at a lower DAPM priority than the domain group widgets
1017	 * so locking the reads of adsp_rate_cache is not necessary as we know
1018	 * changes are locked out by the domain_group_ref reference count.
1019	 */
1020
1021	ret = regmap_read(dsp->cs_dsp.regmap,  dsp->cs_dsp.base, &cur);
1022	if (ret) {
1023		dev_err(madera->dev,
1024			"Failed to read current DSP rate: %d\n", ret);
1025		return ret;
1026	}
1027
1028	cur &= MADERA_DSP_RATE_MASK;
1029
1030	new = priv->adsp_rate_cache[dsp->cs_dsp.num - 1] << MADERA_DSP_RATE_SHIFT;
1031
1032	if (new == cur) {
1033		dev_dbg(madera->dev, "DSP rate not changed\n");
1034		return madera_write_adsp_clk_setting(priv, dsp, freq);
1035	} else {
1036		dev_dbg(madera->dev, "DSP rate changed\n");
1037
1038		/* The write must be guarded by a number of SYSCLK cycles */
1039		madera_spin_sysclk(priv);
1040		ret = madera_write_adsp_clk_setting(priv, dsp, freq);
1041		madera_spin_sysclk(priv);
1042		return ret;
1043	}
1044}
1045EXPORT_SYMBOL_GPL(madera_set_adsp_clk);
1046
1047int madera_rate_put(struct snd_kcontrol *kcontrol,
1048		    struct snd_ctl_elem_value *ucontrol)
1049{
1050	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
1051	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
1052	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1053	unsigned int item = ucontrol->value.enumerated.item[0];
1054	unsigned int val;
1055	int ret;
1056
1057	if (item >= e->items)
1058		return -EINVAL;
1059
1060	/*
1061	 * Prevent the domain powering up while we're checking whether it's
1062	 * safe to change rate domain
1063	 */
1064	mutex_lock(&priv->rate_lock);
1065
1066	val = snd_soc_component_read(component, e->reg);
1067	val >>= e->shift_l;
1068	val &= e->mask;
1069	if (snd_soc_enum_item_to_val(e, item) == val) {
1070		ret = 0;
1071		goto out;
1072	}
1073
1074	if (!madera_can_change_grp_rate(priv, e->reg)) {
1075		dev_warn(priv->madera->dev,
1076			 "Cannot change '%s' while in use by active audio paths\n",
1077			 kcontrol->id.name);
1078		ret = -EBUSY;
1079	} else {
1080		/* The write must be guarded by a number of SYSCLK cycles */
1081		madera_spin_sysclk(priv);
1082		ret = snd_soc_put_enum_double(kcontrol, ucontrol);
1083		madera_spin_sysclk(priv);
1084	}
1085out:
1086	mutex_unlock(&priv->rate_lock);
1087
1088	return ret;
1089}
1090EXPORT_SYMBOL_GPL(madera_rate_put);
1091
1092static void madera_configure_input_mode(struct madera *madera)
1093{
1094	unsigned int dig_mode, ana_mode_l, ana_mode_r;
1095	int max_analogue_inputs, max_dmic_sup, i;
1096
1097	switch (madera->type) {
1098	case CS47L15:
1099		max_analogue_inputs = 1;
1100		max_dmic_sup = 2;
1101		break;
1102	case CS47L35:
1103		max_analogue_inputs = 2;
1104		max_dmic_sup = 2;
1105		break;
1106	case CS47L85:
1107	case WM1840:
1108		max_analogue_inputs = 3;
1109		max_dmic_sup = 3;
1110		break;
1111	case CS47L90:
1112	case CS47L91:
1113		max_analogue_inputs = 2;
1114		max_dmic_sup = 2;
1115		break;
1116	default:
1117		max_analogue_inputs = 2;
1118		max_dmic_sup = 4;
1119		break;
1120	}
1121
1122	/*
1123	 * Initialize input modes from the A settings. For muxed inputs the
1124	 * B settings will be applied if the mux is changed
1125	 */
1126	for (i = 0; i < max_dmic_sup; i++) {
1127		dev_dbg(madera->dev, "IN%d mode %u:%u:%u:%u\n", i + 1,
1128			madera->pdata.codec.inmode[i][0],
1129			madera->pdata.codec.inmode[i][1],
1130			madera->pdata.codec.inmode[i][2],
1131			madera->pdata.codec.inmode[i][3]);
1132
1133		dig_mode = madera->pdata.codec.dmic_ref[i] <<
1134			   MADERA_IN1_DMIC_SUP_SHIFT;
1135
1136		switch (madera->pdata.codec.inmode[i][0]) {
1137		case MADERA_INMODE_DIFF:
1138			ana_mode_l = 0;
1139			break;
1140		case MADERA_INMODE_SE:
1141			ana_mode_l = 1 << MADERA_IN1L_SRC_SE_SHIFT;
1142			break;
1143		default:
1144			dev_warn(madera->dev,
1145				 "IN%dAL Illegal inmode %u ignored\n",
1146				 i + 1, madera->pdata.codec.inmode[i][0]);
1147			continue;
1148		}
1149
1150		switch (madera->pdata.codec.inmode[i][1]) {
1151		case MADERA_INMODE_DIFF:
1152			ana_mode_r = 0;
1153			break;
1154		case MADERA_INMODE_SE:
1155			ana_mode_r = 1 << MADERA_IN1R_SRC_SE_SHIFT;
1156			break;
1157		default:
1158			dev_warn(madera->dev,
1159				 "IN%dAR Illegal inmode %u ignored\n",
1160				 i + 1, madera->pdata.codec.inmode[i][1]);
1161			continue;
1162		}
1163
1164		dev_dbg(madera->dev,
1165			"IN%dA DMIC mode=0x%x Analogue mode=0x%x,0x%x\n",
1166			i + 1, dig_mode, ana_mode_l, ana_mode_r);
1167
1168		regmap_update_bits(madera->regmap,
1169				   MADERA_IN1L_CONTROL + (i * 8),
1170				   MADERA_IN1_DMIC_SUP_MASK, dig_mode);
1171
1172		if (i >= max_analogue_inputs)
1173			continue;
1174
1175		regmap_update_bits(madera->regmap,
1176				   MADERA_ADC_DIGITAL_VOLUME_1L + (i * 8),
1177				   MADERA_IN1L_SRC_SE_MASK, ana_mode_l);
1178
1179		regmap_update_bits(madera->regmap,
1180				   MADERA_ADC_DIGITAL_VOLUME_1R + (i * 8),
1181				   MADERA_IN1R_SRC_SE_MASK, ana_mode_r);
1182	}
1183}
1184
1185int madera_init_inputs(struct snd_soc_component *component)
1186{
1187	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
1188	struct madera *madera = priv->madera;
1189
1190	madera_configure_input_mode(madera);
1191
1192	return 0;
1193}
1194EXPORT_SYMBOL_GPL(madera_init_inputs);
1195
1196static const struct snd_soc_dapm_route madera_mono_routes[] = {
1197	{ "OUT1R", NULL, "OUT1L" },
1198	{ "OUT2R", NULL, "OUT2L" },
1199	{ "OUT3R", NULL, "OUT3L" },
1200	{ "OUT4R", NULL, "OUT4L" },
1201	{ "OUT5R", NULL, "OUT5L" },
1202	{ "OUT6R", NULL, "OUT6L" },
1203};
1204
1205int madera_init_outputs(struct snd_soc_component *component,
1206			const struct snd_soc_dapm_route *routes,
1207			int n_mono_routes, int n_real)
1208{
1209	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
1210	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
1211	struct madera *madera = priv->madera;
1212	const struct madera_codec_pdata *pdata = &madera->pdata.codec;
1213	unsigned int val;
1214	int i;
1215
1216	if (n_mono_routes > MADERA_MAX_OUTPUT) {
1217		dev_warn(madera->dev,
1218			 "Requested %d mono outputs, using maximum allowed %d\n",
1219			 n_mono_routes, MADERA_MAX_OUTPUT);
1220		n_mono_routes = MADERA_MAX_OUTPUT;
1221	}
1222
1223	if (!routes)
1224		routes = madera_mono_routes;
1225
1226	for (i = 0; i < n_mono_routes; i++) {
1227		/* Default is 0 so noop with defaults */
1228		if (pdata->out_mono[i]) {
1229			val = MADERA_OUT1_MONO;
1230			snd_soc_dapm_add_routes(dapm, &routes[i], 1);
1231		} else {
1232			val = 0;
1233		}
1234
1235		if (i >= n_real)
1236			continue;
1237
1238		regmap_update_bits(madera->regmap,
1239				   MADERA_OUTPUT_PATH_CONFIG_1L + (i * 8),
1240				   MADERA_OUT1_MONO, val);
1241
1242		dev_dbg(madera->dev, "OUT%d mono=0x%x\n", i + 1, val);
1243	}
1244
1245	for (i = 0; i < MADERA_MAX_PDM_SPK; i++) {
1246		dev_dbg(madera->dev, "PDM%d fmt=0x%x mute=0x%x\n", i + 1,
1247			pdata->pdm_fmt[i], pdata->pdm_mute[i]);
1248
1249		if (pdata->pdm_mute[i])
1250			regmap_update_bits(madera->regmap,
1251					   MADERA_PDM_SPK1_CTRL_1 + (i * 2),
1252					   MADERA_SPK1_MUTE_ENDIAN_MASK |
1253					   MADERA_SPK1_MUTE_SEQ1_MASK,
1254					   pdata->pdm_mute[i]);
1255
1256		if (pdata->pdm_fmt[i])
1257			regmap_update_bits(madera->regmap,
1258					   MADERA_PDM_SPK1_CTRL_2 + (i * 2),
1259					   MADERA_SPK1_FMT_MASK,
1260					   pdata->pdm_fmt[i]);
1261	}
1262
1263	return 0;
1264}
1265EXPORT_SYMBOL_GPL(madera_init_outputs);
1266
1267int madera_init_bus_error_irq(struct madera_priv *priv, int dsp_num,
1268			      irq_handler_t handler)
1269{
1270	struct madera *madera = priv->madera;
1271	int ret;
1272
1273	ret = madera_request_irq(madera,
1274				 madera_dsp_bus_error_irqs[dsp_num],
1275				 "ADSP2 bus error",
1276				 handler,
1277				 &priv->adsp[dsp_num]);
1278	if (ret)
1279		dev_err(madera->dev,
1280			"Failed to request DSP Lock region IRQ: %d\n", ret);
1281
1282	return ret;
1283}
1284EXPORT_SYMBOL_GPL(madera_init_bus_error_irq);
1285
1286void madera_free_bus_error_irq(struct madera_priv *priv, int dsp_num)
1287{
1288	struct madera *madera = priv->madera;
1289
1290	madera_free_irq(madera,
1291			madera_dsp_bus_error_irqs[dsp_num],
1292			&priv->adsp[dsp_num]);
1293}
1294EXPORT_SYMBOL_GPL(madera_free_bus_error_irq);
1295
1296const char * const madera_mixer_texts[] = {
1297	"None",
1298	"Tone Generator 1",
1299	"Tone Generator 2",
1300	"Haptics",
1301	"AEC1",
1302	"AEC2",
1303	"Mic Mute Mixer",
1304	"Noise Generator",
1305	"IN1L",
1306	"IN1R",
1307	"IN2L",
1308	"IN2R",
1309	"IN3L",
1310	"IN3R",
1311	"IN4L",
1312	"IN4R",
1313	"IN5L",
1314	"IN5R",
1315	"IN6L",
1316	"IN6R",
1317	"AIF1RX1",
1318	"AIF1RX2",
1319	"AIF1RX3",
1320	"AIF1RX4",
1321	"AIF1RX5",
1322	"AIF1RX6",
1323	"AIF1RX7",
1324	"AIF1RX8",
1325	"AIF2RX1",
1326	"AIF2RX2",
1327	"AIF2RX3",
1328	"AIF2RX4",
1329	"AIF2RX5",
1330	"AIF2RX6",
1331	"AIF2RX7",
1332	"AIF2RX8",
1333	"AIF3RX1",
1334	"AIF3RX2",
1335	"AIF3RX3",
1336	"AIF3RX4",
1337	"AIF4RX1",
1338	"AIF4RX2",
1339	"SLIMRX1",
1340	"SLIMRX2",
1341	"SLIMRX3",
1342	"SLIMRX4",
1343	"SLIMRX5",
1344	"SLIMRX6",
1345	"SLIMRX7",
1346	"SLIMRX8",
1347	"EQ1",
1348	"EQ2",
1349	"EQ3",
1350	"EQ4",
1351	"DRC1L",
1352	"DRC1R",
1353	"DRC2L",
1354	"DRC2R",
1355	"LHPF1",
1356	"LHPF2",
1357	"LHPF3",
1358	"LHPF4",
1359	"DSP1.1",
1360	"DSP1.2",
1361	"DSP1.3",
1362	"DSP1.4",
1363	"DSP1.5",
1364	"DSP1.6",
1365	"DSP2.1",
1366	"DSP2.2",
1367	"DSP2.3",
1368	"DSP2.4",
1369	"DSP2.5",
1370	"DSP2.6",
1371	"DSP3.1",
1372	"DSP3.2",
1373	"DSP3.3",
1374	"DSP3.4",
1375	"DSP3.5",
1376	"DSP3.6",
1377	"DSP4.1",
1378	"DSP4.2",
1379	"DSP4.3",
1380	"DSP4.4",
1381	"DSP4.5",
1382	"DSP4.6",
1383	"DSP5.1",
1384	"DSP5.2",
1385	"DSP5.3",
1386	"DSP5.4",
1387	"DSP5.5",
1388	"DSP5.6",
1389	"DSP6.1",
1390	"DSP6.2",
1391	"DSP6.3",
1392	"DSP6.4",
1393	"DSP6.5",
1394	"DSP6.6",
1395	"DSP7.1",
1396	"DSP7.2",
1397	"DSP7.3",
1398	"DSP7.4",
1399	"DSP7.5",
1400	"DSP7.6",
1401	"ASRC1IN1L",
1402	"ASRC1IN1R",
1403	"ASRC1IN2L",
1404	"ASRC1IN2R",
1405	"ASRC2IN1L",
1406	"ASRC2IN1R",
1407	"ASRC2IN2L",
1408	"ASRC2IN2R",
1409	"ISRC1INT1",
1410	"ISRC1INT2",
1411	"ISRC1INT3",
1412	"ISRC1INT4",
1413	"ISRC1DEC1",
1414	"ISRC1DEC2",
1415	"ISRC1DEC3",
1416	"ISRC1DEC4",
1417	"ISRC2INT1",
1418	"ISRC2INT2",
1419	"ISRC2INT3",
1420	"ISRC2INT4",
1421	"ISRC2DEC1",
1422	"ISRC2DEC2",
1423	"ISRC2DEC3",
1424	"ISRC2DEC4",
1425	"ISRC3INT1",
1426	"ISRC3INT2",
1427	"ISRC3INT3",
1428	"ISRC3INT4",
1429	"ISRC3DEC1",
1430	"ISRC3DEC2",
1431	"ISRC3DEC3",
1432	"ISRC3DEC4",
1433	"ISRC4INT1",
1434	"ISRC4INT2",
1435	"ISRC4DEC1",
1436	"ISRC4DEC2",
1437	"DFC1",
1438	"DFC2",
1439	"DFC3",
1440	"DFC4",
1441	"DFC5",
1442	"DFC6",
1443	"DFC7",
1444	"DFC8",
1445};
1446EXPORT_SYMBOL_GPL(madera_mixer_texts);
1447
1448const unsigned int madera_mixer_values[] = {
1449	0x00,	/* None */
1450	0x04,	/* Tone Generator 1 */
1451	0x05,	/* Tone Generator 2 */
1452	0x06,	/* Haptics */
1453	0x08,	/* AEC */
1454	0x09,	/* AEC2 */
1455	0x0c,	/* Noise mixer */
1456	0x0d,	/* Comfort noise */
1457	0x10,	/* IN1L */
1458	0x11,
1459	0x12,
1460	0x13,
1461	0x14,
1462	0x15,
1463	0x16,
1464	0x17,
1465	0x18,
1466	0x19,
1467	0x1A,
1468	0x1B,
1469	0x20,	/* AIF1RX1 */
1470	0x21,
1471	0x22,
1472	0x23,
1473	0x24,
1474	0x25,
1475	0x26,
1476	0x27,
1477	0x28,	/* AIF2RX1 */
1478	0x29,
1479	0x2a,
1480	0x2b,
1481	0x2c,
1482	0x2d,
1483	0x2e,
1484	0x2f,
1485	0x30,	/* AIF3RX1 */
1486	0x31,
1487	0x32,
1488	0x33,
1489	0x34,	/* AIF4RX1 */
1490	0x35,
1491	0x38,	/* SLIMRX1 */
1492	0x39,
1493	0x3a,
1494	0x3b,
1495	0x3c,
1496	0x3d,
1497	0x3e,
1498	0x3f,
1499	0x50,	/* EQ1 */
1500	0x51,
1501	0x52,
1502	0x53,
1503	0x58,	/* DRC1L */
1504	0x59,
1505	0x5a,
1506	0x5b,
1507	0x60,	/* LHPF1 */
1508	0x61,
1509	0x62,
1510	0x63,
1511	0x68,	/* DSP1.1 */
1512	0x69,
1513	0x6a,
1514	0x6b,
1515	0x6c,
1516	0x6d,
1517	0x70,	/* DSP2.1 */
1518	0x71,
1519	0x72,
1520	0x73,
1521	0x74,
1522	0x75,
1523	0x78,	/* DSP3.1 */
1524	0x79,
1525	0x7a,
1526	0x7b,
1527	0x7c,
1528	0x7d,
1529	0x80,	/* DSP4.1 */
1530	0x81,
1531	0x82,
1532	0x83,
1533	0x84,
1534	0x85,
1535	0x88,	/* DSP5.1 */
1536	0x89,
1537	0x8a,
1538	0x8b,
1539	0x8c,
1540	0x8d,
1541	0xc0,	/* DSP6.1 */
1542	0xc1,
1543	0xc2,
1544	0xc3,
1545	0xc4,
1546	0xc5,
1547	0xc8,	/* DSP7.1 */
1548	0xc9,
1549	0xca,
1550	0xcb,
1551	0xcc,
1552	0xcd,
1553	0x90,	/* ASRC1IN1L */
1554	0x91,
1555	0x92,
1556	0x93,
1557	0x94,	/* ASRC2IN1L */
1558	0x95,
1559	0x96,
1560	0x97,
1561	0xa0,	/* ISRC1INT1 */
1562	0xa1,
1563	0xa2,
1564	0xa3,
1565	0xa4,	/* ISRC1DEC1 */
1566	0xa5,
1567	0xa6,
1568	0xa7,
1569	0xa8,	/* ISRC2DEC1 */
1570	0xa9,
1571	0xaa,
1572	0xab,
1573	0xac,	/* ISRC2INT1 */
1574	0xad,
1575	0xae,
1576	0xaf,
1577	0xb0,	/* ISRC3DEC1 */
1578	0xb1,
1579	0xb2,
1580	0xb3,
1581	0xb4,	/* ISRC3INT1 */
1582	0xb5,
1583	0xb6,
1584	0xb7,
1585	0xb8,	/* ISRC4INT1 */
1586	0xb9,
1587	0xbc,	/* ISRC4DEC1 */
1588	0xbd,
1589	0xf8,	/* DFC1 */
1590	0xf9,
1591	0xfa,
1592	0xfb,
1593	0xfc,
1594	0xfd,
1595	0xfe,
1596	0xff,	/* DFC8 */
1597};
1598EXPORT_SYMBOL_GPL(madera_mixer_values);
1599
1600const DECLARE_TLV_DB_SCALE(madera_ana_tlv, 0, 100, 0);
1601EXPORT_SYMBOL_GPL(madera_ana_tlv);
1602
1603const DECLARE_TLV_DB_SCALE(madera_eq_tlv, -1200, 100, 0);
1604EXPORT_SYMBOL_GPL(madera_eq_tlv);
1605
1606const DECLARE_TLV_DB_SCALE(madera_digital_tlv, -6400, 50, 0);
1607EXPORT_SYMBOL_GPL(madera_digital_tlv);
1608
1609const DECLARE_TLV_DB_SCALE(madera_noise_tlv, -13200, 600, 0);
1610EXPORT_SYMBOL_GPL(madera_noise_tlv);
1611
1612const DECLARE_TLV_DB_SCALE(madera_ng_tlv, -12000, 600, 0);
1613EXPORT_SYMBOL_GPL(madera_ng_tlv);
1614
1615const DECLARE_TLV_DB_SCALE(madera_mixer_tlv, -3200, 100, 0);
1616EXPORT_SYMBOL_GPL(madera_mixer_tlv);
1617
1618const char * const madera_rate_text[MADERA_RATE_ENUM_SIZE] = {
1619	"SYNCCLK rate 1", "SYNCCLK rate 2", "SYNCCLK rate 3",
1620	"ASYNCCLK rate 1", "ASYNCCLK rate 2",
1621};
1622EXPORT_SYMBOL_GPL(madera_rate_text);
1623
1624const unsigned int madera_rate_val[MADERA_RATE_ENUM_SIZE] = {
1625	0x0, 0x1, 0x2, 0x8, 0x9,
1626};
1627EXPORT_SYMBOL_GPL(madera_rate_val);
1628
1629static const char * const madera_dfc_width_text[MADERA_DFC_WIDTH_ENUM_SIZE] = {
1630	"8 bit", "16 bit", "20 bit", "24 bit", "32 bit",
1631};
1632
1633static const unsigned int madera_dfc_width_val[MADERA_DFC_WIDTH_ENUM_SIZE] = {
1634	7, 15, 19, 23, 31,
1635};
1636
1637static const char * const madera_dfc_type_text[MADERA_DFC_TYPE_ENUM_SIZE] = {
1638	"Fixed", "Unsigned Fixed", "Single Precision Floating",
1639	"Half Precision Floating", "Arm Alternative Floating",
1640};
1641
1642static const unsigned int madera_dfc_type_val[MADERA_DFC_TYPE_ENUM_SIZE] = {
1643	0, 1, 2, 4, 5,
1644};
1645
1646const struct soc_enum madera_dfc_width[] = {
1647	SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_RX,
1648			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1649			      MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1650			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1651			      ARRAY_SIZE(madera_dfc_width_text),
1652			      madera_dfc_width_text,
1653			      madera_dfc_width_val),
1654	SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_TX,
1655			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1656			      MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1657			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1658			      ARRAY_SIZE(madera_dfc_width_text),
1659			      madera_dfc_width_text,
1660			      madera_dfc_width_val),
1661	SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_RX,
1662			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1663			      MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1664			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1665			      ARRAY_SIZE(madera_dfc_width_text),
1666			      madera_dfc_width_text,
1667			      madera_dfc_width_val),
1668	SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_TX,
1669			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1670			      MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1671			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1672			      ARRAY_SIZE(madera_dfc_width_text),
1673			      madera_dfc_width_text,
1674			      madera_dfc_width_val),
1675	SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_RX,
1676			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1677			      MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1678			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1679			      ARRAY_SIZE(madera_dfc_width_text),
1680			      madera_dfc_width_text,
1681			      madera_dfc_width_val),
1682	SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_TX,
1683			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1684			      MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1685			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1686			      ARRAY_SIZE(madera_dfc_width_text),
1687			      madera_dfc_width_text,
1688			      madera_dfc_width_val),
1689	SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_RX,
1690			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1691			      MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1692			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1693			      ARRAY_SIZE(madera_dfc_width_text),
1694			      madera_dfc_width_text,
1695			      madera_dfc_width_val),
1696	SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_TX,
1697			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1698			      MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1699			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1700			      ARRAY_SIZE(madera_dfc_width_text),
1701			      madera_dfc_width_text,
1702			      madera_dfc_width_val),
1703	SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_RX,
1704			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1705			      MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1706			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1707			      ARRAY_SIZE(madera_dfc_width_text),
1708			      madera_dfc_width_text,
1709			      madera_dfc_width_val),
1710	SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_TX,
1711			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1712			      MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1713			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1714			      ARRAY_SIZE(madera_dfc_width_text),
1715			      madera_dfc_width_text,
1716			      madera_dfc_width_val),
1717	SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_RX,
1718			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1719			      MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1720			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1721			      ARRAY_SIZE(madera_dfc_width_text),
1722			      madera_dfc_width_text,
1723			      madera_dfc_width_val),
1724	SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_TX,
1725			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1726			      MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1727			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1728			      ARRAY_SIZE(madera_dfc_width_text),
1729			      madera_dfc_width_text,
1730			      madera_dfc_width_val),
1731	SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_RX,
1732			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1733			      MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1734			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1735			      ARRAY_SIZE(madera_dfc_width_text),
1736			      madera_dfc_width_text,
1737			      madera_dfc_width_val),
1738	SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_TX,
1739			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1740			      MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1741			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1742			      ARRAY_SIZE(madera_dfc_width_text),
1743			      madera_dfc_width_text,
1744			      madera_dfc_width_val),
1745	SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_RX,
1746			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1747			      MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1748			      MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1749			      ARRAY_SIZE(madera_dfc_width_text),
1750			      madera_dfc_width_text,
1751			      madera_dfc_width_val),
1752	SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_TX,
1753			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1754			      MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1755			      MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1756			      ARRAY_SIZE(madera_dfc_width_text),
1757			      madera_dfc_width_text,
1758			      madera_dfc_width_val),
1759};
1760EXPORT_SYMBOL_GPL(madera_dfc_width);
1761
1762const struct soc_enum madera_dfc_type[] = {
1763	SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_RX,
1764			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1765			      MADERA_DFC1_RX_DATA_TYPE_MASK >>
1766			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1767			      ARRAY_SIZE(madera_dfc_type_text),
1768			      madera_dfc_type_text,
1769			      madera_dfc_type_val),
1770	SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_TX,
1771			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1772			      MADERA_DFC1_TX_DATA_TYPE_MASK >>
1773			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1774			      ARRAY_SIZE(madera_dfc_type_text),
1775			      madera_dfc_type_text,
1776			      madera_dfc_type_val),
1777	SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_RX,
1778			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1779			      MADERA_DFC1_RX_DATA_TYPE_MASK >>
1780			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1781			      ARRAY_SIZE(madera_dfc_type_text),
1782			      madera_dfc_type_text,
1783			      madera_dfc_type_val),
1784	SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_TX,
1785			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1786			      MADERA_DFC1_TX_DATA_TYPE_MASK >>
1787			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1788			      ARRAY_SIZE(madera_dfc_type_text),
1789			      madera_dfc_type_text,
1790			      madera_dfc_type_val),
1791	SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_RX,
1792			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1793			      MADERA_DFC1_RX_DATA_TYPE_MASK >>
1794			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1795			      ARRAY_SIZE(madera_dfc_type_text),
1796			      madera_dfc_type_text,
1797			      madera_dfc_type_val),
1798	SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_TX,
1799			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1800			      MADERA_DFC1_TX_DATA_TYPE_MASK >>
1801			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1802			      ARRAY_SIZE(madera_dfc_type_text),
1803			      madera_dfc_type_text,
1804			      madera_dfc_type_val),
1805	SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_RX,
1806			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1807			      MADERA_DFC1_RX_DATA_TYPE_MASK >>
1808			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1809			      ARRAY_SIZE(madera_dfc_type_text),
1810			      madera_dfc_type_text,
1811			      madera_dfc_type_val),
1812	SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_TX,
1813			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1814			      MADERA_DFC1_TX_DATA_TYPE_MASK >>
1815			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1816			      ARRAY_SIZE(madera_dfc_type_text),
1817			      madera_dfc_type_text,
1818			      madera_dfc_type_val),
1819	SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_RX,
1820			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1821			      MADERA_DFC1_RX_DATA_TYPE_MASK >>
1822			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1823			      ARRAY_SIZE(madera_dfc_type_text),
1824			      madera_dfc_type_text,
1825			      madera_dfc_type_val),
1826	SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_TX,
1827			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1828			      MADERA_DFC1_TX_DATA_TYPE_MASK >>
1829			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1830			      ARRAY_SIZE(madera_dfc_type_text),
1831			      madera_dfc_type_text,
1832			      madera_dfc_type_val),
1833	SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_RX,
1834			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1835			      MADERA_DFC1_RX_DATA_TYPE_MASK >>
1836			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1837			      ARRAY_SIZE(madera_dfc_type_text),
1838			      madera_dfc_type_text,
1839			      madera_dfc_type_val),
1840	SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_TX,
1841			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1842			      MADERA_DFC1_TX_DATA_TYPE_MASK >>
1843			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1844			      ARRAY_SIZE(madera_dfc_type_text),
1845			      madera_dfc_type_text,
1846			      madera_dfc_type_val),
1847	SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_RX,
1848			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1849			      MADERA_DFC1_RX_DATA_TYPE_MASK >>
1850			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1851			      ARRAY_SIZE(madera_dfc_type_text),
1852			      madera_dfc_type_text,
1853			      madera_dfc_type_val),
1854	SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_TX,
1855			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1856			      MADERA_DFC1_TX_DATA_TYPE_MASK >>
1857			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1858			      ARRAY_SIZE(madera_dfc_type_text),
1859			      madera_dfc_type_text,
1860			      madera_dfc_type_val),
1861	SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_RX,
1862			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1863			      MADERA_DFC1_RX_DATA_TYPE_MASK >>
1864			      MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1865			      ARRAY_SIZE(madera_dfc_type_text),
1866			      madera_dfc_type_text,
1867			      madera_dfc_type_val),
1868	SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_TX,
1869			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1870			      MADERA_DFC1_TX_DATA_TYPE_MASK >>
1871			      MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1872			      ARRAY_SIZE(madera_dfc_type_text),
1873			      madera_dfc_type_text,
1874			      madera_dfc_type_val),
1875};
1876EXPORT_SYMBOL_GPL(madera_dfc_type);
1877
1878const struct soc_enum madera_isrc_fsh[] = {
1879	SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_1_CTRL_1,
1880			      MADERA_ISRC1_FSH_SHIFT, 0xf,
1881			      MADERA_RATE_ENUM_SIZE,
1882			      madera_rate_text, madera_rate_val),
1883	SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_2_CTRL_1,
1884			      MADERA_ISRC2_FSH_SHIFT, 0xf,
1885			      MADERA_RATE_ENUM_SIZE,
1886			      madera_rate_text, madera_rate_val),
1887	SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_3_CTRL_1,
1888			      MADERA_ISRC3_FSH_SHIFT, 0xf,
1889			      MADERA_RATE_ENUM_SIZE,
1890			      madera_rate_text, madera_rate_val),
1891	SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_4_CTRL_1,
1892			      MADERA_ISRC4_FSH_SHIFT, 0xf,
1893			      MADERA_RATE_ENUM_SIZE,
1894			      madera_rate_text, madera_rate_val),
1895};
1896EXPORT_SYMBOL_GPL(madera_isrc_fsh);
1897
1898const struct soc_enum madera_isrc_fsl[] = {
1899	SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_1_CTRL_2,
1900			      MADERA_ISRC1_FSL_SHIFT, 0xf,
1901			      MADERA_RATE_ENUM_SIZE,
1902			      madera_rate_text, madera_rate_val),
1903	SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_2_CTRL_2,
1904			      MADERA_ISRC2_FSL_SHIFT, 0xf,
1905			      MADERA_RATE_ENUM_SIZE,
1906			      madera_rate_text, madera_rate_val),
1907	SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_3_CTRL_2,
1908			      MADERA_ISRC3_FSL_SHIFT, 0xf,
1909			      MADERA_RATE_ENUM_SIZE,
1910			      madera_rate_text, madera_rate_val),
1911	SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_4_CTRL_2,
1912			      MADERA_ISRC4_FSL_SHIFT, 0xf,
1913			      MADERA_RATE_ENUM_SIZE,
1914			      madera_rate_text, madera_rate_val),
1915};
1916EXPORT_SYMBOL_GPL(madera_isrc_fsl);
1917
1918const struct soc_enum madera_asrc1_rate[] = {
1919	SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1,
1920			      MADERA_ASRC1_RATE1_SHIFT, 0xf,
1921			      MADERA_SYNC_RATE_ENUM_SIZE,
1922			      madera_rate_text, madera_rate_val),
1923	SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2,
1924			      MADERA_ASRC1_RATE1_SHIFT, 0xf,
1925			      MADERA_ASYNC_RATE_ENUM_SIZE,
1926			      madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
1927			      madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
1928};
1929EXPORT_SYMBOL_GPL(madera_asrc1_rate);
1930
1931const struct soc_enum madera_asrc1_bidir_rate[] = {
1932	SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1,
1933			      MADERA_ASRC1_RATE1_SHIFT, 0xf,
1934			      MADERA_RATE_ENUM_SIZE,
1935			      madera_rate_text, madera_rate_val),
1936	SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2,
1937			      MADERA_ASRC1_RATE2_SHIFT, 0xf,
1938			      MADERA_RATE_ENUM_SIZE,
1939			      madera_rate_text, madera_rate_val),
1940};
1941EXPORT_SYMBOL_GPL(madera_asrc1_bidir_rate);
1942
1943const struct soc_enum madera_asrc2_rate[] = {
1944	SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE1,
1945			      MADERA_ASRC2_RATE1_SHIFT, 0xf,
1946			      MADERA_SYNC_RATE_ENUM_SIZE,
1947			      madera_rate_text, madera_rate_val),
1948	SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE2,
1949			      MADERA_ASRC2_RATE2_SHIFT, 0xf,
1950			      MADERA_ASYNC_RATE_ENUM_SIZE,
1951			      madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
1952			      madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
1953};
1954EXPORT_SYMBOL_GPL(madera_asrc2_rate);
1955
1956static const char * const madera_vol_ramp_text[] = {
1957	"0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
1958	"15ms/6dB", "30ms/6dB",
1959};
1960
1961SOC_ENUM_SINGLE_DECL(madera_in_vd_ramp,
1962		     MADERA_INPUT_VOLUME_RAMP,
1963		     MADERA_IN_VD_RAMP_SHIFT,
1964		     madera_vol_ramp_text);
1965EXPORT_SYMBOL_GPL(madera_in_vd_ramp);
1966
1967SOC_ENUM_SINGLE_DECL(madera_in_vi_ramp,
1968		     MADERA_INPUT_VOLUME_RAMP,
1969		     MADERA_IN_VI_RAMP_SHIFT,
1970		     madera_vol_ramp_text);
1971EXPORT_SYMBOL_GPL(madera_in_vi_ramp);
1972
1973SOC_ENUM_SINGLE_DECL(madera_out_vd_ramp,
1974		     MADERA_OUTPUT_VOLUME_RAMP,
1975		     MADERA_OUT_VD_RAMP_SHIFT,
1976		     madera_vol_ramp_text);
1977EXPORT_SYMBOL_GPL(madera_out_vd_ramp);
1978
1979SOC_ENUM_SINGLE_DECL(madera_out_vi_ramp,
1980		     MADERA_OUTPUT_VOLUME_RAMP,
1981		     MADERA_OUT_VI_RAMP_SHIFT,
1982		     madera_vol_ramp_text);
1983EXPORT_SYMBOL_GPL(madera_out_vi_ramp);
1984
1985static const char * const madera_lhpf_mode_text[] = {
1986	"Low-pass", "High-pass"
1987};
1988
1989SOC_ENUM_SINGLE_DECL(madera_lhpf1_mode,
1990		     MADERA_HPLPF1_1,
1991		     MADERA_LHPF1_MODE_SHIFT,
1992		     madera_lhpf_mode_text);
1993EXPORT_SYMBOL_GPL(madera_lhpf1_mode);
1994
1995SOC_ENUM_SINGLE_DECL(madera_lhpf2_mode,
1996		     MADERA_HPLPF2_1,
1997		     MADERA_LHPF2_MODE_SHIFT,
1998		     madera_lhpf_mode_text);
1999EXPORT_SYMBOL_GPL(madera_lhpf2_mode);
2000
2001SOC_ENUM_SINGLE_DECL(madera_lhpf3_mode,
2002		     MADERA_HPLPF3_1,
2003		     MADERA_LHPF3_MODE_SHIFT,
2004		     madera_lhpf_mode_text);
2005EXPORT_SYMBOL_GPL(madera_lhpf3_mode);
2006
2007SOC_ENUM_SINGLE_DECL(madera_lhpf4_mode,
2008		     MADERA_HPLPF4_1,
2009		     MADERA_LHPF4_MODE_SHIFT,
2010		     madera_lhpf_mode_text);
2011EXPORT_SYMBOL_GPL(madera_lhpf4_mode);
2012
2013static const char * const madera_ng_hold_text[] = {
2014	"30ms", "120ms", "250ms", "500ms",
2015};
2016
2017SOC_ENUM_SINGLE_DECL(madera_ng_hold,
2018		     MADERA_NOISE_GATE_CONTROL,
2019		     MADERA_NGATE_HOLD_SHIFT,
2020		     madera_ng_hold_text);
2021EXPORT_SYMBOL_GPL(madera_ng_hold);
2022
2023static const char * const madera_in_hpf_cut_text[] = {
2024	"2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
2025};
2026
2027SOC_ENUM_SINGLE_DECL(madera_in_hpf_cut_enum,
2028		     MADERA_HPF_CONTROL,
2029		     MADERA_IN_HPF_CUT_SHIFT,
2030		     madera_in_hpf_cut_text);
2031EXPORT_SYMBOL_GPL(madera_in_hpf_cut_enum);
2032
2033static const char * const madera_in_dmic_osr_text[MADERA_OSR_ENUM_SIZE] = {
2034	"384kHz", "768kHz", "1.536MHz", "3.072MHz", "6.144MHz",
2035};
2036
2037static const unsigned int madera_in_dmic_osr_val[MADERA_OSR_ENUM_SIZE] = {
2038	2, 3, 4, 5, 6,
2039};
2040
2041const struct soc_enum madera_in_dmic_osr[] = {
2042	SOC_VALUE_ENUM_SINGLE(MADERA_DMIC1L_CONTROL, MADERA_IN1_OSR_SHIFT,
2043			      0x7, MADERA_OSR_ENUM_SIZE,
2044			      madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2045	SOC_VALUE_ENUM_SINGLE(MADERA_DMIC2L_CONTROL, MADERA_IN2_OSR_SHIFT,
2046			      0x7, MADERA_OSR_ENUM_SIZE,
2047			      madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2048	SOC_VALUE_ENUM_SINGLE(MADERA_DMIC3L_CONTROL, MADERA_IN3_OSR_SHIFT,
2049			      0x7, MADERA_OSR_ENUM_SIZE,
2050			      madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2051	SOC_VALUE_ENUM_SINGLE(MADERA_DMIC4L_CONTROL, MADERA_IN4_OSR_SHIFT,
2052			      0x7, MADERA_OSR_ENUM_SIZE,
2053			      madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2054	SOC_VALUE_ENUM_SINGLE(MADERA_DMIC5L_CONTROL, MADERA_IN5_OSR_SHIFT,
2055			      0x7, MADERA_OSR_ENUM_SIZE,
2056			      madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2057	SOC_VALUE_ENUM_SINGLE(MADERA_DMIC6L_CONTROL, MADERA_IN6_OSR_SHIFT,
2058			      0x7, MADERA_OSR_ENUM_SIZE,
2059			      madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2060};
2061EXPORT_SYMBOL_GPL(madera_in_dmic_osr);
2062
2063static const char * const madera_anc_input_src_text[] = {
2064	"None", "IN1", "IN2", "IN3", "IN4", "IN5", "IN6",
2065};
2066
2067static const char * const madera_anc_channel_src_text[] = {
2068	"None", "Left", "Right", "Combine",
2069};
2070
2071const struct soc_enum madera_anc_input_src[] = {
2072	SOC_ENUM_SINGLE(MADERA_ANC_SRC,
2073			MADERA_IN_RXANCL_SEL_SHIFT,
2074			ARRAY_SIZE(madera_anc_input_src_text),
2075			madera_anc_input_src_text),
2076	SOC_ENUM_SINGLE(MADERA_FCL_ADC_REFORMATTER_CONTROL,
2077			MADERA_FCL_MIC_MODE_SEL_SHIFT,
2078			ARRAY_SIZE(madera_anc_channel_src_text),
2079			madera_anc_channel_src_text),
2080	SOC_ENUM_SINGLE(MADERA_ANC_SRC,
2081			MADERA_IN_RXANCR_SEL_SHIFT,
2082			ARRAY_SIZE(madera_anc_input_src_text),
2083			madera_anc_input_src_text),
2084	SOC_ENUM_SINGLE(MADERA_FCR_ADC_REFORMATTER_CONTROL,
2085			MADERA_FCR_MIC_MODE_SEL_SHIFT,
2086			ARRAY_SIZE(madera_anc_channel_src_text),
2087			madera_anc_channel_src_text),
2088};
2089EXPORT_SYMBOL_GPL(madera_anc_input_src);
2090
2091static const char * const madera_anc_ng_texts[] = {
2092	"None", "Internal", "External",
2093};
2094
2095SOC_ENUM_SINGLE_DECL(madera_anc_ng_enum, SND_SOC_NOPM, 0, madera_anc_ng_texts);
2096EXPORT_SYMBOL_GPL(madera_anc_ng_enum);
2097
2098static const char * const madera_out_anc_src_text[] = {
2099	"None", "RXANCL", "RXANCR",
2100};
2101
2102const struct soc_enum madera_output_anc_src[] = {
2103	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_1L,
2104			MADERA_OUT1L_ANC_SRC_SHIFT,
2105			ARRAY_SIZE(madera_out_anc_src_text),
2106			madera_out_anc_src_text),
2107	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_1R,
2108			MADERA_OUT1R_ANC_SRC_SHIFT,
2109			ARRAY_SIZE(madera_out_anc_src_text),
2110			madera_out_anc_src_text),
2111	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_2L,
2112			MADERA_OUT2L_ANC_SRC_SHIFT,
2113			ARRAY_SIZE(madera_out_anc_src_text),
2114			madera_out_anc_src_text),
2115	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_2R,
2116			MADERA_OUT2R_ANC_SRC_SHIFT,
2117			ARRAY_SIZE(madera_out_anc_src_text),
2118			madera_out_anc_src_text),
2119	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_3L,
2120			MADERA_OUT3L_ANC_SRC_SHIFT,
2121			ARRAY_SIZE(madera_out_anc_src_text),
2122			madera_out_anc_src_text),
2123	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_3R,
2124			MADERA_OUT3R_ANC_SRC_SHIFT,
2125			ARRAY_SIZE(madera_out_anc_src_text),
2126			madera_out_anc_src_text),
2127	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_4L,
2128			MADERA_OUT4L_ANC_SRC_SHIFT,
2129			ARRAY_SIZE(madera_out_anc_src_text),
2130			madera_out_anc_src_text),
2131	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_4R,
2132			MADERA_OUT4R_ANC_SRC_SHIFT,
2133			ARRAY_SIZE(madera_out_anc_src_text),
2134			madera_out_anc_src_text),
2135	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_5L,
2136			MADERA_OUT5L_ANC_SRC_SHIFT,
2137			ARRAY_SIZE(madera_out_anc_src_text),
2138			madera_out_anc_src_text),
2139	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_5R,
2140			MADERA_OUT5R_ANC_SRC_SHIFT,
2141			ARRAY_SIZE(madera_out_anc_src_text),
2142			madera_out_anc_src_text),
2143	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_6L,
2144			MADERA_OUT6L_ANC_SRC_SHIFT,
2145			ARRAY_SIZE(madera_out_anc_src_text),
2146			madera_out_anc_src_text),
2147	SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_6R,
2148			MADERA_OUT6R_ANC_SRC_SHIFT,
2149			ARRAY_SIZE(madera_out_anc_src_text),
2150			madera_out_anc_src_text),
2151};
2152EXPORT_SYMBOL_GPL(madera_output_anc_src);
2153
2154int madera_dfc_put(struct snd_kcontrol *kcontrol,
2155		   struct snd_ctl_elem_value *ucontrol)
2156{
2157	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
2158	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
2159	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2160	unsigned int reg = e->reg;
2161	unsigned int val;
2162	int ret = 0;
2163
2164	reg = ((reg / 6) * 6) - 2;
2165
2166	snd_soc_dapm_mutex_lock(dapm);
2167
2168	val = snd_soc_component_read(component, reg);
2169	if (val & MADERA_DFC1_ENA) {
2170		ret = -EBUSY;
2171		dev_err(component->dev, "Can't change mode on an active DFC\n");
2172		goto exit;
2173	}
2174
2175	ret = snd_soc_put_enum_double(kcontrol, ucontrol);
2176exit:
2177	snd_soc_dapm_mutex_unlock(dapm);
2178
2179	return ret;
2180}
2181EXPORT_SYMBOL_GPL(madera_dfc_put);
2182
2183int madera_lp_mode_put(struct snd_kcontrol *kcontrol,
2184		       struct snd_ctl_elem_value *ucontrol)
2185{
2186	struct soc_mixer_control *mc =
2187		(struct soc_mixer_control *)kcontrol->private_value;
2188	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
2189	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
2190	unsigned int val, mask;
2191	int ret;
2192
2193	snd_soc_dapm_mutex_lock(dapm);
2194
2195	/* Cannot change lp mode on an active input */
2196	val = snd_soc_component_read(component, MADERA_INPUT_ENABLES);
2197	mask = (mc->reg - MADERA_ADC_DIGITAL_VOLUME_1L) / 4;
2198	mask ^= 0x1; /* Flip bottom bit for channel order */
2199
2200	if (val & (1 << mask)) {
2201		ret = -EBUSY;
2202		dev_err(component->dev,
2203			"Can't change lp mode on an active input\n");
2204		goto exit;
2205	}
2206
2207	ret = snd_soc_put_volsw(kcontrol, ucontrol);
2208
2209exit:
2210	snd_soc_dapm_mutex_unlock(dapm);
2211
2212	return ret;
2213}
2214EXPORT_SYMBOL_GPL(madera_lp_mode_put);
2215
2216const struct snd_kcontrol_new madera_dsp_trigger_output_mux[] = {
2217	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2218	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2219	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2220	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2221	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2222	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2223	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2224};
2225EXPORT_SYMBOL_GPL(madera_dsp_trigger_output_mux);
2226
2227const struct snd_kcontrol_new madera_drc_activity_output_mux[] = {
2228	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2229	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2230};
2231EXPORT_SYMBOL_GPL(madera_drc_activity_output_mux);
2232
2233static void madera_in_set_vu(struct madera_priv *priv, bool enable)
2234{
2235	unsigned int val;
2236	int i, ret;
2237
2238	if (enable)
2239		val = MADERA_IN_VU;
2240	else
2241		val = 0;
2242
2243	for (i = 0; i < priv->num_inputs; i++) {
2244		ret = regmap_update_bits(priv->madera->regmap,
2245					 MADERA_ADC_DIGITAL_VOLUME_1L + (i * 4),
2246					 MADERA_IN_VU, val);
2247		if (ret)
2248			dev_warn(priv->madera->dev,
2249				 "Failed to modify VU bits: %d\n", ret);
2250	}
2251}
2252
2253int madera_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
2254		 int event)
2255{
2256	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2257	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2258	unsigned int reg, val;
2259
2260	if (w->shift % 2)
2261		reg = MADERA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
2262	else
2263		reg = MADERA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
2264
2265	switch (event) {
2266	case SND_SOC_DAPM_PRE_PMU:
2267		priv->in_pending++;
2268		break;
2269	case SND_SOC_DAPM_POST_PMU:
2270		priv->in_pending--;
2271		snd_soc_component_update_bits(component, reg,
2272					      MADERA_IN1L_MUTE, 0);
2273
2274		/* If this is the last input pending then allow VU */
2275		if (priv->in_pending == 0) {
2276			usleep_range(1000, 3000);
2277			madera_in_set_vu(priv, true);
2278		}
2279		break;
2280	case SND_SOC_DAPM_PRE_PMD:
2281		snd_soc_component_update_bits(component, reg,
2282					      MADERA_IN1L_MUTE | MADERA_IN_VU,
2283					      MADERA_IN1L_MUTE | MADERA_IN_VU);
2284		break;
2285	case SND_SOC_DAPM_POST_PMD:
2286		/* Disable volume updates if no inputs are enabled */
2287		val = snd_soc_component_read(component, MADERA_INPUT_ENABLES);
2288		if (!val)
2289			madera_in_set_vu(priv, false);
2290		break;
2291	default:
2292		break;
2293	}
2294
2295	return 0;
2296}
2297EXPORT_SYMBOL_GPL(madera_in_ev);
2298
2299int madera_out_ev(struct snd_soc_dapm_widget *w,
2300		  struct snd_kcontrol *kcontrol, int event)
2301{
2302	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2303	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2304	struct madera *madera = priv->madera;
2305	int out_up_delay;
2306
2307	switch (madera->type) {
2308	case CS47L90:
2309	case CS47L91:
2310	case CS42L92:
2311	case CS47L92:
2312	case CS47L93:
2313		out_up_delay = 6000;
2314		break;
2315	default:
2316		out_up_delay = 17000;
2317		break;
2318	}
2319
2320	switch (event) {
2321	case SND_SOC_DAPM_PRE_PMU:
2322		switch (w->shift) {
2323		case MADERA_OUT1L_ENA_SHIFT:
2324		case MADERA_OUT1R_ENA_SHIFT:
2325		case MADERA_OUT2L_ENA_SHIFT:
2326		case MADERA_OUT2R_ENA_SHIFT:
2327		case MADERA_OUT3L_ENA_SHIFT:
2328		case MADERA_OUT3R_ENA_SHIFT:
2329			priv->out_up_pending++;
2330			priv->out_up_delay += out_up_delay;
2331			break;
2332		default:
2333			break;
2334		}
2335		break;
2336
2337	case SND_SOC_DAPM_POST_PMU:
2338		switch (w->shift) {
2339		case MADERA_OUT1L_ENA_SHIFT:
2340		case MADERA_OUT1R_ENA_SHIFT:
2341		case MADERA_OUT2L_ENA_SHIFT:
2342		case MADERA_OUT2R_ENA_SHIFT:
2343		case MADERA_OUT3L_ENA_SHIFT:
2344		case MADERA_OUT3R_ENA_SHIFT:
2345			priv->out_up_pending--;
2346			if (!priv->out_up_pending) {
2347				fsleep(priv->out_up_delay);
2348				priv->out_up_delay = 0;
2349			}
2350			break;
2351
2352		default:
2353			break;
2354		}
2355		break;
2356
2357	case SND_SOC_DAPM_PRE_PMD:
2358		switch (w->shift) {
2359		case MADERA_OUT1L_ENA_SHIFT:
2360		case MADERA_OUT1R_ENA_SHIFT:
2361		case MADERA_OUT2L_ENA_SHIFT:
2362		case MADERA_OUT2R_ENA_SHIFT:
2363		case MADERA_OUT3L_ENA_SHIFT:
2364		case MADERA_OUT3R_ENA_SHIFT:
2365			priv->out_down_pending++;
2366			priv->out_down_delay += 1000;
2367			break;
2368		default:
2369			break;
2370		}
2371		break;
2372
2373	case SND_SOC_DAPM_POST_PMD:
2374		switch (w->shift) {
2375		case MADERA_OUT1L_ENA_SHIFT:
2376		case MADERA_OUT1R_ENA_SHIFT:
2377		case MADERA_OUT2L_ENA_SHIFT:
2378		case MADERA_OUT2R_ENA_SHIFT:
2379		case MADERA_OUT3L_ENA_SHIFT:
2380		case MADERA_OUT3R_ENA_SHIFT:
2381			priv->out_down_pending--;
2382			if (!priv->out_down_pending) {
2383				fsleep(priv->out_down_delay);
2384				priv->out_down_delay = 0;
2385			}
2386			break;
2387		default:
2388			break;
2389		}
2390		break;
2391	default:
2392		break;
2393	}
2394
2395	return 0;
2396}
2397EXPORT_SYMBOL_GPL(madera_out_ev);
2398
2399int madera_hp_ev(struct snd_soc_dapm_widget *w,
2400		 struct snd_kcontrol *kcontrol, int event)
2401{
2402	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2403	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2404	struct madera *madera = priv->madera;
2405	unsigned int mask = 1 << w->shift;
2406	unsigned int out_num = w->shift / 2;
2407	unsigned int val;
2408	unsigned int ep_sel = 0;
2409
2410	switch (event) {
2411	case SND_SOC_DAPM_POST_PMU:
2412		val = mask;
2413		break;
2414	case SND_SOC_DAPM_PRE_PMD:
2415		val = 0;
2416		break;
2417	case SND_SOC_DAPM_PRE_PMU:
2418	case SND_SOC_DAPM_POST_PMD:
2419		return madera_out_ev(w, kcontrol, event);
2420	default:
2421		return 0;
2422	}
2423
2424	/* Store the desired state for the HP outputs */
2425	madera->hp_ena &= ~mask;
2426	madera->hp_ena |= val;
2427
2428	switch (madera->type) {
2429	case CS42L92:
2430	case CS47L92:
2431	case CS47L93:
2432		break;
2433	default:
2434		/* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */
2435		regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel);
2436		ep_sel &= MADERA_EP_SEL_MASK;
2437		break;
2438	}
2439
2440	/* Force off if HPDET has disabled the clamp for this output */
2441	if (!ep_sel &&
2442	    (!madera->out_clamp[out_num] || madera->out_shorted[out_num]))
2443		val = 0;
2444
2445	regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, mask, val);
2446
2447	return madera_out_ev(w, kcontrol, event);
2448}
2449EXPORT_SYMBOL_GPL(madera_hp_ev);
2450
2451int madera_anc_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
2452		  int event)
2453{
2454	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2455	unsigned int val;
2456
2457	switch (event) {
2458	case SND_SOC_DAPM_POST_PMU:
2459		val = 1 << w->shift;
2460		break;
2461	case SND_SOC_DAPM_PRE_PMD:
2462		val = 1 << (w->shift + 1);
2463		break;
2464	default:
2465		return 0;
2466	}
2467
2468	snd_soc_component_write(component, MADERA_CLOCK_CONTROL, val);
2469
2470	return 0;
2471}
2472EXPORT_SYMBOL_GPL(madera_anc_ev);
2473
2474static const unsigned int madera_opclk_ref_48k_rates[] = {
2475	6144000,
2476	12288000,
2477	24576000,
2478	49152000,
2479};
2480
2481static const unsigned int madera_opclk_ref_44k1_rates[] = {
2482	5644800,
2483	11289600,
2484	22579200,
2485	45158400,
2486};
2487
2488static int madera_set_opclk(struct snd_soc_component *component,
2489			    unsigned int clk, unsigned int freq)
2490{
2491	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2492	unsigned int mask = MADERA_OPCLK_DIV_MASK | MADERA_OPCLK_SEL_MASK;
2493	unsigned int reg, val;
2494	const unsigned int *rates;
2495	int ref, div, refclk;
2496
2497	BUILD_BUG_ON(ARRAY_SIZE(madera_opclk_ref_48k_rates) !=
2498		     ARRAY_SIZE(madera_opclk_ref_44k1_rates));
2499
2500	switch (clk) {
2501	case MADERA_CLK_OPCLK:
2502		reg = MADERA_OUTPUT_SYSTEM_CLOCK;
2503		refclk = priv->sysclk;
2504		break;
2505	case MADERA_CLK_ASYNC_OPCLK:
2506		reg = MADERA_OUTPUT_ASYNC_CLOCK;
2507		refclk = priv->asyncclk;
2508		break;
2509	default:
2510		return -EINVAL;
2511	}
2512
2513	if (refclk % 4000)
2514		rates = madera_opclk_ref_44k1_rates;
2515	else
2516		rates = madera_opclk_ref_48k_rates;
2517
2518	for (ref = 0; ref < ARRAY_SIZE(madera_opclk_ref_48k_rates); ++ref) {
2519		if (rates[ref] > refclk)
2520			continue;
2521
2522		div = 2;
2523		while ((rates[ref] / div >= freq) && (div <= 30)) {
2524			if (rates[ref] / div == freq) {
2525				dev_dbg(component->dev, "Configured %dHz OPCLK\n",
2526					freq);
2527
2528				val = (div << MADERA_OPCLK_DIV_SHIFT) | ref;
2529
2530				snd_soc_component_update_bits(component, reg,
2531							      mask, val);
2532				return 0;
2533			}
2534			div += 2;
2535		}
2536	}
2537
2538	dev_err(component->dev, "Unable to generate %dHz OPCLK\n", freq);
2539
2540	return -EINVAL;
2541}
2542
2543static int madera_get_sysclk_setting(unsigned int freq)
2544{
2545	switch (freq) {
2546	case 0:
2547	case 5644800:
2548	case 6144000:
2549		return 0;
2550	case 11289600:
2551	case 12288000:
2552		return MADERA_SYSCLK_12MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2553	case 22579200:
2554	case 24576000:
2555		return MADERA_SYSCLK_24MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2556	case 45158400:
2557	case 49152000:
2558		return MADERA_SYSCLK_49MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2559	case 90316800:
2560	case 98304000:
2561		return MADERA_SYSCLK_98MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2562	default:
2563		return -EINVAL;
2564	}
2565}
2566
2567static int madera_get_legacy_dspclk_setting(struct madera *madera,
2568					    unsigned int freq)
2569{
2570	switch (freq) {
2571	case 0:
2572		return 0;
2573	case 45158400:
2574	case 49152000:
2575		switch (madera->type) {
2576		case CS47L85:
2577		case WM1840:
2578			if (madera->rev < 3)
2579				return -EINVAL;
2580			else
2581				return MADERA_SYSCLK_49MHZ <<
2582				       MADERA_SYSCLK_FREQ_SHIFT;
2583		default:
2584			return -EINVAL;
2585		}
2586	case 135475200:
2587	case 147456000:
2588		return MADERA_DSPCLK_147MHZ << MADERA_DSP_CLK_FREQ_LEGACY_SHIFT;
2589	default:
2590		return -EINVAL;
2591	}
2592}
2593
2594static int madera_get_dspclk_setting(struct madera *madera,
2595				     unsigned int freq,
2596				     unsigned int *clock_2_val)
2597{
2598	switch (madera->type) {
2599	case CS47L35:
2600	case CS47L85:
2601	case WM1840:
2602		*clock_2_val = 0; /* don't use MADERA_DSP_CLOCK_2 */
2603		return madera_get_legacy_dspclk_setting(madera, freq);
2604	default:
2605		if (freq > 150000000)
2606			return -EINVAL;
2607
2608		/* Use new exact frequency control */
2609		*clock_2_val = freq / 15625; /* freq * (2^6) / (10^6) */
2610		return 0;
2611	}
2612}
2613
2614static int madera_set_outclk(struct snd_soc_component *component,
2615			     unsigned int source, unsigned int freq)
2616{
2617	int div, div_inc, rate;
2618
2619	switch (source) {
2620	case MADERA_OUTCLK_SYSCLK:
2621		dev_dbg(component->dev, "Configured OUTCLK to SYSCLK\n");
2622		snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1,
2623					      MADERA_OUT_CLK_SRC_MASK, source);
2624		return 0;
2625	case MADERA_OUTCLK_ASYNCCLK:
2626		dev_dbg(component->dev, "Configured OUTCLK to ASYNCCLK\n");
2627		snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1,
2628					      MADERA_OUT_CLK_SRC_MASK, source);
2629		return 0;
2630	case MADERA_OUTCLK_MCLK1:
2631	case MADERA_OUTCLK_MCLK2:
2632	case MADERA_OUTCLK_MCLK3:
2633		break;
2634	default:
2635		return -EINVAL;
2636	}
2637
2638	if (freq % 4000)
2639		rate = 5644800;
2640	else
2641		rate = 6144000;
2642
2643	div = 1;
2644	div_inc = 0;
2645	while (div <= 8) {
2646		if (freq / div == rate && !(freq % div)) {
2647			dev_dbg(component->dev, "Configured %dHz OUTCLK\n", rate);
2648			snd_soc_component_update_bits(component,
2649				MADERA_OUTPUT_RATE_1,
2650				MADERA_OUT_EXT_CLK_DIV_MASK |
2651				MADERA_OUT_CLK_SRC_MASK,
2652				(div_inc << MADERA_OUT_EXT_CLK_DIV_SHIFT) |
2653				source);
2654			return 0;
2655		}
2656		div_inc++;
2657		div *= 2;
2658	}
2659
2660	dev_err(component->dev,
2661		"Unable to generate %dHz OUTCLK from %dHz MCLK\n",
2662		rate, freq);
2663	return -EINVAL;
2664}
2665
2666int madera_set_sysclk(struct snd_soc_component *component, int clk_id,
2667		      int source, unsigned int freq, int dir)
2668{
2669	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2670	struct madera *madera = priv->madera;
2671	char *name;
2672	unsigned int reg, clock_2_val = 0;
2673	unsigned int mask = MADERA_SYSCLK_FREQ_MASK | MADERA_SYSCLK_SRC_MASK;
2674	unsigned int val = source << MADERA_SYSCLK_SRC_SHIFT;
2675	int clk_freq_sel, *clk;
2676	int ret = 0;
2677
2678	switch (clk_id) {
2679	case MADERA_CLK_SYSCLK_1:
2680		name = "SYSCLK";
2681		reg = MADERA_SYSTEM_CLOCK_1;
2682		clk = &priv->sysclk;
2683		clk_freq_sel = madera_get_sysclk_setting(freq);
2684		mask |= MADERA_SYSCLK_FRAC;
2685		break;
2686	case MADERA_CLK_ASYNCCLK_1:
2687		name = "ASYNCCLK";
2688		reg = MADERA_ASYNC_CLOCK_1;
2689		clk = &priv->asyncclk;
2690		clk_freq_sel = madera_get_sysclk_setting(freq);
2691		break;
2692	case MADERA_CLK_DSPCLK:
2693		name = "DSPCLK";
2694		reg = MADERA_DSP_CLOCK_1;
2695		clk = &priv->dspclk;
2696		clk_freq_sel = madera_get_dspclk_setting(madera, freq,
2697							 &clock_2_val);
2698		break;
2699	case MADERA_CLK_OPCLK:
2700	case MADERA_CLK_ASYNC_OPCLK:
2701		return madera_set_opclk(component, clk_id, freq);
2702	case MADERA_CLK_OUTCLK:
2703		return madera_set_outclk(component, source, freq);
2704	default:
2705		return -EINVAL;
2706	}
2707
2708	if (clk_freq_sel < 0) {
2709		dev_err(madera->dev,
2710			"Failed to get clk setting for %dHZ\n", freq);
2711		return clk_freq_sel;
2712	}
2713
2714	*clk = freq;
2715
2716	if (freq == 0) {
2717		dev_dbg(madera->dev, "%s cleared\n", name);
2718		return 0;
2719	}
2720
2721	val |= clk_freq_sel;
2722
2723	if (clock_2_val) {
2724		ret = regmap_write(madera->regmap, MADERA_DSP_CLOCK_2,
2725				   clock_2_val);
2726		if (ret) {
2727			dev_err(madera->dev,
2728				"Failed to write DSP_CONFIG2: %d\n", ret);
2729			return ret;
2730		}
2731
2732		/*
2733		 * We're using the frequency setting in MADERA_DSP_CLOCK_2 so
2734		 * don't change the frequency select bits in MADERA_DSP_CLOCK_1
2735		 */
2736		mask = MADERA_SYSCLK_SRC_MASK;
2737	}
2738
2739	if (freq % 6144000)
2740		val |= MADERA_SYSCLK_FRAC;
2741
2742	dev_dbg(madera->dev, "%s set to %uHz\n", name, freq);
2743
2744	return regmap_update_bits(madera->regmap, reg, mask, val);
2745}
2746EXPORT_SYMBOL_GPL(madera_set_sysclk);
2747
2748static int madera_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2749{
2750	struct snd_soc_component *component = dai->component;
2751	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2752	struct madera *madera = priv->madera;
2753	int lrclk, bclk, mode, base;
2754
2755	base = dai->driver->base;
2756
2757	lrclk = 0;
2758	bclk = 0;
2759
2760	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
2761	case SND_SOC_DAIFMT_DSP_A:
2762		mode = MADERA_FMT_DSP_MODE_A;
2763		break;
2764	case SND_SOC_DAIFMT_DSP_B:
2765		if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) !=
2766		    SND_SOC_DAIFMT_CBP_CFP) {
2767			madera_aif_err(dai, "DSP_B not valid in slave mode\n");
2768			return -EINVAL;
2769		}
2770		mode = MADERA_FMT_DSP_MODE_B;
2771		break;
2772	case SND_SOC_DAIFMT_I2S:
2773		mode = MADERA_FMT_I2S_MODE;
2774		break;
2775	case SND_SOC_DAIFMT_LEFT_J:
2776		if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) !=
2777		    SND_SOC_DAIFMT_CBP_CFP) {
2778			madera_aif_err(dai, "LEFT_J not valid in slave mode\n");
2779			return -EINVAL;
2780		}
2781		mode = MADERA_FMT_LEFT_JUSTIFIED_MODE;
2782		break;
2783	default:
2784		madera_aif_err(dai, "Unsupported DAI format %d\n",
2785			       fmt & SND_SOC_DAIFMT_FORMAT_MASK);
2786		return -EINVAL;
2787	}
2788
2789	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
2790	case SND_SOC_DAIFMT_CBC_CFC:
2791		break;
2792	case SND_SOC_DAIFMT_CBC_CFP:
2793		lrclk |= MADERA_AIF1TX_LRCLK_MSTR;
2794		break;
2795	case SND_SOC_DAIFMT_CBP_CFC:
2796		bclk |= MADERA_AIF1_BCLK_MSTR;
2797		break;
2798	case SND_SOC_DAIFMT_CBP_CFP:
2799		bclk |= MADERA_AIF1_BCLK_MSTR;
2800		lrclk |= MADERA_AIF1TX_LRCLK_MSTR;
2801		break;
2802	default:
2803		madera_aif_err(dai, "Unsupported master mode %d\n",
2804			       fmt & SND_SOC_DAIFMT_MASTER_MASK);
2805		return -EINVAL;
2806	}
2807
2808	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
2809	case SND_SOC_DAIFMT_NB_NF:
2810		break;
2811	case SND_SOC_DAIFMT_IB_IF:
2812		bclk |= MADERA_AIF1_BCLK_INV;
2813		lrclk |= MADERA_AIF1TX_LRCLK_INV;
2814		break;
2815	case SND_SOC_DAIFMT_IB_NF:
2816		bclk |= MADERA_AIF1_BCLK_INV;
2817		break;
2818	case SND_SOC_DAIFMT_NB_IF:
2819		lrclk |= MADERA_AIF1TX_LRCLK_INV;
2820		break;
2821	default:
2822		madera_aif_err(dai, "Unsupported invert mode %d\n",
2823			       fmt & SND_SOC_DAIFMT_INV_MASK);
2824		return -EINVAL;
2825	}
2826
2827	regmap_update_bits(madera->regmap, base + MADERA_AIF_BCLK_CTRL,
2828			   MADERA_AIF1_BCLK_INV | MADERA_AIF1_BCLK_MSTR,
2829			   bclk);
2830	regmap_update_bits(madera->regmap, base + MADERA_AIF_TX_PIN_CTRL,
2831			   MADERA_AIF1TX_LRCLK_INV | MADERA_AIF1TX_LRCLK_MSTR,
2832			   lrclk);
2833	regmap_update_bits(madera->regmap, base + MADERA_AIF_RX_PIN_CTRL,
2834			   MADERA_AIF1RX_LRCLK_INV | MADERA_AIF1RX_LRCLK_MSTR,
2835			   lrclk);
2836	regmap_update_bits(madera->regmap, base + MADERA_AIF_FORMAT,
2837			   MADERA_AIF1_FMT_MASK, mode);
2838
2839	return 0;
2840}
2841
2842static const int madera_48k_bclk_rates[] = {
2843	-1,
2844	48000,
2845	64000,
2846	96000,
2847	128000,
2848	192000,
2849	256000,
2850	384000,
2851	512000,
2852	768000,
2853	1024000,
2854	1536000,
2855	2048000,
2856	3072000,
2857	4096000,
2858	6144000,
2859	8192000,
2860	12288000,
2861	24576000,
2862};
2863
2864static const int madera_44k1_bclk_rates[] = {
2865	-1,
2866	44100,
2867	58800,
2868	88200,
2869	117600,
2870	177640,
2871	235200,
2872	352800,
2873	470400,
2874	705600,
2875	940800,
2876	1411200,
2877	1881600,
2878	2822400,
2879	3763200,
2880	5644800,
2881	7526400,
2882	11289600,
2883	22579200,
2884};
2885
2886static const unsigned int madera_sr_vals[] = {
2887	0,
2888	12000,
2889	24000,
2890	48000,
2891	96000,
2892	192000,
2893	384000,
2894	768000,
2895	0,
2896	11025,
2897	22050,
2898	44100,
2899	88200,
2900	176400,
2901	352800,
2902	705600,
2903	4000,
2904	8000,
2905	16000,
2906	32000,
2907	64000,
2908	128000,
2909	256000,
2910	512000,
2911};
2912
2913#define MADERA_192K_48K_RATE_MASK	0x0F003E
2914#define MADERA_192K_44K1_RATE_MASK	0x003E00
2915#define MADERA_192K_RATE_MASK		(MADERA_192K_48K_RATE_MASK | \
2916					 MADERA_192K_44K1_RATE_MASK)
2917#define MADERA_384K_48K_RATE_MASK	0x0F007E
2918#define MADERA_384K_44K1_RATE_MASK	0x007E00
2919#define MADERA_384K_RATE_MASK		(MADERA_384K_48K_RATE_MASK | \
2920					 MADERA_384K_44K1_RATE_MASK)
2921
2922static const struct snd_pcm_hw_constraint_list madera_constraint = {
2923	.count	= ARRAY_SIZE(madera_sr_vals),
2924	.list	= madera_sr_vals,
2925};
2926
2927static int madera_startup(struct snd_pcm_substream *substream,
2928			  struct snd_soc_dai *dai)
2929{
2930	struct snd_soc_component *component = dai->component;
2931	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2932	struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
2933	struct madera *madera = priv->madera;
2934	unsigned int base_rate;
2935
2936	if (!substream->runtime)
2937		return 0;
2938
2939	switch (dai_priv->clk) {
2940	case MADERA_CLK_SYSCLK_1:
2941	case MADERA_CLK_SYSCLK_2:
2942	case MADERA_CLK_SYSCLK_3:
2943		base_rate = priv->sysclk;
2944		break;
2945	case MADERA_CLK_ASYNCCLK_1:
2946	case MADERA_CLK_ASYNCCLK_2:
2947		base_rate = priv->asyncclk;
2948		break;
2949	default:
2950		return 0;
2951	}
2952
2953	switch (madera->type) {
2954	case CS42L92:
2955	case CS47L92:
2956	case CS47L93:
2957		if (base_rate == 0)
2958			dai_priv->constraint.mask = MADERA_384K_RATE_MASK;
2959		else if (base_rate % 4000)
2960			dai_priv->constraint.mask = MADERA_384K_44K1_RATE_MASK;
2961		else
2962			dai_priv->constraint.mask = MADERA_384K_48K_RATE_MASK;
2963		break;
2964	default:
2965		if (base_rate == 0)
2966			dai_priv->constraint.mask = MADERA_192K_RATE_MASK;
2967		else if (base_rate % 4000)
2968			dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK;
2969		else
2970			dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK;
2971		break;
2972	}
2973
2974	return snd_pcm_hw_constraint_list(substream->runtime, 0,
2975					  SNDRV_PCM_HW_PARAM_RATE,
2976					  &dai_priv->constraint);
2977}
2978
2979static int madera_hw_params_rate(struct snd_pcm_substream *substream,
2980				 struct snd_pcm_hw_params *params,
2981				 struct snd_soc_dai *dai)
2982{
2983	struct snd_soc_component *component = dai->component;
2984	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2985	struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
2986	int base = dai->driver->base;
2987	int i, sr_val;
2988	unsigned int reg, cur, tar;
2989	int ret;
2990
2991	for (i = 0; i < ARRAY_SIZE(madera_sr_vals); i++)
2992		if (madera_sr_vals[i] == params_rate(params))
2993			break;
2994
2995	if (i == ARRAY_SIZE(madera_sr_vals)) {
2996		madera_aif_err(dai, "Unsupported sample rate %dHz\n",
2997			       params_rate(params));
2998		return -EINVAL;
2999	}
3000	sr_val = i;
3001
3002	switch (dai_priv->clk) {
3003	case MADERA_CLK_SYSCLK_1:
3004		reg = MADERA_SAMPLE_RATE_1;
3005		tar = 0 << MADERA_AIF1_RATE_SHIFT;
3006		break;
3007	case MADERA_CLK_SYSCLK_2:
3008		reg = MADERA_SAMPLE_RATE_2;
3009		tar = 1 << MADERA_AIF1_RATE_SHIFT;
3010		break;
3011	case MADERA_CLK_SYSCLK_3:
3012		reg = MADERA_SAMPLE_RATE_3;
3013		tar = 2 << MADERA_AIF1_RATE_SHIFT;
3014		break;
3015	case MADERA_CLK_ASYNCCLK_1:
3016		reg = MADERA_ASYNC_SAMPLE_RATE_1;
3017		tar = 8 << MADERA_AIF1_RATE_SHIFT;
3018		break;
3019	case MADERA_CLK_ASYNCCLK_2:
3020		reg = MADERA_ASYNC_SAMPLE_RATE_2;
3021		tar = 9 << MADERA_AIF1_RATE_SHIFT;
3022		break;
3023	default:
3024		madera_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
3025		return -EINVAL;
3026	}
3027
3028	snd_soc_component_update_bits(component, reg, MADERA_SAMPLE_RATE_1_MASK,
3029				      sr_val);
3030
3031	if (!base)
3032		return 0;
3033
3034	ret = regmap_read(priv->madera->regmap,
3035			  base + MADERA_AIF_RATE_CTRL, &cur);
3036	if (ret != 0) {
3037		madera_aif_err(dai, "Failed to check rate: %d\n", ret);
3038		return ret;
3039	}
3040
3041	if ((cur & MADERA_AIF1_RATE_MASK) == (tar & MADERA_AIF1_RATE_MASK))
3042		return 0;
3043
3044	mutex_lock(&priv->rate_lock);
3045
3046	if (!madera_can_change_grp_rate(priv, base + MADERA_AIF_RATE_CTRL)) {
3047		madera_aif_warn(dai, "Cannot change rate while active\n");
3048		ret = -EBUSY;
3049		goto out;
3050	}
3051
3052	/* Guard the rate change with SYSCLK cycles */
3053	madera_spin_sysclk(priv);
3054	snd_soc_component_update_bits(component, base + MADERA_AIF_RATE_CTRL,
3055				      MADERA_AIF1_RATE_MASK, tar);
3056	madera_spin_sysclk(priv);
3057
3058out:
3059	mutex_unlock(&priv->rate_lock);
3060
3061	return ret;
3062}
3063
3064static int madera_aif_cfg_changed(struct snd_soc_component *component,
3065				  int base, int bclk, int lrclk, int frame)
3066{
3067	unsigned int val;
3068
3069	val = snd_soc_component_read(component, base + MADERA_AIF_BCLK_CTRL);
3070	if (bclk != (val & MADERA_AIF1_BCLK_FREQ_MASK))
3071		return 1;
3072
3073	val = snd_soc_component_read(component, base + MADERA_AIF_RX_BCLK_RATE);
3074	if (lrclk != (val & MADERA_AIF1RX_BCPF_MASK))
3075		return 1;
3076
3077	val = snd_soc_component_read(component, base + MADERA_AIF_FRAME_CTRL_1);
3078	if (frame != (val & (MADERA_AIF1TX_WL_MASK |
3079			     MADERA_AIF1TX_SLOT_LEN_MASK)))
3080		return 1;
3081
3082	return 0;
3083}
3084
3085static int madera_hw_params(struct snd_pcm_substream *substream,
3086			    struct snd_pcm_hw_params *params,
3087			    struct snd_soc_dai *dai)
3088{
3089	struct snd_soc_component *component = dai->component;
3090	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3091	struct madera *madera = priv->madera;
3092	int base = dai->driver->base;
3093	const int *rates;
3094	int i, ret;
3095	unsigned int val;
3096	unsigned int channels = params_channels(params);
3097	unsigned int rate = params_rate(params);
3098	unsigned int chan_limit =
3099			madera->pdata.codec.max_channels_clocked[dai->id - 1];
3100	int tdm_width = priv->tdm_width[dai->id - 1];
3101	int tdm_slots = priv->tdm_slots[dai->id - 1];
3102	int bclk, lrclk, wl, frame, bclk_target, num_rates;
3103	int reconfig;
3104	unsigned int aif_tx_state = 0, aif_rx_state = 0;
3105
3106	if (rate % 4000) {
3107		rates = &madera_44k1_bclk_rates[0];
3108		num_rates = ARRAY_SIZE(madera_44k1_bclk_rates);
3109	} else {
3110		rates = &madera_48k_bclk_rates[0];
3111		num_rates = ARRAY_SIZE(madera_48k_bclk_rates);
3112	}
3113
3114	wl = snd_pcm_format_width(params_format(params));
3115
3116	if (tdm_slots) {
3117		madera_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
3118			       tdm_slots, tdm_width);
3119		bclk_target = tdm_slots * tdm_width * rate;
3120		channels = tdm_slots;
3121	} else {
3122		bclk_target = snd_soc_params_to_bclk(params);
3123		tdm_width = wl;
3124	}
3125
3126	if (chan_limit && chan_limit < channels) {
3127		madera_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
3128		bclk_target /= channels;
3129		bclk_target *= chan_limit;
3130	}
3131
3132	/* Force multiple of 2 channels for I2S mode */
3133	val = snd_soc_component_read(component, base + MADERA_AIF_FORMAT);
3134	val &= MADERA_AIF1_FMT_MASK;
3135	if ((channels & 1) && val == MADERA_FMT_I2S_MODE) {
3136		madera_aif_dbg(dai, "Forcing stereo mode\n");
3137		bclk_target /= channels;
3138		bclk_target *= channels + 1;
3139	}
3140
3141	for (i = 0; i < num_rates; i++) {
3142		if (rates[i] >= bclk_target && rates[i] % rate == 0) {
3143			bclk = i;
3144			break;
3145		}
3146	}
3147
3148	if (i == num_rates) {
3149		madera_aif_err(dai, "Unsupported sample rate %dHz\n", rate);
3150		return -EINVAL;
3151	}
3152
3153	lrclk = rates[bclk] / rate;
3154
3155	madera_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
3156		       rates[bclk], rates[bclk] / lrclk);
3157
3158	frame = wl << MADERA_AIF1TX_WL_SHIFT | tdm_width;
3159
3160	reconfig = madera_aif_cfg_changed(component, base, bclk, lrclk, frame);
3161	if (reconfig < 0)
3162		return reconfig;
3163
3164	if (reconfig) {
3165		/* Save AIF TX/RX state */
3166		regmap_read(madera->regmap, base + MADERA_AIF_TX_ENABLES,
3167			    &aif_tx_state);
3168		regmap_read(madera->regmap, base + MADERA_AIF_RX_ENABLES,
3169			    &aif_rx_state);
3170		/* Disable AIF TX/RX before reconfiguring it */
3171		regmap_update_bits(madera->regmap,
3172				   base + MADERA_AIF_TX_ENABLES, 0xff, 0x0);
3173		regmap_update_bits(madera->regmap,
3174				   base + MADERA_AIF_RX_ENABLES, 0xff, 0x0);
3175	}
3176
3177	ret = madera_hw_params_rate(substream, params, dai);
3178	if (ret != 0)
3179		goto restore_aif;
3180
3181	if (reconfig) {
3182		regmap_update_bits(madera->regmap,
3183				   base + MADERA_AIF_BCLK_CTRL,
3184				   MADERA_AIF1_BCLK_FREQ_MASK, bclk);
3185		regmap_update_bits(madera->regmap,
3186				   base + MADERA_AIF_RX_BCLK_RATE,
3187				   MADERA_AIF1RX_BCPF_MASK, lrclk);
3188		regmap_update_bits(madera->regmap,
3189				   base + MADERA_AIF_FRAME_CTRL_1,
3190				   MADERA_AIF1TX_WL_MASK |
3191				   MADERA_AIF1TX_SLOT_LEN_MASK, frame);
3192		regmap_update_bits(madera->regmap,
3193				   base + MADERA_AIF_FRAME_CTRL_2,
3194				   MADERA_AIF1RX_WL_MASK |
3195				   MADERA_AIF1RX_SLOT_LEN_MASK, frame);
3196	}
3197
3198restore_aif:
3199	if (reconfig) {
3200		/* Restore AIF TX/RX state */
3201		regmap_update_bits(madera->regmap,
3202				   base + MADERA_AIF_TX_ENABLES,
3203				   0xff, aif_tx_state);
3204		regmap_update_bits(madera->regmap,
3205				   base + MADERA_AIF_RX_ENABLES,
3206				   0xff, aif_rx_state);
3207	}
3208
3209	return ret;
3210}
3211
3212static int madera_is_syncclk(int clk_id)
3213{
3214	switch (clk_id) {
3215	case MADERA_CLK_SYSCLK_1:
3216	case MADERA_CLK_SYSCLK_2:
3217	case MADERA_CLK_SYSCLK_3:
3218		return 1;
3219	case MADERA_CLK_ASYNCCLK_1:
3220	case MADERA_CLK_ASYNCCLK_2:
3221		return 0;
3222	default:
3223		return -EINVAL;
3224	}
3225}
3226
3227static int madera_dai_set_sysclk(struct snd_soc_dai *dai,
3228				 int clk_id, unsigned int freq, int dir)
3229{
3230	struct snd_soc_component *component = dai->component;
3231	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
3232	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3233	struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
3234	struct snd_soc_dapm_route routes[2];
3235	int is_sync;
3236
3237	is_sync = madera_is_syncclk(clk_id);
3238	if (is_sync < 0) {
3239		dev_err(component->dev, "Illegal DAI clock id %d\n", clk_id);
3240		return is_sync;
3241	}
3242
3243	if (is_sync == madera_is_syncclk(dai_priv->clk))
3244		return 0;
3245
3246	if (snd_soc_dai_active(dai)) {
3247		dev_err(component->dev, "Can't change clock on active DAI %d\n",
3248			dai->id);
3249		return -EBUSY;
3250	}
3251
3252	dev_dbg(component->dev, "Setting AIF%d to %s\n", dai->id,
3253		is_sync ? "SYSCLK" : "ASYNCCLK");
3254
3255	/*
3256	 * A connection to SYSCLK is always required, we only add and remove
3257	 * a connection to ASYNCCLK
3258	 */
3259	memset(&routes, 0, sizeof(routes));
3260	routes[0].sink = dai->driver->capture.stream_name;
3261	routes[1].sink = dai->driver->playback.stream_name;
3262	routes[0].source = "ASYNCCLK";
3263	routes[1].source = "ASYNCCLK";
3264
3265	if (is_sync)
3266		snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes));
3267	else
3268		snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
3269
3270	dai_priv->clk = clk_id;
3271
3272	return snd_soc_dapm_sync(dapm);
3273}
3274
3275static int madera_set_tristate(struct snd_soc_dai *dai, int tristate)
3276{
3277	struct snd_soc_component *component = dai->component;
3278	int base = dai->driver->base;
3279	unsigned int reg;
3280	int ret;
3281
3282	if (tristate)
3283		reg = MADERA_AIF1_TRI;
3284	else
3285		reg = 0;
3286
3287	ret = snd_soc_component_update_bits(component,
3288					    base + MADERA_AIF_RATE_CTRL,
3289					    MADERA_AIF1_TRI, reg);
3290	if (ret < 0)
3291		return ret;
3292	else
3293		return 0;
3294}
3295
3296static void madera_set_channels_to_mask(struct snd_soc_dai *dai,
3297					unsigned int base,
3298					int channels, unsigned int mask)
3299{
3300	struct snd_soc_component *component = dai->component;
3301	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3302	struct madera *madera = priv->madera;
3303	int slot, i;
3304
3305	for (i = 0; i < channels; ++i) {
3306		slot = ffs(mask) - 1;
3307		if (slot < 0)
3308			return;
3309
3310		regmap_write(madera->regmap, base + i, slot);
3311
3312		mask &= ~(1 << slot);
3313	}
3314
3315	if (mask)
3316		madera_aif_warn(dai, "Too many channels in TDM mask\n");
3317}
3318
3319static int madera_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
3320			       unsigned int rx_mask, int slots, int slot_width)
3321{
3322	struct snd_soc_component *component = dai->component;
3323	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3324	int base = dai->driver->base;
3325	int rx_max_chan = dai->driver->playback.channels_max;
3326	int tx_max_chan = dai->driver->capture.channels_max;
3327
3328	/* Only support TDM for the physical AIFs */
3329	if (dai->id > MADERA_MAX_AIF)
3330		return -ENOTSUPP;
3331
3332	if (slots == 0) {
3333		tx_mask = (1 << tx_max_chan) - 1;
3334		rx_mask = (1 << rx_max_chan) - 1;
3335	}
3336
3337	madera_set_channels_to_mask(dai, base + MADERA_AIF_FRAME_CTRL_3,
3338				    tx_max_chan, tx_mask);
3339	madera_set_channels_to_mask(dai, base + MADERA_AIF_FRAME_CTRL_11,
3340				    rx_max_chan, rx_mask);
3341
3342	priv->tdm_width[dai->id - 1] = slot_width;
3343	priv->tdm_slots[dai->id - 1] = slots;
3344
3345	return 0;
3346}
3347
3348const struct snd_soc_dai_ops madera_dai_ops = {
3349	.startup = &madera_startup,
3350	.set_fmt = &madera_set_fmt,
3351	.set_tdm_slot = &madera_set_tdm_slot,
3352	.hw_params = &madera_hw_params,
3353	.set_sysclk = &madera_dai_set_sysclk,
3354	.set_tristate = &madera_set_tristate,
3355};
3356EXPORT_SYMBOL_GPL(madera_dai_ops);
3357
3358const struct snd_soc_dai_ops madera_simple_dai_ops = {
3359	.startup = &madera_startup,
3360	.hw_params = &madera_hw_params_rate,
3361	.set_sysclk = &madera_dai_set_sysclk,
3362};
3363EXPORT_SYMBOL_GPL(madera_simple_dai_ops);
3364
3365int madera_init_dai(struct madera_priv *priv, int id)
3366{
3367	struct madera_dai_priv *dai_priv = &priv->dai[id];
3368
3369	dai_priv->clk = MADERA_CLK_SYSCLK_1;
3370	dai_priv->constraint = madera_constraint;
3371
3372	return 0;
3373}
3374EXPORT_SYMBOL_GPL(madera_init_dai);
3375
3376static const struct {
3377	unsigned int min;
3378	unsigned int max;
3379	u16 fratio;
3380	int ratio;
3381} fll_sync_fratios[] = {
3382	{       0,    64000, 4, 16 },
3383	{   64000,   128000, 3,  8 },
3384	{  128000,   256000, 2,  4 },
3385	{  256000,  1000000, 1,  2 },
3386	{ 1000000, 13500000, 0,  1 },
3387};
3388
3389static const unsigned int pseudo_fref_max[MADERA_FLL_MAX_FRATIO] = {
3390	13500000,
3391	 6144000,
3392	 6144000,
3393	 3072000,
3394	 3072000,
3395	 2822400,
3396	 2822400,
3397	 1536000,
3398	 1536000,
3399	 1536000,
3400	 1536000,
3401	 1536000,
3402	 1536000,
3403	 1536000,
3404	 1536000,
3405	  768000,
3406};
3407
3408struct madera_fll_gains {
3409	unsigned int min;
3410	unsigned int max;
3411	int gain;		/* main gain */
3412	int alt_gain;		/* alternate integer gain */
3413};
3414
3415static const struct madera_fll_gains madera_fll_sync_gains[] = {
3416	{       0,   256000, 0, -1 },
3417	{  256000,  1000000, 2, -1 },
3418	{ 1000000, 13500000, 4, -1 },
3419};
3420
3421static const struct madera_fll_gains madera_fll_main_gains[] = {
3422	{       0,   100000, 0, 2 },
3423	{  100000,   375000, 2, 2 },
3424	{  375000,   768000, 3, 2 },
3425	{  768001,  1500000, 3, 3 },
3426	{ 1500000,  6000000, 4, 3 },
3427	{ 6000000, 13500000, 5, 3 },
3428};
3429
3430static int madera_find_sync_fratio(unsigned int fref, int *fratio)
3431{
3432	int i;
3433
3434	for (i = 0; i < ARRAY_SIZE(fll_sync_fratios); i++) {
3435		if (fll_sync_fratios[i].min <= fref &&
3436		    fref <= fll_sync_fratios[i].max) {
3437			if (fratio)
3438				*fratio = fll_sync_fratios[i].fratio;
3439
3440			return fll_sync_fratios[i].ratio;
3441		}
3442	}
3443
3444	return -EINVAL;
3445}
3446
3447static int madera_find_main_fratio(unsigned int fref, unsigned int fout,
3448				   int *fratio)
3449{
3450	int ratio = 1;
3451
3452	while ((fout / (ratio * fref)) > MADERA_FLL_MAX_N)
3453		ratio++;
3454
3455	if (fratio)
3456		*fratio = ratio - 1;
3457
3458	return ratio;
3459}
3460
3461static int madera_find_fratio(struct madera_fll *fll, unsigned int fref,
3462			      bool sync, int *fratio)
3463{
3464	switch (fll->madera->type) {
3465	case CS47L35:
3466		switch (fll->madera->rev) {
3467		case 0:
3468			/* rev A0 uses sync calculation for both loops */
3469			return madera_find_sync_fratio(fref, fratio);
3470		default:
3471			if (sync)
3472				return madera_find_sync_fratio(fref, fratio);
3473			else
3474				return madera_find_main_fratio(fref,
3475							       fll->fout,
3476							       fratio);
3477		}
3478		break;
3479	case CS47L85:
3480	case WM1840:
3481		/* these use the same calculation for main and sync loops */
3482		return madera_find_sync_fratio(fref, fratio);
3483	default:
3484		if (sync)
3485			return madera_find_sync_fratio(fref, fratio);
3486		else
3487			return madera_find_main_fratio(fref, fll->fout, fratio);
3488	}
3489}
3490
3491static int madera_calc_fratio(struct madera_fll *fll,
3492			      struct madera_fll_cfg *cfg,
3493			      unsigned int fref, bool sync)
3494{
3495	int init_ratio, ratio;
3496	int refdiv, div;
3497
3498	/* fref must be <=13.5MHz, find initial refdiv */
3499	div = 1;
3500	cfg->refdiv = 0;
3501	while (fref > MADERA_FLL_MAX_FREF) {
3502		div *= 2;
3503		fref /= 2;
3504		cfg->refdiv++;
3505
3506		if (div > MADERA_FLL_MAX_REFDIV)
3507			return -EINVAL;
3508	}
3509
3510	/* Find an appropriate FLL_FRATIO */
3511	init_ratio = madera_find_fratio(fll, fref, sync, &cfg->fratio);
3512	if (init_ratio < 0) {
3513		madera_fll_err(fll, "Unable to find FRATIO for fref=%uHz\n",
3514			       fref);
3515		return init_ratio;
3516	}
3517
3518	if (!sync)
3519		cfg->fratio = init_ratio - 1;
3520
3521	switch (fll->madera->type) {
3522	case CS47L35:
3523		switch (fll->madera->rev) {
3524		case 0:
3525			if (sync)
3526				return init_ratio;
3527			break;
3528		default:
3529			return init_ratio;
3530		}
3531		break;
3532	case CS47L85:
3533	case WM1840:
3534		if (sync)
3535			return init_ratio;
3536		break;
3537	default:
3538		return init_ratio;
3539	}
3540
3541	/*
3542	 * For CS47L35 rev A0, CS47L85 and WM1840 adjust FRATIO/refdiv to avoid
3543	 * integer mode if possible
3544	 */
3545	refdiv = cfg->refdiv;
3546
3547	while (div <= MADERA_FLL_MAX_REFDIV) {
3548		/*
3549		 * start from init_ratio because this may already give a
3550		 * fractional N.K
3551		 */
3552		for (ratio = init_ratio; ratio > 0; ratio--) {
3553			if (fll->fout % (ratio * fref)) {
3554				cfg->refdiv = refdiv;
3555				cfg->fratio = ratio - 1;
3556				return ratio;
3557			}
3558		}
3559
3560		for (ratio = init_ratio + 1; ratio <= MADERA_FLL_MAX_FRATIO;
3561		     ratio++) {
3562			if ((MADERA_FLL_VCO_CORNER / 2) /
3563			    (MADERA_FLL_VCO_MULT * ratio) < fref)
3564				break;
3565
3566			if (fref > pseudo_fref_max[ratio - 1])
3567				break;
3568
3569			if (fll->fout % (ratio * fref)) {
3570				cfg->refdiv = refdiv;
3571				cfg->fratio = ratio - 1;
3572				return ratio;
3573			}
3574		}
3575
3576		div *= 2;
3577		fref /= 2;
3578		refdiv++;
3579		init_ratio = madera_find_fratio(fll, fref, sync, NULL);
3580	}
3581
3582	madera_fll_warn(fll, "Falling back to integer mode operation\n");
3583
3584	return cfg->fratio + 1;
3585}
3586
3587static int madera_find_fll_gain(struct madera_fll *fll,
3588				struct madera_fll_cfg *cfg,
3589				unsigned int fref,
3590				const struct madera_fll_gains *gains,
3591				int n_gains)
3592{
3593	int i;
3594
3595	for (i = 0; i < n_gains; i++) {
3596		if (gains[i].min <= fref && fref <= gains[i].max) {
3597			cfg->gain = gains[i].gain;
3598			cfg->alt_gain = gains[i].alt_gain;
3599			return 0;
3600		}
3601	}
3602
3603	madera_fll_err(fll, "Unable to find gain for fref=%uHz\n", fref);
3604
3605	return -EINVAL;
3606}
3607
3608static int madera_calc_fll(struct madera_fll *fll,
3609			   struct madera_fll_cfg *cfg,
3610			   unsigned int fref, bool sync)
3611{
3612	unsigned int gcd_fll;
3613	const struct madera_fll_gains *gains;
3614	int n_gains;
3615	int ratio, ret;
3616
3617	madera_fll_dbg(fll, "fref=%u Fout=%u fvco=%u\n",
3618		       fref, fll->fout, fll->fout * MADERA_FLL_VCO_MULT);
3619
3620	/* Find an appropriate FLL_FRATIO and refdiv */
3621	ratio = madera_calc_fratio(fll, cfg, fref, sync);
3622	if (ratio < 0)
3623		return ratio;
3624
3625	/* Apply the division for our remaining calculations */
3626	fref = fref / (1 << cfg->refdiv);
3627
3628	cfg->n = fll->fout / (ratio * fref);
3629
3630	if (fll->fout % (ratio * fref)) {
3631		gcd_fll = gcd(fll->fout, ratio * fref);
3632		madera_fll_dbg(fll, "GCD=%u\n", gcd_fll);
3633
3634		cfg->theta = (fll->fout - (cfg->n * ratio * fref))
3635			/ gcd_fll;
3636		cfg->lambda = (ratio * fref) / gcd_fll;
3637	} else {
3638		cfg->theta = 0;
3639		cfg->lambda = 0;
3640	}
3641
3642	/*
3643	 * Round down to 16bit range with cost of accuracy lost.
3644	 * Denominator must be bigger than numerator so we only
3645	 * take care of it.
3646	 */
3647	while (cfg->lambda >= (1 << 16)) {
3648		cfg->theta >>= 1;
3649		cfg->lambda >>= 1;
3650	}
3651
3652	switch (fll->madera->type) {
3653	case CS47L35:
3654		switch (fll->madera->rev) {
3655		case 0:
3656			/* Rev A0 uses the sync gains for both loops */
3657			gains = madera_fll_sync_gains;
3658			n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3659			break;
3660		default:
3661			if (sync) {
3662				gains = madera_fll_sync_gains;
3663				n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3664			} else {
3665				gains = madera_fll_main_gains;
3666				n_gains = ARRAY_SIZE(madera_fll_main_gains);
3667			}
3668			break;
3669		}
3670		break;
3671	case CS47L85:
3672	case WM1840:
3673		/* These use the sync gains for both loops */
3674		gains = madera_fll_sync_gains;
3675		n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3676		break;
3677	default:
3678		if (sync) {
3679			gains = madera_fll_sync_gains;
3680			n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3681		} else {
3682			gains = madera_fll_main_gains;
3683			n_gains = ARRAY_SIZE(madera_fll_main_gains);
3684		}
3685		break;
3686	}
3687
3688	ret = madera_find_fll_gain(fll, cfg, fref, gains, n_gains);
3689	if (ret)
3690		return ret;
3691
3692	madera_fll_dbg(fll, "N=%d THETA=%d LAMBDA=%d\n",
3693		       cfg->n, cfg->theta, cfg->lambda);
3694	madera_fll_dbg(fll, "FRATIO=0x%x(%d) REFCLK_DIV=0x%x(%d)\n",
3695		       cfg->fratio, ratio, cfg->refdiv, 1 << cfg->refdiv);
3696	madera_fll_dbg(fll, "GAIN=0x%x(%d)\n", cfg->gain, 1 << cfg->gain);
3697
3698	return 0;
3699}
3700
3701static bool madera_write_fll(struct madera *madera, unsigned int base,
3702			     struct madera_fll_cfg *cfg, int source,
3703			     bool sync, int gain)
3704{
3705	bool change, fll_change;
3706
3707	fll_change = false;
3708	regmap_update_bits_check(madera->regmap,
3709				 base + MADERA_FLL_CONTROL_3_OFFS,
3710				 MADERA_FLL1_THETA_MASK,
3711				 cfg->theta, &change);
3712	fll_change |= change;
3713	regmap_update_bits_check(madera->regmap,
3714				 base + MADERA_FLL_CONTROL_4_OFFS,
3715				 MADERA_FLL1_LAMBDA_MASK,
3716				 cfg->lambda, &change);
3717	fll_change |= change;
3718	regmap_update_bits_check(madera->regmap,
3719				 base + MADERA_FLL_CONTROL_5_OFFS,
3720				 MADERA_FLL1_FRATIO_MASK,
3721				 cfg->fratio << MADERA_FLL1_FRATIO_SHIFT,
3722				 &change);
3723	fll_change |= change;
3724	regmap_update_bits_check(madera->regmap,
3725				 base + MADERA_FLL_CONTROL_6_OFFS,
3726				 MADERA_FLL1_REFCLK_DIV_MASK |
3727				 MADERA_FLL1_REFCLK_SRC_MASK,
3728				 cfg->refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT |
3729				 source << MADERA_FLL1_REFCLK_SRC_SHIFT,
3730				 &change);
3731	fll_change |= change;
3732
3733	if (sync) {
3734		regmap_update_bits_check(madera->regmap,
3735					 base + MADERA_FLL_SYNCHRONISER_7_OFFS,
3736					 MADERA_FLL1_GAIN_MASK,
3737					 gain << MADERA_FLL1_GAIN_SHIFT,
3738					 &change);
3739		fll_change |= change;
3740	} else {
3741		regmap_update_bits_check(madera->regmap,
3742					 base + MADERA_FLL_CONTROL_7_OFFS,
3743					 MADERA_FLL1_GAIN_MASK,
3744					 gain << MADERA_FLL1_GAIN_SHIFT,
3745					 &change);
3746		fll_change |= change;
3747	}
3748
3749	regmap_update_bits_check(madera->regmap,
3750				 base + MADERA_FLL_CONTROL_2_OFFS,
3751				 MADERA_FLL1_CTRL_UPD | MADERA_FLL1_N_MASK,
3752				 MADERA_FLL1_CTRL_UPD | cfg->n, &change);
3753	fll_change |= change;
3754
3755	return fll_change;
3756}
3757
3758static int madera_is_enabled_fll(struct madera_fll *fll, int base)
3759{
3760	struct madera *madera = fll->madera;
3761	unsigned int reg;
3762	int ret;
3763
3764	ret = regmap_read(madera->regmap,
3765			  base + MADERA_FLL_CONTROL_1_OFFS, &reg);
3766	if (ret != 0) {
3767		madera_fll_err(fll, "Failed to read current state: %d\n", ret);
3768		return ret;
3769	}
3770
3771	return reg & MADERA_FLL1_ENA;
3772}
3773
3774static int madera_wait_for_fll(struct madera_fll *fll, bool requested)
3775{
3776	struct madera *madera = fll->madera;
3777	unsigned int val = 0;
3778	bool status;
3779	int i;
3780
3781	madera_fll_dbg(fll, "Waiting for FLL...\n");
3782
3783	for (i = 0; i < 30; i++) {
3784		regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_2, &val);
3785		status = val & (MADERA_FLL1_LOCK_STS1 << (fll->id - 1));
3786		if (status == requested)
3787			return 0;
3788
3789		switch (i) {
3790		case 0 ... 5:
3791			usleep_range(75, 125);
3792			break;
3793		case 11 ... 20:
3794			usleep_range(750, 1250);
3795			break;
3796		default:
3797			msleep(20);
3798			break;
3799		}
3800	}
3801
3802	madera_fll_warn(fll, "Timed out waiting for lock\n");
3803
3804	return -ETIMEDOUT;
3805}
3806
3807static bool madera_set_fll_phase_integrator(struct madera_fll *fll,
3808					    struct madera_fll_cfg *ref_cfg,
3809					    bool sync)
3810{
3811	unsigned int val;
3812	bool reg_change;
3813
3814	if (!sync && ref_cfg->theta == 0)
3815		val = (1 << MADERA_FLL1_PHASE_ENA_SHIFT) |
3816		      (2 << MADERA_FLL1_PHASE_GAIN_SHIFT);
3817	else
3818		val = 2 << MADERA_FLL1_PHASE_GAIN_SHIFT;
3819
3820	regmap_update_bits_check(fll->madera->regmap,
3821				 fll->base + MADERA_FLL_EFS_2_OFFS,
3822				 MADERA_FLL1_PHASE_ENA_MASK |
3823				 MADERA_FLL1_PHASE_GAIN_MASK,
3824				 val, &reg_change);
3825
3826	return reg_change;
3827}
3828
3829static int madera_set_fll_clks_reg(struct madera_fll *fll, bool ena,
3830				   unsigned int reg, unsigned int mask,
3831				   unsigned int shift)
3832{
3833	struct madera *madera = fll->madera;
3834	unsigned int src;
3835	struct clk *clk;
3836	int ret;
3837
3838	ret = regmap_read(madera->regmap, reg, &src);
3839	if (ret != 0) {
3840		madera_fll_err(fll, "Failed to read current source: %d\n",
3841			       ret);
3842		return ret;
3843	}
3844
3845	src = (src & mask) >> shift;
3846
3847	switch (src) {
3848	case MADERA_FLL_SRC_MCLK1:
3849		clk = madera->mclk[MADERA_MCLK1].clk;
3850		break;
3851	case MADERA_FLL_SRC_MCLK2:
3852		clk = madera->mclk[MADERA_MCLK2].clk;
3853		break;
3854	case MADERA_FLL_SRC_MCLK3:
3855		clk = madera->mclk[MADERA_MCLK3].clk;
3856		break;
3857	default:
3858		return 0;
3859	}
3860
3861	if (ena) {
3862		return clk_prepare_enable(clk);
3863	} else {
3864		clk_disable_unprepare(clk);
3865		return 0;
3866	}
3867}
3868
3869static inline int madera_set_fll_clks(struct madera_fll *fll, int base, bool ena)
3870{
3871	return madera_set_fll_clks_reg(fll, ena,
3872				       base + MADERA_FLL_CONTROL_6_OFFS,
3873				       MADERA_FLL1_REFCLK_SRC_MASK,
3874				       MADERA_FLL1_REFCLK_SRC_SHIFT);
3875}
3876
3877static inline int madera_set_fllao_clks(struct madera_fll *fll, int base, bool ena)
3878{
3879	return madera_set_fll_clks_reg(fll, ena,
3880				       base + MADERA_FLLAO_CONTROL_6_OFFS,
3881				       MADERA_FLL_AO_REFCLK_SRC_MASK,
3882				       MADERA_FLL_AO_REFCLK_SRC_SHIFT);
3883}
3884
3885static inline int madera_set_fllhj_clks(struct madera_fll *fll, int base, bool ena)
3886{
3887	return madera_set_fll_clks_reg(fll, ena,
3888				       base + MADERA_FLL_CONTROL_1_OFFS,
3889				       CS47L92_FLL1_REFCLK_SRC_MASK,
3890				       CS47L92_FLL1_REFCLK_SRC_SHIFT);
3891}
3892
3893static void madera_disable_fll(struct madera_fll *fll)
3894{
3895	struct madera *madera = fll->madera;
3896	unsigned int sync_base;
3897	bool ref_change, sync_change;
3898
3899	switch (madera->type) {
3900	case CS47L35:
3901		sync_base = fll->base + CS47L35_FLL_SYNCHRONISER_OFFS;
3902		break;
3903	default:
3904		sync_base = fll->base + MADERA_FLL_SYNCHRONISER_OFFS;
3905		break;
3906	}
3907
3908	madera_fll_dbg(fll, "Disabling FLL\n");
3909
3910	regmap_update_bits(madera->regmap,
3911			   fll->base + MADERA_FLL_CONTROL_1_OFFS,
3912			   MADERA_FLL1_FREERUN, MADERA_FLL1_FREERUN);
3913	regmap_update_bits_check(madera->regmap,
3914				 fll->base + MADERA_FLL_CONTROL_1_OFFS,
3915				 MADERA_FLL1_ENA, 0, &ref_change);
3916	regmap_update_bits_check(madera->regmap,
3917				 sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
3918				 MADERA_FLL1_SYNC_ENA, 0, &sync_change);
3919	regmap_update_bits(madera->regmap,
3920			   fll->base + MADERA_FLL_CONTROL_1_OFFS,
3921			   MADERA_FLL1_FREERUN, 0);
3922
3923	madera_wait_for_fll(fll, false);
3924
3925	if (sync_change)
3926		madera_set_fll_clks(fll, sync_base, false);
3927
3928	if (ref_change) {
3929		madera_set_fll_clks(fll, fll->base, false);
3930		pm_runtime_put_autosuspend(madera->dev);
3931	}
3932}
3933
3934static int madera_enable_fll(struct madera_fll *fll)
3935{
3936	struct madera *madera = fll->madera;
3937	bool have_sync = false;
3938	int already_enabled = madera_is_enabled_fll(fll, fll->base);
3939	int sync_enabled;
3940	struct madera_fll_cfg cfg;
3941	unsigned int sync_base;
3942	int gain, ret;
3943	bool fll_change = false;
3944
3945	if (already_enabled < 0)
3946		return already_enabled;	/* error getting current state */
3947
3948	if (fll->ref_src < 0 || fll->ref_freq == 0) {
3949		madera_fll_err(fll, "No REFCLK\n");
3950		ret = -EINVAL;
3951		goto err;
3952	}
3953
3954	madera_fll_dbg(fll, "Enabling FLL, initially %s\n",
3955		       str_enabled_disabled(already_enabled));
3956
3957	if (fll->fout < MADERA_FLL_MIN_FOUT ||
3958	    fll->fout > MADERA_FLL_MAX_FOUT) {
3959		madera_fll_err(fll, "invalid fout %uHz\n", fll->fout);
3960		ret = -EINVAL;
3961		goto err;
3962	}
3963
3964	switch (madera->type) {
3965	case CS47L35:
3966		sync_base = fll->base + CS47L35_FLL_SYNCHRONISER_OFFS;
3967		break;
3968	default:
3969		sync_base = fll->base + MADERA_FLL_SYNCHRONISER_OFFS;
3970		break;
3971	}
3972
3973	sync_enabled = madera_is_enabled_fll(fll, sync_base);
3974	if (sync_enabled < 0)
3975		return sync_enabled;
3976
3977	if (already_enabled) {
3978		/* Facilitate smooth refclk across the transition */
3979		regmap_update_bits(fll->madera->regmap,
3980				   fll->base + MADERA_FLL_CONTROL_1_OFFS,
3981				   MADERA_FLL1_FREERUN,
3982				   MADERA_FLL1_FREERUN);
3983		udelay(32);
3984		regmap_update_bits(fll->madera->regmap,
3985				   fll->base + MADERA_FLL_CONTROL_7_OFFS,
3986				   MADERA_FLL1_GAIN_MASK, 0);
3987
3988		if (sync_enabled > 0)
3989			madera_set_fll_clks(fll, sync_base, false);
3990		madera_set_fll_clks(fll, fll->base, false);
3991	}
3992
3993	/* Apply SYNCCLK setting */
3994	if (fll->sync_src >= 0) {
3995		ret = madera_calc_fll(fll, &cfg, fll->sync_freq, true);
3996		if (ret < 0)
3997			goto err;
3998
3999		fll_change |= madera_write_fll(madera, sync_base,
4000					       &cfg, fll->sync_src,
4001					       true, cfg.gain);
4002		have_sync = true;
4003	}
4004
4005	if (already_enabled && !!sync_enabled != have_sync)
4006		madera_fll_warn(fll, "Synchroniser changed on active FLL\n");
4007
4008	/* Apply REFCLK setting */
4009	ret = madera_calc_fll(fll, &cfg, fll->ref_freq, false);
4010	if (ret < 0)
4011		goto err;
4012
4013	/* Ref path hardcodes lambda to 65536 when sync is on */
4014	if (have_sync && cfg.lambda)
4015		cfg.theta = (cfg.theta * (1 << 16)) / cfg.lambda;
4016
4017	switch (fll->madera->type) {
4018	case CS47L35:
4019		switch (fll->madera->rev) {
4020		case 0:
4021			gain = cfg.gain;
4022			break;
4023		default:
4024			fll_change |=
4025				madera_set_fll_phase_integrator(fll, &cfg,
4026								have_sync);
4027			if (!have_sync && cfg.theta == 0)
4028				gain = cfg.alt_gain;
4029			else
4030				gain = cfg.gain;
4031			break;
4032		}
4033		break;
4034	case CS47L85:
4035	case WM1840:
4036		gain = cfg.gain;
4037		break;
4038	default:
4039		fll_change |= madera_set_fll_phase_integrator(fll, &cfg,
4040							      have_sync);
4041		if (!have_sync && cfg.theta == 0)
4042			gain = cfg.alt_gain;
4043		else
4044			gain = cfg.gain;
4045		break;
4046	}
4047
4048	fll_change |= madera_write_fll(madera, fll->base,
4049				       &cfg, fll->ref_src,
4050				       false, gain);
4051
4052	/*
4053	 * Increase the bandwidth if we're not using a low frequency
4054	 * sync source.
4055	 */
4056	if (have_sync && fll->sync_freq > 100000)
4057		regmap_update_bits(madera->regmap,
4058				   sync_base + MADERA_FLL_SYNCHRONISER_7_OFFS,
4059				   MADERA_FLL1_SYNC_DFSAT_MASK, 0);
4060	else
4061		regmap_update_bits(madera->regmap,
4062				   sync_base + MADERA_FLL_SYNCHRONISER_7_OFFS,
4063				   MADERA_FLL1_SYNC_DFSAT_MASK,
4064				   MADERA_FLL1_SYNC_DFSAT);
4065
4066	if (!already_enabled)
4067		pm_runtime_get_sync(madera->dev);
4068
4069	if (have_sync) {
4070		madera_set_fll_clks(fll, sync_base, true);
4071		regmap_update_bits(madera->regmap,
4072				   sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
4073				   MADERA_FLL1_SYNC_ENA,
4074				   MADERA_FLL1_SYNC_ENA);
4075	}
4076
4077	madera_set_fll_clks(fll, fll->base, true);
4078	regmap_update_bits(madera->regmap,
4079			   fll->base + MADERA_FLL_CONTROL_1_OFFS,
4080			   MADERA_FLL1_ENA, MADERA_FLL1_ENA);
4081
4082	if (already_enabled)
4083		regmap_update_bits(madera->regmap,
4084				   fll->base + MADERA_FLL_CONTROL_1_OFFS,
4085				   MADERA_FLL1_FREERUN, 0);
4086
4087	if (fll_change || !already_enabled)
4088		madera_wait_for_fll(fll, true);
4089
4090	return 0;
4091
4092err:
4093	 /* In case of error don't leave the FLL running with an old config */
4094	madera_disable_fll(fll);
4095
4096	return ret;
4097}
4098
4099static int madera_apply_fll(struct madera_fll *fll)
4100{
4101	if (fll->fout) {
4102		return madera_enable_fll(fll);
4103	} else {
4104		madera_disable_fll(fll);
4105		return 0;
4106	}
4107}
4108
4109int madera_set_fll_syncclk(struct madera_fll *fll, int source,
4110			   unsigned int fref, unsigned int fout)
4111{
4112	/*
4113	 * fout is ignored, since the synchronizer is an optional extra
4114	 * constraint on the Fout generated from REFCLK, so the Fout is
4115	 * set when configuring REFCLK
4116	 */
4117
4118	if (fll->sync_src == source && fll->sync_freq == fref)
4119		return 0;
4120
4121	fll->sync_src = source;
4122	fll->sync_freq = fref;
4123
4124	return madera_apply_fll(fll);
4125}
4126EXPORT_SYMBOL_GPL(madera_set_fll_syncclk);
4127
4128int madera_set_fll_refclk(struct madera_fll *fll, int source,
4129			  unsigned int fref, unsigned int fout)
4130{
4131	int ret;
4132
4133	if (fll->ref_src == source &&
4134	    fll->ref_freq == fref && fll->fout == fout)
4135		return 0;
4136
4137	/*
4138	 * Changes of fout on an enabled FLL aren't allowed except when
4139	 * setting fout==0 to disable the FLL
4140	 */
4141	if (fout && fout != fll->fout) {
4142		ret = madera_is_enabled_fll(fll, fll->base);
4143		if (ret < 0)
4144			return ret;
4145
4146		if (ret) {
4147			madera_fll_err(fll, "Can't change Fout on active FLL\n");
4148			return -EBUSY;
4149		}
4150	}
4151
4152	fll->ref_src = source;
4153	fll->ref_freq = fref;
4154	fll->fout = fout;
4155
4156	return madera_apply_fll(fll);
4157}
4158EXPORT_SYMBOL_GPL(madera_set_fll_refclk);
4159
4160int madera_init_fll(struct madera *madera, int id, int base,
4161		    struct madera_fll *fll)
4162{
4163	fll->id = id;
4164	fll->base = base;
4165	fll->madera = madera;
4166	fll->ref_src = MADERA_FLL_SRC_NONE;
4167	fll->sync_src = MADERA_FLL_SRC_NONE;
4168
4169	regmap_update_bits(madera->regmap,
4170			   fll->base + MADERA_FLL_CONTROL_1_OFFS,
4171			   MADERA_FLL1_FREERUN, 0);
4172
4173	return 0;
4174}
4175EXPORT_SYMBOL_GPL(madera_init_fll);
4176
4177static const struct reg_sequence madera_fll_ao_32K_49M_patch[] = {
4178	{ MADERA_FLLAO_CONTROL_2,  0x02EE },
4179	{ MADERA_FLLAO_CONTROL_3,  0x0000 },
4180	{ MADERA_FLLAO_CONTROL_4,  0x0001 },
4181	{ MADERA_FLLAO_CONTROL_5,  0x0002 },
4182	{ MADERA_FLLAO_CONTROL_6,  0x8001 },
4183	{ MADERA_FLLAO_CONTROL_7,  0x0004 },
4184	{ MADERA_FLLAO_CONTROL_8,  0x0077 },
4185	{ MADERA_FLLAO_CONTROL_10, 0x06D8 },
4186	{ MADERA_FLLAO_CONTROL_11, 0x0085 },
4187	{ MADERA_FLLAO_CONTROL_2,  0x82EE },
4188};
4189
4190static const struct reg_sequence madera_fll_ao_32K_45M_patch[] = {
4191	{ MADERA_FLLAO_CONTROL_2,  0x02B1 },
4192	{ MADERA_FLLAO_CONTROL_3,  0x0001 },
4193	{ MADERA_FLLAO_CONTROL_4,  0x0010 },
4194	{ MADERA_FLLAO_CONTROL_5,  0x0002 },
4195	{ MADERA_FLLAO_CONTROL_6,  0x8001 },
4196	{ MADERA_FLLAO_CONTROL_7,  0x0004 },
4197	{ MADERA_FLLAO_CONTROL_8,  0x0077 },
4198	{ MADERA_FLLAO_CONTROL_10, 0x06D8 },
4199	{ MADERA_FLLAO_CONTROL_11, 0x0005 },
4200	{ MADERA_FLLAO_CONTROL_2,  0x82B1 },
4201};
4202
4203struct madera_fllao_patch {
4204	unsigned int fin;
4205	unsigned int fout;
4206	const struct reg_sequence *patch;
4207	unsigned int patch_size;
4208};
4209
4210static const struct madera_fllao_patch madera_fllao_settings[] = {
4211	{
4212		.fin = 32768,
4213		.fout = 49152000,
4214		.patch = madera_fll_ao_32K_49M_patch,
4215		.patch_size = ARRAY_SIZE(madera_fll_ao_32K_49M_patch),
4216
4217	},
4218	{
4219		.fin = 32768,
4220		.fout = 45158400,
4221		.patch = madera_fll_ao_32K_45M_patch,
4222		.patch_size = ARRAY_SIZE(madera_fll_ao_32K_45M_patch),
4223	},
4224};
4225
4226static int madera_enable_fll_ao(struct madera_fll *fll,
4227				const struct reg_sequence *patch,
4228				unsigned int patch_size)
4229{
4230	struct madera *madera = fll->madera;
4231	int already_enabled = madera_is_enabled_fll(fll, fll->base);
4232	unsigned int val;
4233	int i;
4234
4235	if (already_enabled < 0)
4236		return already_enabled;
4237
4238	if (!already_enabled)
4239		pm_runtime_get_sync(madera->dev);
4240
4241	madera_fll_dbg(fll, "Enabling FLL_AO, initially %s\n",
4242		       str_enabled_disabled(already_enabled));
4243
4244	/* FLL_AO_HOLD must be set before configuring any registers */
4245	regmap_update_bits(fll->madera->regmap,
4246			   fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4247			   MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD);
4248
4249	if (already_enabled)
4250		madera_set_fllao_clks(fll, fll->base, false);
4251
4252	for (i = 0; i < patch_size; i++) {
4253		val = patch[i].def;
4254
4255		/* modify the patch to apply fll->ref_src as input clock */
4256		if (patch[i].reg == MADERA_FLLAO_CONTROL_6) {
4257			val &= ~MADERA_FLL_AO_REFCLK_SRC_MASK;
4258			val |= (fll->ref_src << MADERA_FLL_AO_REFCLK_SRC_SHIFT)
4259				& MADERA_FLL_AO_REFCLK_SRC_MASK;
4260		}
4261
4262		regmap_write(madera->regmap, patch[i].reg, val);
4263	}
4264
4265	madera_set_fllao_clks(fll, fll->base, true);
4266
4267	regmap_update_bits(madera->regmap,
4268			   fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4269			   MADERA_FLL_AO_ENA, MADERA_FLL_AO_ENA);
4270
4271	/* Release the hold so that fll_ao locks to external frequency */
4272	regmap_update_bits(madera->regmap,
4273			   fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4274			   MADERA_FLL_AO_HOLD, 0);
4275
4276	if (!already_enabled)
4277		madera_wait_for_fll(fll, true);
4278
4279	return 0;
4280}
4281
4282static int madera_disable_fll_ao(struct madera_fll *fll)
4283{
4284	struct madera *madera = fll->madera;
4285	bool change;
4286
4287	madera_fll_dbg(fll, "Disabling FLL_AO\n");
4288
4289	regmap_update_bits(madera->regmap,
4290			   fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4291			   MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD);
4292	regmap_update_bits_check(madera->regmap,
4293				 fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4294				 MADERA_FLL_AO_ENA, 0, &change);
4295
4296	madera_wait_for_fll(fll, false);
4297
4298	/*
4299	 * ctrl_up gates the writes to all fll_ao register, setting it to 0
4300	 * here ensures that after a runtime suspend/resume cycle when one
4301	 * enables the fllao then ctrl_up is the last bit that is configured
4302	 * by the fllao enable code rather than the cache sync operation which
4303	 * would have updated it much earlier before writing out all fllao
4304	 * registers
4305	 */
4306	regmap_update_bits(madera->regmap,
4307			   fll->base + MADERA_FLLAO_CONTROL_2_OFFS,
4308			   MADERA_FLL_AO_CTRL_UPD_MASK, 0);
4309
4310	if (change) {
4311		madera_set_fllao_clks(fll, fll->base, false);
4312		pm_runtime_put_autosuspend(madera->dev);
4313	}
4314
4315	return 0;
4316}
4317
4318int madera_set_fll_ao_refclk(struct madera_fll *fll, int source,
4319			     unsigned int fin, unsigned int fout)
4320{
4321	int ret = 0;
4322	const struct reg_sequence *patch = NULL;
4323	int patch_size = 0;
4324	unsigned int i;
4325
4326	if (fll->ref_src == source &&
4327	    fll->ref_freq == fin && fll->fout == fout)
4328		return 0;
4329
4330	madera_fll_dbg(fll, "Change FLL_AO refclk to fin=%u fout=%u source=%d\n",
4331		       fin, fout, source);
4332
4333	if (fout && (fll->ref_freq != fin || fll->fout != fout)) {
4334		for (i = 0; i < ARRAY_SIZE(madera_fllao_settings); i++) {
4335			if (madera_fllao_settings[i].fin == fin &&
4336			    madera_fllao_settings[i].fout == fout)
4337				break;
4338		}
4339
4340		if (i == ARRAY_SIZE(madera_fllao_settings)) {
4341			madera_fll_err(fll,
4342				       "No matching configuration for FLL_AO\n");
4343			return -EINVAL;
4344		}
4345
4346		patch = madera_fllao_settings[i].patch;
4347		patch_size = madera_fllao_settings[i].patch_size;
4348	}
4349
4350	fll->ref_src = source;
4351	fll->ref_freq = fin;
4352	fll->fout = fout;
4353
4354	if (fout)
4355		ret = madera_enable_fll_ao(fll, patch, patch_size);
4356	else
4357		madera_disable_fll_ao(fll);
4358
4359	return ret;
4360}
4361EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk);
4362
4363static int madera_fllhj_disable(struct madera_fll *fll)
4364{
4365	struct madera *madera = fll->madera;
4366	bool change;
4367
4368	madera_fll_dbg(fll, "Disabling FLL\n");
4369
4370	/* Disable lockdet, but don't set ctrl_upd update but.  This allows the
4371	 * lock status bit to clear as normal, but should the FLL be enabled
4372	 * again due to a control clock being required, the lock won't re-assert
4373	 * as the FLL config registers are automatically applied when the FLL
4374	 * enables.
4375	 */
4376	regmap_update_bits(madera->regmap,
4377			   fll->base + MADERA_FLL_CONTROL_11_OFFS,
4378			   MADERA_FLL1_LOCKDET_MASK, 0);
4379	regmap_update_bits(madera->regmap,
4380			   fll->base + MADERA_FLL_CONTROL_1_OFFS,
4381			   MADERA_FLL1_HOLD_MASK, MADERA_FLL1_HOLD_MASK);
4382	regmap_update_bits_check(madera->regmap,
4383				 fll->base + MADERA_FLL_CONTROL_1_OFFS,
4384				 MADERA_FLL1_ENA_MASK, 0, &change);
4385
4386	madera_wait_for_fll(fll, false);
4387
4388	/* ctrl_up gates the writes to all the fll's registers, setting it to 0
4389	 * here ensures that after a runtime suspend/resume cycle when one
4390	 * enables the fll then ctrl_up is the last bit that is configured
4391	 * by the fll enable code rather than the cache sync operation which
4392	 * would have updated it much earlier before writing out all fll
4393	 * registers
4394	 */
4395	regmap_update_bits(madera->regmap,
4396			   fll->base + MADERA_FLL_CONTROL_2_OFFS,
4397			   MADERA_FLL1_CTRL_UPD_MASK, 0);
4398
4399	if (change) {
4400		madera_set_fllhj_clks(fll, fll->base, false);
4401		pm_runtime_put_autosuspend(madera->dev);
4402	}
4403
4404	return 0;
4405}
4406
4407static int madera_fllhj_apply(struct madera_fll *fll, int fin)
4408{
4409	struct madera *madera = fll->madera;
4410	int refdiv, fref, fout, lockdet_thr, fbdiv, hp, fast_clk, fllgcd;
4411	bool frac = false;
4412	unsigned int fll_n, min_n, max_n, ratio, theta, lambda;
4413	unsigned int gains, val, num;
4414
4415	madera_fll_dbg(fll, "fin=%d, fout=%d\n", fin, fll->fout);
4416
4417	for (refdiv = 0; refdiv < 4; refdiv++)
4418		if ((fin / (1 << refdiv)) <= MADERA_FLLHJ_MAX_THRESH)
4419			break;
4420
4421	fref = fin / (1 << refdiv);
4422
4423	/* Use simple heuristic approach to find a configuration that
4424	 * should work for most input clocks.
4425	 */
4426	fast_clk = 0;
4427	fout = fll->fout;
4428	frac = fout % fref;
4429
4430	if (fref < MADERA_FLLHJ_LOW_THRESH) {
4431		lockdet_thr = 2;
4432		gains = MADERA_FLLHJ_LOW_GAINS;
4433		if (frac)
4434			fbdiv = 256;
4435		else
4436			fbdiv = 4;
4437	} else if (fref < MADERA_FLLHJ_MID_THRESH) {
4438		lockdet_thr = 8;
4439		gains = MADERA_FLLHJ_MID_GAINS;
4440		fbdiv = 1;
4441	} else {
4442		lockdet_thr = 8;
4443		gains = MADERA_FLLHJ_HIGH_GAINS;
4444		fbdiv = 1;
4445		/* For high speed input clocks, enable 300MHz fast oscillator
4446		 * when we're in fractional divider mode.
4447		 */
4448		if (frac) {
4449			fast_clk = 0x3;
4450			fout = fll->fout * 6;
4451		}
4452	}
4453	/* Use high performance mode for fractional configurations. */
4454	if (frac) {
4455		hp = 0x3;
4456		min_n = MADERA_FLLHJ_FRAC_MIN_N;
4457		max_n = MADERA_FLLHJ_FRAC_MAX_N;
4458	} else {
4459		hp = 0x0;
4460		min_n = MADERA_FLLHJ_INT_MIN_N;
4461		max_n = MADERA_FLLHJ_INT_MAX_N;
4462	}
4463
4464	ratio = fout / fref;
4465
4466	madera_fll_dbg(fll, "refdiv=%d, fref=%d, frac:%d\n",
4467		       refdiv, fref, frac);
4468
4469	while (ratio / fbdiv < min_n) {
4470		fbdiv /= 2;
4471		if (fbdiv < 1) {
4472			madera_fll_err(fll, "FBDIV (%d) must be >= 1\n", fbdiv);
4473			return -EINVAL;
4474		}
4475	}
4476	while (frac && (ratio / fbdiv > max_n)) {
4477		fbdiv *= 2;
4478		if (fbdiv >= 1024) {
4479			madera_fll_err(fll, "FBDIV (%u) >= 1024\n", fbdiv);
4480			return -EINVAL;
4481		}
4482	}
4483
4484	madera_fll_dbg(fll, "lockdet=%d, hp=0x%x, fbdiv:%d\n",
4485		       lockdet_thr, hp, fbdiv);
4486
4487	/* Calculate N.K values */
4488	fllgcd = gcd(fout, fbdiv * fref);
4489	num = fout / fllgcd;
4490	lambda = (fref * fbdiv) / fllgcd;
4491	fll_n = num / lambda;
4492	theta = num % lambda;
4493
4494	madera_fll_dbg(fll, "fll_n=%d, gcd=%d, theta=%d, lambda=%d\n",
4495		       fll_n, fllgcd, theta, lambda);
4496
4497	/* Some sanity checks before any registers are written. */
4498	if (fll_n < min_n || fll_n > max_n) {
4499		madera_fll_err(fll, "N not in valid %s mode range %d-%d: %d\n",
4500			       frac ? "fractional" : "integer", min_n, max_n,
4501			       fll_n);
4502		return -EINVAL;
4503	}
4504	if (fbdiv < 1 || (frac && fbdiv >= 1024) || (!frac && fbdiv >= 256)) {
4505		madera_fll_err(fll, "Invalid fbdiv for %s mode (%u)\n",
4506			       frac ? "fractional" : "integer", fbdiv);
4507		return -EINVAL;
4508	}
4509
4510	/* clear the ctrl_upd bit to guarantee we write to it later. */
4511	regmap_write(madera->regmap,
4512		     fll->base + MADERA_FLL_CONTROL_2_OFFS,
4513		     fll_n << MADERA_FLL1_N_SHIFT);
4514	regmap_update_bits(madera->regmap,
4515			   fll->base + MADERA_FLL_CONTROL_3_OFFS,
4516			   MADERA_FLL1_THETA_MASK,
4517			   theta << MADERA_FLL1_THETA_SHIFT);
4518	regmap_update_bits(madera->regmap,
4519			   fll->base + MADERA_FLL_CONTROL_4_OFFS,
4520			   MADERA_FLL1_LAMBDA_MASK,
4521			   lambda << MADERA_FLL1_LAMBDA_SHIFT);
4522	regmap_update_bits(madera->regmap,
4523			   fll->base + MADERA_FLL_CONTROL_5_OFFS,
4524			   MADERA_FLL1_FB_DIV_MASK,
4525			   fbdiv << MADERA_FLL1_FB_DIV_SHIFT);
4526	regmap_update_bits(madera->regmap,
4527			   fll->base + MADERA_FLL_CONTROL_6_OFFS,
4528			   MADERA_FLL1_REFCLK_DIV_MASK,
4529			   refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT);
4530	regmap_update_bits(madera->regmap,
4531			   fll->base + MADERA_FLL_GAIN_OFFS,
4532			   0xffff,
4533			   gains);
4534	val = hp << MADERA_FLL1_HP_SHIFT;
4535	val |= 1 << MADERA_FLL1_PHASEDET_ENA_SHIFT;
4536	regmap_update_bits(madera->regmap,
4537			   fll->base + MADERA_FLL_CONTROL_10_OFFS,
4538			   MADERA_FLL1_HP_MASK | MADERA_FLL1_PHASEDET_ENA_MASK,
4539			   val);
4540	regmap_update_bits(madera->regmap,
4541			   fll->base + MADERA_FLL_CONTROL_11_OFFS,
4542			   MADERA_FLL1_LOCKDET_THR_MASK,
4543			   lockdet_thr << MADERA_FLL1_LOCKDET_THR_SHIFT);
4544	regmap_update_bits(madera->regmap,
4545			   fll->base + MADERA_FLL1_DIGITAL_TEST_1_OFFS,
4546			   MADERA_FLL1_SYNC_EFS_ENA_MASK |
4547			   MADERA_FLL1_CLK_VCO_FAST_SRC_MASK,
4548			   fast_clk);
4549
4550	return 0;
4551}
4552
4553static int madera_fllhj_enable(struct madera_fll *fll)
4554{
4555	struct madera *madera = fll->madera;
4556	int already_enabled = madera_is_enabled_fll(fll, fll->base);
4557	int ret;
4558
4559	if (already_enabled < 0)
4560		return already_enabled;
4561
4562	if (!already_enabled)
4563		pm_runtime_get_sync(madera->dev);
4564
4565	madera_fll_dbg(fll, "Enabling FLL, initially %s\n",
4566		       str_enabled_disabled(already_enabled));
4567
4568	/* FLLn_HOLD must be set before configuring any registers */
4569	regmap_update_bits(fll->madera->regmap,
4570			   fll->base + MADERA_FLL_CONTROL_1_OFFS,
4571			   MADERA_FLL1_HOLD_MASK,
4572			   MADERA_FLL1_HOLD_MASK);
4573
4574	if (already_enabled)
4575		madera_set_fllhj_clks(fll, fll->base, false);
4576
4577	/* Apply refclk */
4578	ret = madera_fllhj_apply(fll, fll->ref_freq);
4579	if (ret) {
4580		madera_fll_err(fll, "Failed to set FLL: %d\n", ret);
4581		goto out;
4582	}
4583	regmap_update_bits(madera->regmap,
4584			   fll->base + MADERA_FLL_CONTROL_1_OFFS,
4585			   CS47L92_FLL1_REFCLK_SRC_MASK,
4586			   fll->ref_src << CS47L92_FLL1_REFCLK_SRC_SHIFT);
4587
4588	madera_set_fllhj_clks(fll, fll->base, true);
4589
4590	regmap_update_bits(madera->regmap,
4591			   fll->base + MADERA_FLL_CONTROL_1_OFFS,
4592			   MADERA_FLL1_ENA_MASK,
4593			   MADERA_FLL1_ENA_MASK);
4594
4595out:
4596	regmap_update_bits(madera->regmap,
4597			   fll->base + MADERA_FLL_CONTROL_11_OFFS,
4598			   MADERA_FLL1_LOCKDET_MASK,
4599			   MADERA_FLL1_LOCKDET_MASK);
4600
4601	regmap_update_bits(madera->regmap,
4602			   fll->base + MADERA_FLL_CONTROL_2_OFFS,
4603			   MADERA_FLL1_CTRL_UPD_MASK,
4604			   MADERA_FLL1_CTRL_UPD_MASK);
4605
4606	/* Release the hold so that flln locks to external frequency */
4607	regmap_update_bits(madera->regmap,
4608			   fll->base + MADERA_FLL_CONTROL_1_OFFS,
4609			   MADERA_FLL1_HOLD_MASK,
4610			   0);
4611
4612	if (!already_enabled)
4613		madera_wait_for_fll(fll, true);
4614
4615	return 0;
4616}
4617
4618static int madera_fllhj_validate(struct madera_fll *fll,
4619				 unsigned int ref_in,
4620				 unsigned int fout)
4621{
4622	if (fout && !ref_in) {
4623		madera_fll_err(fll, "fllout set without valid input clk\n");
4624		return -EINVAL;
4625	}
4626
4627	if (fll->fout && fout != fll->fout) {
4628		madera_fll_err(fll, "Can't change output on active FLL\n");
4629		return -EINVAL;
4630	}
4631
4632	if (ref_in / MADERA_FLL_MAX_REFDIV > MADERA_FLLHJ_MAX_THRESH) {
4633		madera_fll_err(fll, "Can't scale %dMHz to <=13MHz\n", ref_in);
4634		return -EINVAL;
4635	}
4636
4637	return 0;
4638}
4639
4640int madera_fllhj_set_refclk(struct madera_fll *fll, int source,
4641			    unsigned int fin, unsigned int fout)
4642{
4643	int ret = 0;
4644
4645	/* To remain consistent with previous FLLs, we expect fout to be
4646	 * provided in the form of the required sysclk rate, which is
4647	 * 2x the calculated fll out.
4648	 */
4649	if (fout)
4650		fout /= 2;
4651
4652	if (fll->ref_src == source && fll->ref_freq == fin &&
4653	    fll->fout == fout)
4654		return 0;
4655
4656	if (fin && fout && madera_fllhj_validate(fll, fin, fout))
4657		return -EINVAL;
4658
4659	fll->ref_src = source;
4660	fll->ref_freq = fin;
4661	fll->fout = fout;
4662
4663	if (fout)
4664		ret = madera_fllhj_enable(fll);
4665	else
4666		madera_fllhj_disable(fll);
4667
4668	return ret;
4669}
4670EXPORT_SYMBOL_GPL(madera_fllhj_set_refclk);
4671
4672/**
4673 * madera_set_output_mode - Set the mode of the specified output
4674 *
4675 * @component: Device to configure
4676 * @output: Output number
4677 * @differential: True to set the output to differential mode
4678 *
4679 * Some systems use external analogue switches to connect more
4680 * analogue devices to the CODEC than are supported by the device.  In
4681 * some systems this requires changing the switched output from single
4682 * ended to differential mode dynamically at runtime, an operation
4683 * supported using this function.
4684 *
4685 * Most systems have a single static configuration and should use
4686 * platform data instead.
4687 */
4688int madera_set_output_mode(struct snd_soc_component *component, int output,
4689			   bool differential)
4690{
4691	unsigned int reg, val;
4692	int ret;
4693
4694	if (output < 1 || output > MADERA_MAX_OUTPUT)
4695		return -EINVAL;
4696
4697	reg = MADERA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
4698
4699	if (differential)
4700		val = MADERA_OUT1_MONO;
4701	else
4702		val = 0;
4703
4704	ret = snd_soc_component_update_bits(component, reg, MADERA_OUT1_MONO,
4705					    val);
4706	if (ret < 0)
4707		return ret;
4708	else
4709		return 0;
4710}
4711EXPORT_SYMBOL_GPL(madera_set_output_mode);
4712
4713static bool madera_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
4714{
4715	s16 a = be16_to_cpu(_a);
4716	s16 b = be16_to_cpu(_b);
4717
4718	if (!mode) {
4719		return abs(a) >= 4096;
4720	} else {
4721		if (abs(b) >= 4096)
4722			return true;
4723
4724		return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
4725	}
4726}
4727
4728int madera_eq_coeff_put(struct snd_kcontrol *kcontrol,
4729			struct snd_ctl_elem_value *ucontrol)
4730{
4731	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4732	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
4733	struct madera *madera = priv->madera;
4734	struct soc_bytes *params = (void *)kcontrol->private_value;
4735	unsigned int val;
4736	__be16 *data;
4737	int len;
4738	int ret;
4739
4740	len = params->num_regs * regmap_get_val_bytes(madera->regmap);
4741
4742	data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
4743	if (!data)
4744		return -ENOMEM;
4745
4746	data[0] &= cpu_to_be16(MADERA_EQ1_B1_MODE);
4747
4748	if (madera_eq_filter_unstable(!!data[0], data[1], data[2]) ||
4749	    madera_eq_filter_unstable(true, data[4], data[5]) ||
4750	    madera_eq_filter_unstable(true, data[8], data[9]) ||
4751	    madera_eq_filter_unstable(true, data[12], data[13]) ||
4752	    madera_eq_filter_unstable(false, data[16], data[17])) {
4753		dev_err(madera->dev, "Rejecting unstable EQ coefficients\n");
4754		ret = -EINVAL;
4755		goto out;
4756	}
4757
4758	ret = regmap_read(madera->regmap, params->base, &val);
4759	if (ret != 0)
4760		goto out;
4761
4762	val &= ~MADERA_EQ1_B1_MODE;
4763	data[0] |= cpu_to_be16(val);
4764
4765	ret = regmap_raw_write(madera->regmap, params->base, data, len);
4766
4767out:
4768	kfree(data);
4769
4770	return ret;
4771}
4772EXPORT_SYMBOL_GPL(madera_eq_coeff_put);
4773
4774int madera_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
4775			  struct snd_ctl_elem_value *ucontrol)
4776{
4777	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4778	struct madera_priv *priv = snd_soc_component_get_drvdata(component);
4779	struct madera *madera = priv->madera;
4780	__be16 *data = (__be16 *)ucontrol->value.bytes.data;
4781	s16 val = be16_to_cpu(*data);
4782
4783	if (abs(val) >= 4096) {
4784		dev_err(madera->dev, "Rejecting unstable LHPF coefficients\n");
4785		return -EINVAL;
4786	}
4787
4788	return snd_soc_bytes_put(kcontrol, ucontrol);
4789}
4790EXPORT_SYMBOL_GPL(madera_lhpf_coeff_put);
4791
4792MODULE_SOFTDEP("pre: madera");
4793MODULE_DESCRIPTION("ASoC Cirrus Logic Madera codec support");
4794MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
4795MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
4796MODULE_LICENSE("GPL v2");
~/ Read-only file preview.