Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// cs35l45.c - CS35L45 ALSA SoC audio driver
   4//
   5// Copyright 2019-2022 Cirrus Logic, Inc.
   6//
   7// Author: James Schulman <james.schulman@cirrus.com>
   8
   9#include <linux/gpio/consumer.h>
  10#include <linux/module.h>
  11#include <linux/pm_runtime.h>
  12#include <linux/property.h>
  13#include <linux/firmware.h>
  14#include <linux/regulator/consumer.h>
  15#include <sound/core.h>
  16#include <sound/pcm.h>
  17#include <sound/pcm_params.h>
  18#include <sound/soc.h>
  19#include <sound/tlv.h>
  20
  21#include "cs35l45.h"
  22
  23static bool cs35l45_check_cspl_mbox_sts(const enum cs35l45_cspl_mboxcmd cmd,
  24					enum cs35l45_cspl_mboxstate sts)
  25{
  26	switch (cmd) {
  27	case CSPL_MBOX_CMD_NONE:
  28	case CSPL_MBOX_CMD_UNKNOWN_CMD:
  29		return true;
  30	case CSPL_MBOX_CMD_PAUSE:
  31	case CSPL_MBOX_CMD_OUT_OF_HIBERNATE:
  32		return (sts == CSPL_MBOX_STS_PAUSED);
  33	case CSPL_MBOX_CMD_RESUME:
  34		return (sts == CSPL_MBOX_STS_RUNNING);
  35	case CSPL_MBOX_CMD_REINIT:
  36		return (sts == CSPL_MBOX_STS_RUNNING);
  37	case CSPL_MBOX_CMD_STOP_PRE_REINIT:
  38		return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT);
  39	case CSPL_MBOX_CMD_HIBERNATE:
  40		return (sts == CSPL_MBOX_STS_HIBERNATE);
  41	default:
  42		return false;
  43	}
  44}
  45
  46static int cs35l45_set_cspl_mbox_cmd(struct cs35l45_private *cs35l45,
  47				      struct regmap *regmap,
  48				      const enum cs35l45_cspl_mboxcmd cmd)
  49{
  50	unsigned int sts = 0, i;
  51	int ret;
  52
  53	if (!cs35l45->dsp.cs_dsp.running) {
  54		dev_err(cs35l45->dev, "DSP not running\n");
  55		return -EPERM;
  56	}
  57
  58	// Set mailbox cmd
  59	ret = regmap_write(regmap, CS35L45_DSP_VIRT1_MBOX_1, cmd);
  60	if (ret < 0) {
  61		if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE)
  62			dev_err(cs35l45->dev, "Failed to write MBOX: %d\n", ret);
  63		return ret;
  64	}
  65
  66	// Read mailbox status and verify it is appropriate for the given cmd
  67	for (i = 0; i < 5; i++) {
  68		usleep_range(1000, 1100);
  69
  70		ret = regmap_read(regmap, CS35L45_DSP_MBOX_2, &sts);
  71		if (ret < 0) {
  72			dev_err(cs35l45->dev, "Failed to read MBOX STS: %d\n", ret);
  73			continue;
  74		}
  75
  76		if (!cs35l45_check_cspl_mbox_sts(cmd, sts))
  77			dev_dbg(cs35l45->dev, "[%u] cmd %u returned invalid sts %u", i, cmd, sts);
  78		else
  79			return 0;
  80	}
  81
  82	if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE)
  83		dev_err(cs35l45->dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts);
  84
  85	return -ENOMSG;
  86}
  87
  88static int cs35l45_global_en_ev(struct snd_soc_dapm_widget *w,
  89				struct snd_kcontrol *kcontrol, int event)
  90{
  91	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  92	struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component);
  93
  94	dev_dbg(cs35l45->dev, "%s event : %x\n", __func__, event);
  95
  96	switch (event) {
  97	case SND_SOC_DAPM_POST_PMU:
  98		regmap_write(cs35l45->regmap, CS35L45_GLOBAL_ENABLES,
  99			     CS35L45_GLOBAL_EN_MASK);
 100
 101		usleep_range(CS35L45_POST_GLOBAL_EN_US, CS35L45_POST_GLOBAL_EN_US + 100);
 102		break;
 103	case SND_SOC_DAPM_PRE_PMD:
 104		usleep_range(CS35L45_PRE_GLOBAL_DIS_US, CS35L45_PRE_GLOBAL_DIS_US + 100);
 105
 106		regmap_write(cs35l45->regmap, CS35L45_GLOBAL_ENABLES, 0);
 107		break;
 108	default:
 109		break;
 110	}
 111
 112	return 0;
 113}
 114
 115static int cs35l45_dsp_preload_ev(struct snd_soc_dapm_widget *w,
 116				  struct snd_kcontrol *kcontrol, int event)
 117{
 118	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 119	struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component);
 120	int ret;
 121
 122	switch (event) {
 123	case SND_SOC_DAPM_PRE_PMU:
 124		if (cs35l45->dsp.cs_dsp.booted)
 125			return 0;
 126
 127		return wm_adsp_early_event(w, kcontrol, event);
 128	case SND_SOC_DAPM_POST_PMU:
 129		if (cs35l45->dsp.cs_dsp.running)
 130			return 0;
 131
 132		regmap_set_bits(cs35l45->regmap, CS35L45_PWRMGT_CTL,
 133				   CS35L45_MEM_RDY_MASK);
 134
 135		return wm_adsp_event(w, kcontrol, event);
 136	case SND_SOC_DAPM_PRE_PMD:
 137		if (cs35l45->dsp.preloaded)
 138			return 0;
 139
 140		if (cs35l45->dsp.cs_dsp.running) {
 141			ret = wm_adsp_event(w, kcontrol, event);
 142			if (ret)
 143				return ret;
 144		}
 145
 146		return wm_adsp_early_event(w, kcontrol, event);
 147	default:
 148		return 0;
 149	}
 150}
 151
 152static int cs35l45_dsp_audio_ev(struct snd_soc_dapm_widget *w,
 153				struct snd_kcontrol *kcontrol, int event)
 154{
 155	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 156	struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component);
 157
 158	switch (event) {
 159	case SND_SOC_DAPM_POST_PMU:
 160		return cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap,
 161						 CSPL_MBOX_CMD_RESUME);
 162	case SND_SOC_DAPM_PRE_PMD:
 163		return cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap,
 164						 CSPL_MBOX_CMD_PAUSE);
 165	default:
 166		return 0;
 167	}
 168
 169	return 0;
 170}
 171
 172static int cs35l45_activate_ctl(struct snd_soc_component *component,
 173				const char *ctl_name, bool active)
 174{
 175	struct snd_card *card = component->card->snd_card;
 176	struct snd_kcontrol *kcontrol;
 177	struct snd_kcontrol_volatile *vd;
 178	unsigned int index_offset;
 179
 180	kcontrol = snd_soc_component_get_kcontrol(component, ctl_name);
 181	if (!kcontrol) {
 182		dev_err(component->dev, "Can't find kcontrol %s\n", ctl_name);
 183		return -EINVAL;
 184	}
 185
 186	index_offset = snd_ctl_get_ioff(kcontrol, &kcontrol->id);
 187	vd = &kcontrol->vd[index_offset];
 188	if (active)
 189		vd->access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
 190	else
 191		vd->access &= ~SNDRV_CTL_ELEM_ACCESS_WRITE;
 192
 193	snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, &kcontrol->id);
 194
 195	return 0;
 196}
 197
 198static int cs35l45_amplifier_mode_get(struct snd_kcontrol *kcontrol,
 199				      struct snd_ctl_elem_value *ucontrol)
 200{
 201	struct snd_soc_component *component =
 202			snd_soc_kcontrol_component(kcontrol);
 203	struct cs35l45_private *cs35l45 =
 204			snd_soc_component_get_drvdata(component);
 205
 206	ucontrol->value.integer.value[0] = cs35l45->amplifier_mode;
 207
 208	return 0;
 209}
 210
 211static int cs35l45_amplifier_mode_put(struct snd_kcontrol *kcontrol,
 212				      struct snd_ctl_elem_value *ucontrol)
 213{
 214	struct snd_soc_component *component =
 215			snd_soc_kcontrol_component(kcontrol);
 216	struct cs35l45_private *cs35l45 =
 217			snd_soc_component_get_drvdata(component);
 218	struct snd_soc_dapm_context *dapm =
 219			snd_soc_component_get_dapm(component);
 220	unsigned int amp_state;
 221	int ret;
 222
 223	if ((ucontrol->value.integer.value[0] == cs35l45->amplifier_mode) ||
 224	    (ucontrol->value.integer.value[0] > AMP_MODE_RCV))
 225		return 0;
 226
 227	snd_soc_dapm_mutex_lock(dapm);
 228
 229	ret = regmap_read(cs35l45->regmap, CS35L45_BLOCK_ENABLES, &amp_state);
 230	if (ret < 0) {
 231		dev_err(cs35l45->dev, "Failed to read AMP state: %d\n", ret);
 232		snd_soc_dapm_mutex_unlock(dapm);
 233		return ret;
 234	}
 235
 236	regmap_clear_bits(cs35l45->regmap, CS35L45_BLOCK_ENABLES,
 237				  CS35L45_AMP_EN_MASK);
 238	snd_soc_component_disable_pin_unlocked(component, "SPK");
 239	snd_soc_dapm_sync_unlocked(dapm);
 240
 241	if (ucontrol->value.integer.value[0] == AMP_MODE_SPK) {
 242		regmap_clear_bits(cs35l45->regmap, CS35L45_BLOCK_ENABLES,
 243				  CS35L45_RCV_EN_MASK);
 244
 245		regmap_update_bits(cs35l45->regmap, CS35L45_BLOCK_ENABLES,
 246				   CS35L45_BST_EN_MASK,
 247				   CS35L45_BST_ENABLE << CS35L45_BST_EN_SHIFT);
 248
 249		regmap_update_bits(cs35l45->regmap, CS35L45_HVLV_CONFIG,
 250				   CS35L45_HVLV_MODE_MASK,
 251				   CS35L45_HVLV_OPERATION <<
 252				   CS35L45_HVLV_MODE_SHIFT);
 253
 254		ret = cs35l45_activate_ctl(component, "Analog PCM Volume", true);
 255		if (ret < 0)
 256			dev_err(cs35l45->dev,
 257				"Unable to deactivate ctl (%d)\n", ret);
 258
 259	} else  /* AMP_MODE_RCV */ {
 260		regmap_set_bits(cs35l45->regmap, CS35L45_BLOCK_ENABLES,
 261				CS35L45_RCV_EN_MASK);
 262
 263		regmap_update_bits(cs35l45->regmap, CS35L45_BLOCK_ENABLES,
 264				   CS35L45_BST_EN_MASK,
 265				   CS35L45_BST_DISABLE_FET_OFF <<
 266				   CS35L45_BST_EN_SHIFT);
 267
 268		regmap_update_bits(cs35l45->regmap, CS35L45_HVLV_CONFIG,
 269				   CS35L45_HVLV_MODE_MASK,
 270				   CS35L45_FORCE_LV_OPERATION <<
 271				   CS35L45_HVLV_MODE_SHIFT);
 272
 273		regmap_clear_bits(cs35l45->regmap,
 274				  CS35L45_BLOCK_ENABLES2,
 275				  CS35L45_AMP_DRE_EN_MASK);
 276
 277		regmap_update_bits(cs35l45->regmap, CS35L45_AMP_GAIN,
 278				   CS35L45_AMP_GAIN_PCM_MASK,
 279				   CS35L45_AMP_GAIN_PCM_13DBV <<
 280				   CS35L45_AMP_GAIN_PCM_SHIFT);
 281
 282		ret = cs35l45_activate_ctl(component, "Analog PCM Volume", false);
 283		if (ret < 0)
 284			dev_err(cs35l45->dev,
 285				"Unable to deactivate ctl (%d)\n", ret);
 286	}
 287
 288	if (amp_state & CS35L45_AMP_EN_MASK)
 289		regmap_set_bits(cs35l45->regmap, CS35L45_BLOCK_ENABLES,
 290				CS35L45_AMP_EN_MASK);
 291
 292	snd_soc_component_enable_pin_unlocked(component, "SPK");
 293	snd_soc_dapm_sync_unlocked(dapm);
 294	snd_soc_dapm_mutex_unlock(dapm);
 295
 296	cs35l45->amplifier_mode = ucontrol->value.integer.value[0];
 297
 298	return 1;
 299}
 300
 301static const char * const cs35l45_asp_tx_txt[] = {
 302	"Zero", "ASP_RX1", "ASP_RX2",
 303	"VMON", "IMON", "ERR_VOL",
 304	"VDD_BATTMON", "VDD_BSTMON",
 305	"DSP_TX1", "DSP_TX2",
 306	"Interpolator", "IL_TARGET",
 307};
 308
 309static const unsigned int cs35l45_asp_tx_val[] = {
 310	CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2,
 311	CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL,
 312	CS35L45_PCM_SRC_VDD_BATTMON, CS35L45_PCM_SRC_VDD_BSTMON,
 313	CS35L45_PCM_SRC_DSP_TX1, CS35L45_PCM_SRC_DSP_TX2,
 314	CS35L45_PCM_SRC_INTERPOLATOR, CS35L45_PCM_SRC_IL_TARGET,
 315};
 316
 317static const struct soc_enum cs35l45_asp_tx_enums[] = {
 318	SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX1_INPUT, 0, CS35L45_PCM_SRC_MASK,
 319			      ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt,
 320			      cs35l45_asp_tx_val),
 321	SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX2_INPUT, 0, CS35L45_PCM_SRC_MASK,
 322			      ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt,
 323			      cs35l45_asp_tx_val),
 324	SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX3_INPUT, 0, CS35L45_PCM_SRC_MASK,
 325			      ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt,
 326			      cs35l45_asp_tx_val),
 327	SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX4_INPUT, 0, CS35L45_PCM_SRC_MASK,
 328			      ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt,
 329			      cs35l45_asp_tx_val),
 330	SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX5_INPUT, 0, CS35L45_PCM_SRC_MASK,
 331			      ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt,
 332			      cs35l45_asp_tx_val),
 333};
 334
 335static const char * const cs35l45_dsp_rx_txt[] = {
 336	"Zero", "ASP_RX1", "ASP_RX2",
 337	"VMON", "IMON", "ERR_VOL",
 338	"CLASSH_TGT", "VDD_BATTMON",
 339	"VDD_BSTMON", "TEMPMON",
 340};
 341
 342static const unsigned int cs35l45_dsp_rx_val[] = {
 343	CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2,
 344	CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL,
 345	CS35L45_PCM_SRC_CLASSH_TGT, CS35L45_PCM_SRC_VDD_BATTMON,
 346	CS35L45_PCM_SRC_VDD_BSTMON, CS35L45_PCM_SRC_TEMPMON,
 347};
 348
 349static const struct soc_enum cs35l45_dsp_rx_enums[] = {
 350	SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX1_INPUT, 0, CS35L45_PCM_SRC_MASK,
 351			      ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt,
 352			      cs35l45_dsp_rx_val),
 353	SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX2_INPUT, 0, CS35L45_PCM_SRC_MASK,
 354			      ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt,
 355			      cs35l45_dsp_rx_val),
 356	SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX3_INPUT, 0, CS35L45_PCM_SRC_MASK,
 357			      ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt,
 358			      cs35l45_dsp_rx_val),
 359	SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX4_INPUT, 0, CS35L45_PCM_SRC_MASK,
 360			      ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt,
 361			      cs35l45_dsp_rx_val),
 362	SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX5_INPUT, 0, CS35L45_PCM_SRC_MASK,
 363			      ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt,
 364			      cs35l45_dsp_rx_val),
 365	SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX6_INPUT, 0, CS35L45_PCM_SRC_MASK,
 366			      ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt,
 367			      cs35l45_dsp_rx_val),
 368	SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX7_INPUT, 0, CS35L45_PCM_SRC_MASK,
 369			      ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt,
 370			      cs35l45_dsp_rx_val),
 371	SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX8_INPUT, 0, CS35L45_PCM_SRC_MASK,
 372			      ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt,
 373			      cs35l45_dsp_rx_val),
 374};
 375
 376static const char * const cs35l45_dac_txt[] = {
 377	"Zero", "ASP_RX1", "ASP_RX2", "DSP_TX1", "DSP_TX2"
 378};
 379
 380static const unsigned int cs35l45_dac_val[] = {
 381	CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2,
 382	CS35L45_PCM_SRC_DSP_TX1, CS35L45_PCM_SRC_DSP_TX2
 383};
 384
 385static const struct soc_enum cs35l45_dacpcm_enums[] = {
 386	SOC_VALUE_ENUM_SINGLE(CS35L45_DACPCM1_INPUT, 0, CS35L45_PCM_SRC_MASK,
 387			      ARRAY_SIZE(cs35l45_dac_txt), cs35l45_dac_txt,
 388			      cs35l45_dac_val),
 389};
 390
 391static const struct snd_kcontrol_new cs35l45_asp_muxes[] = {
 392	SOC_DAPM_ENUM("ASP_TX1 Source", cs35l45_asp_tx_enums[0]),
 393	SOC_DAPM_ENUM("ASP_TX2 Source", cs35l45_asp_tx_enums[1]),
 394	SOC_DAPM_ENUM("ASP_TX3 Source", cs35l45_asp_tx_enums[2]),
 395	SOC_DAPM_ENUM("ASP_TX4 Source", cs35l45_asp_tx_enums[3]),
 396	SOC_DAPM_ENUM("ASP_TX5 Source", cs35l45_asp_tx_enums[4]),
 397};
 398
 399static const struct snd_kcontrol_new cs35l45_dsp_muxes[] = {
 400	SOC_DAPM_ENUM("DSP_RX1 Source", cs35l45_dsp_rx_enums[0]),
 401	SOC_DAPM_ENUM("DSP_RX2 Source", cs35l45_dsp_rx_enums[1]),
 402	SOC_DAPM_ENUM("DSP_RX3 Source", cs35l45_dsp_rx_enums[2]),
 403	SOC_DAPM_ENUM("DSP_RX4 Source", cs35l45_dsp_rx_enums[3]),
 404	SOC_DAPM_ENUM("DSP_RX5 Source", cs35l45_dsp_rx_enums[4]),
 405	SOC_DAPM_ENUM("DSP_RX6 Source", cs35l45_dsp_rx_enums[5]),
 406	SOC_DAPM_ENUM("DSP_RX7 Source", cs35l45_dsp_rx_enums[6]),
 407	SOC_DAPM_ENUM("DSP_RX8 Source", cs35l45_dsp_rx_enums[7]),
 408};
 409
 410static const struct snd_kcontrol_new cs35l45_dac_muxes[] = {
 411	SOC_DAPM_ENUM("DACPCM Source", cs35l45_dacpcm_enums[0]),
 412};
 413static const struct snd_kcontrol_new amp_en_ctl =
 414	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
 415
 416static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = {
 417	SND_SOC_DAPM_SPK("DSP1 Preload", NULL),
 418	SND_SOC_DAPM_SUPPLY_S("DSP1 Preloader", 100, SND_SOC_NOPM, 0, 0,
 419				cs35l45_dsp_preload_ev,
 420				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 421	SND_SOC_DAPM_OUT_DRV_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0,
 422				cs35l45_dsp_audio_ev,
 423				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 424	SND_SOC_DAPM_SUPPLY("GLOBAL_EN", SND_SOC_NOPM, 0, 0,
 425			    cs35l45_global_en_ev,
 426			    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 427	SND_SOC_DAPM_SUPPLY("ASP_EN", CS35L45_BLOCK_ENABLES2, CS35L45_ASP_EN_SHIFT, 0, NULL, 0),
 428
 429	SND_SOC_DAPM_SIGGEN("VMON_SRC"),
 430	SND_SOC_DAPM_SIGGEN("IMON_SRC"),
 431	SND_SOC_DAPM_SIGGEN("TEMPMON_SRC"),
 432	SND_SOC_DAPM_SIGGEN("VDD_BATTMON_SRC"),
 433	SND_SOC_DAPM_SIGGEN("VDD_BSTMON_SRC"),
 434	SND_SOC_DAPM_SIGGEN("ERR_VOL"),
 435	SND_SOC_DAPM_SIGGEN("AMP_INTP"),
 436	SND_SOC_DAPM_SIGGEN("IL_TARGET"),
 437
 438	SND_SOC_DAPM_SUPPLY("VMON_EN", CS35L45_BLOCK_ENABLES, CS35L45_VMON_EN_SHIFT, 0, NULL, 0),
 439	SND_SOC_DAPM_SUPPLY("IMON_EN", CS35L45_BLOCK_ENABLES, CS35L45_IMON_EN_SHIFT, 0, NULL, 0),
 440	SND_SOC_DAPM_SUPPLY("TEMPMON_EN", CS35L45_BLOCK_ENABLES, CS35L45_TEMPMON_EN_SHIFT, 0, NULL, 0),
 441	SND_SOC_DAPM_SUPPLY("VDD_BATTMON_EN", CS35L45_BLOCK_ENABLES, CS35L45_VDD_BATTMON_EN_SHIFT, 0, NULL, 0),
 442	SND_SOC_DAPM_SUPPLY("VDD_BSTMON_EN", CS35L45_BLOCK_ENABLES, CS35L45_VDD_BSTMON_EN_SHIFT, 0, NULL, 0),
 443
 444	SND_SOC_DAPM_ADC("VMON", NULL, SND_SOC_NOPM, 0, 0),
 445	SND_SOC_DAPM_ADC("IMON", NULL, SND_SOC_NOPM, 0, 0),
 446	SND_SOC_DAPM_ADC("TEMPMON", NULL, SND_SOC_NOPM, 0, 0),
 447	SND_SOC_DAPM_ADC("VDD_BATTMON", NULL, SND_SOC_NOPM, 0, 0),
 448	SND_SOC_DAPM_ADC("VDD_BSTMON", NULL, SND_SOC_NOPM, 0, 0),
 449
 450
 451	SND_SOC_DAPM_AIF_IN("ASP_RX1", NULL, 0, CS35L45_ASP_ENABLES1, CS35L45_ASP_RX1_EN_SHIFT, 0),
 452	SND_SOC_DAPM_AIF_IN("ASP_RX2", NULL, 1, CS35L45_ASP_ENABLES1, CS35L45_ASP_RX2_EN_SHIFT, 0),
 453
 454	SND_SOC_DAPM_AIF_OUT("ASP_TX1", NULL, 0, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX1_EN_SHIFT, 0),
 455	SND_SOC_DAPM_AIF_OUT("ASP_TX2", NULL, 1, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX2_EN_SHIFT, 0),
 456	SND_SOC_DAPM_AIF_OUT("ASP_TX3", NULL, 2, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX3_EN_SHIFT, 0),
 457	SND_SOC_DAPM_AIF_OUT("ASP_TX4", NULL, 3, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX4_EN_SHIFT, 0),
 458	SND_SOC_DAPM_AIF_OUT("ASP_TX5", NULL, 3, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX5_EN_SHIFT, 0),
 459
 460	SND_SOC_DAPM_MUX("ASP_TX1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[0]),
 461	SND_SOC_DAPM_MUX("ASP_TX2 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[1]),
 462	SND_SOC_DAPM_MUX("ASP_TX3 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[2]),
 463	SND_SOC_DAPM_MUX("ASP_TX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[3]),
 464	SND_SOC_DAPM_MUX("ASP_TX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[4]),
 465
 466	SND_SOC_DAPM_MUX("DSP_RX1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[0]),
 467	SND_SOC_DAPM_MUX("DSP_RX2 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[1]),
 468	SND_SOC_DAPM_MUX("DSP_RX3 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[2]),
 469	SND_SOC_DAPM_MUX("DSP_RX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[3]),
 470	SND_SOC_DAPM_MUX("DSP_RX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[4]),
 471	SND_SOC_DAPM_MUX("DSP_RX6 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[5]),
 472	SND_SOC_DAPM_MUX("DSP_RX7 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[6]),
 473	SND_SOC_DAPM_MUX("DSP_RX8 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[7]),
 474
 475	SND_SOC_DAPM_MUX("DACPCM Source", SND_SOC_NOPM, 0, 0, &cs35l45_dac_muxes[0]),
 476
 477	SND_SOC_DAPM_SWITCH("AMP Enable", SND_SOC_NOPM, 0, 0, &amp_en_ctl),
 478
 479	SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0),
 480
 481	SND_SOC_DAPM_OUTPUT("SPK"),
 482};
 483
 484#define CS35L45_ASP_MUX_ROUTE(name) \
 485	{ name" Source", "ASP_RX1",	 "ASP_RX1" }, \
 486	{ name" Source", "ASP_RX2",	 "ASP_RX2" }, \
 487	{ name" Source", "DSP_TX1",	 "DSP1" }, \
 488	{ name" Source", "DSP_TX2",	 "DSP1" }, \
 489	{ name" Source", "VMON",	 "VMON" }, \
 490	{ name" Source", "IMON",	 "IMON" }, \
 491	{ name" Source", "ERR_VOL",	 "ERR_VOL" }, \
 492	{ name" Source", "VDD_BATTMON",	 "VDD_BATTMON" }, \
 493	{ name" Source", "VDD_BSTMON",	 "VDD_BSTMON" }, \
 494	{ name" Source", "Interpolator", "AMP_INTP" }, \
 495	{ name" Source", "IL_TARGET",	 "IL_TARGET" }
 496
 497#define CS35L45_DSP_MUX_ROUTE(name) \
 498	{ name" Source", "ASP_RX1",	"ASP_RX1" }, \
 499	{ name" Source", "ASP_RX2",	"ASP_RX2" }
 500
 501#define CS35L45_DAC_MUX_ROUTE(name) \
 502	{ name" Source", "ASP_RX1",	"ASP_RX1" }, \
 503	{ name" Source", "ASP_RX2",	"ASP_RX2" }, \
 504	{ name" Source", "DSP_TX1",	"DSP1" }, \
 505	{ name" Source", "DSP_TX2",	"DSP1" }
 506
 507static const struct snd_soc_dapm_route cs35l45_dapm_routes[] = {
 508	/* Feedback */
 509	{ "VMON", NULL, "VMON_SRC" },
 510	{ "IMON", NULL, "IMON_SRC" },
 511	{ "TEMPMON", NULL, "TEMPMON_SRC" },
 512	{ "VDD_BATTMON", NULL, "VDD_BATTMON_SRC" },
 513	{ "VDD_BSTMON", NULL, "VDD_BSTMON_SRC" },
 514
 515	{ "VMON", NULL, "VMON_EN" },
 516	{ "IMON", NULL, "IMON_EN" },
 517	{ "TEMPMON", NULL, "TEMPMON_EN" },
 518	{ "VDD_BATTMON", NULL, "VDD_BATTMON_EN" },
 519	{ "VDD_BSTMON", NULL, "VDD_BSTMON_EN" },
 520
 521	{ "Capture", NULL, "ASP_TX1"},
 522	{ "Capture", NULL, "ASP_TX2"},
 523	{ "Capture", NULL, "ASP_TX3"},
 524	{ "Capture", NULL, "ASP_TX4"},
 525	{ "Capture", NULL, "ASP_TX5"},
 526	{ "ASP_TX1", NULL, "ASP_TX1 Source"},
 527	{ "ASP_TX2", NULL, "ASP_TX2 Source"},
 528	{ "ASP_TX3", NULL, "ASP_TX3 Source"},
 529	{ "ASP_TX4", NULL, "ASP_TX4 Source"},
 530	{ "ASP_TX5", NULL, "ASP_TX5 Source"},
 531
 532	{ "ASP_TX1", NULL, "ASP_EN" },
 533	{ "ASP_TX2", NULL, "ASP_EN" },
 534	{ "ASP_TX3", NULL, "ASP_EN" },
 535	{ "ASP_TX4", NULL, "ASP_EN" },
 536	{ "ASP_TX1", NULL, "GLOBAL_EN" },
 537	{ "ASP_TX2", NULL, "GLOBAL_EN" },
 538	{ "ASP_TX3", NULL, "GLOBAL_EN" },
 539	{ "ASP_TX4", NULL, "GLOBAL_EN" },
 540	{ "ASP_TX5", NULL, "GLOBAL_EN" },
 541
 542	CS35L45_ASP_MUX_ROUTE("ASP_TX1"),
 543	CS35L45_ASP_MUX_ROUTE("ASP_TX2"),
 544	CS35L45_ASP_MUX_ROUTE("ASP_TX3"),
 545	CS35L45_ASP_MUX_ROUTE("ASP_TX4"),
 546	CS35L45_ASP_MUX_ROUTE("ASP_TX5"),
 547
 548	/* Playback */
 549	{ "ASP_RX1", NULL, "Playback" },
 550	{ "ASP_RX2", NULL, "Playback" },
 551	{ "ASP_RX1", NULL, "ASP_EN" },
 552	{ "ASP_RX2", NULL, "ASP_EN" },
 553
 554	{ "AMP", NULL, "DACPCM Source"},
 555	{ "AMP", NULL, "GLOBAL_EN"},
 556
 557	CS35L45_DSP_MUX_ROUTE("DSP_RX1"),
 558	CS35L45_DSP_MUX_ROUTE("DSP_RX2"),
 559	CS35L45_DSP_MUX_ROUTE("DSP_RX3"),
 560	CS35L45_DSP_MUX_ROUTE("DSP_RX4"),
 561	CS35L45_DSP_MUX_ROUTE("DSP_RX5"),
 562	CS35L45_DSP_MUX_ROUTE("DSP_RX6"),
 563	CS35L45_DSP_MUX_ROUTE("DSP_RX7"),
 564	CS35L45_DSP_MUX_ROUTE("DSP_RX8"),
 565
 566	{"DSP1", NULL, "DSP_RX1 Source"},
 567	{"DSP1", NULL, "DSP_RX2 Source"},
 568	{"DSP1", NULL, "DSP_RX3 Source"},
 569	{"DSP1", NULL, "DSP_RX4 Source"},
 570	{"DSP1", NULL, "DSP_RX5 Source"},
 571	{"DSP1", NULL, "DSP_RX6 Source"},
 572	{"DSP1", NULL, "DSP_RX7 Source"},
 573	{"DSP1", NULL, "DSP_RX8 Source"},
 574
 575	{"DSP1", NULL, "VMON_EN"},
 576	{"DSP1", NULL, "IMON_EN"},
 577	{"DSP1", NULL, "VDD_BATTMON_EN"},
 578	{"DSP1", NULL, "VDD_BSTMON_EN"},
 579	{"DSP1", NULL, "TEMPMON_EN"},
 580
 581	{"DSP1 Preload", NULL, "DSP1 Preloader"},
 582	{"DSP1", NULL, "DSP1 Preloader"},
 583
 584	CS35L45_DAC_MUX_ROUTE("DACPCM"),
 585
 586	{ "AMP Enable", "Switch", "AMP" },
 587	{ "SPK", NULL, "AMP Enable"},
 588};
 589
 590static const char * const amplifier_mode_texts[] = {"SPK", "RCV"};
 591static SOC_ENUM_SINGLE_DECL(amplifier_mode_enum, SND_SOC_NOPM, 0,
 592			    amplifier_mode_texts);
 593static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 1000, 300, 0);
 594static const DECLARE_TLV_DB_SCALE(cs35l45_dig_pcm_vol_tlv, -10225, 25, true);
 595
 596static const struct snd_kcontrol_new cs35l45_controls[] = {
 597	SOC_ENUM_EXT("Amplifier Mode", amplifier_mode_enum,
 598		     cs35l45_amplifier_mode_get, cs35l45_amplifier_mode_put),
 599	SOC_SINGLE_TLV("Analog PCM Volume", CS35L45_AMP_GAIN,
 600			CS35L45_AMP_GAIN_PCM_SHIFT,
 601			CS35L45_AMP_GAIN_PCM_MASK >> CS35L45_AMP_GAIN_PCM_SHIFT,
 602			0, amp_gain_tlv),
 603	/* Ignore bit 0: it is beyond the resolution of TLV_DB_SCALE */
 604	SOC_SINGLE_S_TLV("Digital PCM Volume",
 605			 CS35L45_AMP_PCM_CONTROL,
 606			 CS35L45_AMP_VOL_PCM_SHIFT + 1,
 607			 -409, 48,
 608			 (CS35L45_AMP_VOL_PCM_WIDTH - 1) - 1,
 609			 0, cs35l45_dig_pcm_vol_tlv),
 610	WM_ADSP2_PRELOAD_SWITCH("DSP1", 1),
 611	WM_ADSP_FW_CONTROL("DSP1", 0),
 612};
 613
 614static int cs35l45_set_pll(struct cs35l45_private *cs35l45, unsigned int freq)
 615{
 616	unsigned int val;
 617	int freq_id;
 618
 619	freq_id = cs35l45_get_clk_freq_id(freq);
 620	if (freq_id < 0) {
 621		dev_err(cs35l45->dev, "Invalid freq: %u\n", freq);
 622		return -EINVAL;
 623	}
 624
 625	regmap_read(cs35l45->regmap, CS35L45_REFCLK_INPUT, &val);
 626	val = (val & CS35L45_PLL_REFCLK_FREQ_MASK) >> CS35L45_PLL_REFCLK_FREQ_SHIFT;
 627	if (val == freq_id)
 628		return 0;
 629
 630	regmap_set_bits(cs35l45->regmap, CS35L45_REFCLK_INPUT, CS35L45_PLL_OPEN_LOOP_MASK);
 631	regmap_update_bits(cs35l45->regmap, CS35L45_REFCLK_INPUT,
 632			   CS35L45_PLL_REFCLK_FREQ_MASK,
 633			   freq_id << CS35L45_PLL_REFCLK_FREQ_SHIFT);
 634	regmap_clear_bits(cs35l45->regmap, CS35L45_REFCLK_INPUT, CS35L45_PLL_REFCLK_EN_MASK);
 635	regmap_clear_bits(cs35l45->regmap, CS35L45_REFCLK_INPUT, CS35L45_PLL_OPEN_LOOP_MASK);
 636	regmap_set_bits(cs35l45->regmap, CS35L45_REFCLK_INPUT, CS35L45_PLL_REFCLK_EN_MASK);
 637
 638	return 0;
 639}
 640
 641static int cs35l45_asp_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 642{
 643	struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(codec_dai->component);
 644	unsigned int asp_fmt, fsync_inv, bclk_inv;
 645
 646	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
 647	case SND_SOC_DAIFMT_CBC_CFC:
 648		break;
 649	default:
 650		dev_err(cs35l45->dev, "Invalid DAI clocking\n");
 651		return -EINVAL;
 652	}
 653
 654	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 655	case SND_SOC_DAIFMT_DSP_A:
 656		asp_fmt = CS35l45_ASP_FMT_DSP_A;
 657		break;
 658	case SND_SOC_DAIFMT_I2S:
 659		asp_fmt = CS35L45_ASP_FMT_I2S;
 660		break;
 661	default:
 662		dev_err(cs35l45->dev, "Invalid DAI format\n");
 663		return -EINVAL;
 664	}
 665
 666	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 667	case SND_SOC_DAIFMT_NB_IF:
 668		fsync_inv = 1;
 669		bclk_inv = 0;
 670		break;
 671	case SND_SOC_DAIFMT_IB_NF:
 672		fsync_inv = 0;
 673		bclk_inv = 1;
 674		break;
 675	case SND_SOC_DAIFMT_IB_IF:
 676		fsync_inv = 1;
 677		bclk_inv = 1;
 678		break;
 679	case SND_SOC_DAIFMT_NB_NF:
 680		fsync_inv = 0;
 681		bclk_inv = 0;
 682		break;
 683	default:
 684		dev_warn(cs35l45->dev, "Invalid DAI clock polarity\n");
 685		return -EINVAL;
 686	}
 687
 688	regmap_update_bits(cs35l45->regmap, CS35L45_ASP_CONTROL2,
 689			   CS35L45_ASP_FMT_MASK |
 690			   CS35L45_ASP_FSYNC_INV_MASK |
 691			   CS35L45_ASP_BCLK_INV_MASK,
 692			   (asp_fmt << CS35L45_ASP_FMT_SHIFT) |
 693			   (fsync_inv << CS35L45_ASP_FSYNC_INV_SHIFT) |
 694			   (bclk_inv << CS35L45_ASP_BCLK_INV_SHIFT));
 695
 696	return 0;
 697}
 698
 699static int cs35l45_asp_hw_params(struct snd_pcm_substream *substream,
 700				 struct snd_pcm_hw_params *params,
 701				 struct snd_soc_dai *dai)
 702{
 703	struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(dai->component);
 704	unsigned int asp_width, asp_wl, global_fs, slot_multiple, asp_fmt;
 705	int bclk;
 706
 707	switch (params_rate(params)) {
 708	case 44100:
 709		global_fs = CS35L45_44P100_KHZ;
 710		break;
 711	case 48000:
 712		global_fs = CS35L45_48P0_KHZ;
 713		break;
 714	case 88200:
 715		global_fs = CS35L45_88P200_KHZ;
 716		break;
 717	case 96000:
 718		global_fs = CS35L45_96P0_KHZ;
 719		break;
 720	default:
 721		dev_warn(cs35l45->dev, "Unsupported sample rate (%d)\n",
 722			 params_rate(params));
 723		return -EINVAL;
 724	}
 725
 726	regmap_update_bits(cs35l45->regmap, CS35L45_GLOBAL_SAMPLE_RATE,
 727			   CS35L45_GLOBAL_FS_MASK,
 728			   global_fs << CS35L45_GLOBAL_FS_SHIFT);
 729
 730	asp_wl = params_width(params);
 731
 732	if (cs35l45->slot_width)
 733		asp_width = cs35l45->slot_width;
 734	else
 735		asp_width = params_width(params);
 736
 737	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 738		regmap_update_bits(cs35l45->regmap, CS35L45_ASP_CONTROL2,
 739				   CS35L45_ASP_WIDTH_RX_MASK,
 740				   asp_width << CS35L45_ASP_WIDTH_RX_SHIFT);
 741
 742		regmap_update_bits(cs35l45->regmap, CS35L45_ASP_DATA_CONTROL5,
 743				   CS35L45_ASP_WL_MASK,
 744				   asp_wl << CS35L45_ASP_WL_SHIFT);
 745	} else {
 746		regmap_update_bits(cs35l45->regmap, CS35L45_ASP_CONTROL2,
 747				   CS35L45_ASP_WIDTH_TX_MASK,
 748				   asp_width << CS35L45_ASP_WIDTH_TX_SHIFT);
 749
 750		regmap_update_bits(cs35l45->regmap, CS35L45_ASP_DATA_CONTROL1,
 751				   CS35L45_ASP_WL_MASK,
 752				   asp_wl << CS35L45_ASP_WL_SHIFT);
 753	}
 754
 755	if (cs35l45->sysclk_set)
 756		return 0;
 757
 758	/* I2S always has an even number of channels */
 759	regmap_read(cs35l45->regmap, CS35L45_ASP_CONTROL2, &asp_fmt);
 760	asp_fmt = (asp_fmt & CS35L45_ASP_FMT_MASK) >> CS35L45_ASP_FMT_SHIFT;
 761	if (asp_fmt == CS35L45_ASP_FMT_I2S)
 762		slot_multiple = 2;
 763	else
 764		slot_multiple = 1;
 765
 766	bclk = snd_soc_tdm_params_to_bclk(params, asp_width,
 767					  cs35l45->slot_count, slot_multiple);
 768
 769	return cs35l45_set_pll(cs35l45, bclk);
 770}
 771
 772static int cs35l45_asp_set_tdm_slot(struct snd_soc_dai *dai,
 773				    unsigned int tx_mask, unsigned int rx_mask,
 774				    int slots, int slot_width)
 775{
 776	struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(dai->component);
 777
 778	if (slot_width && ((slot_width < 16) || (slot_width > 128)))
 779		return -EINVAL;
 780
 781	cs35l45->slot_width = slot_width;
 782	cs35l45->slot_count = slots;
 783
 784	return 0;
 785}
 786
 787static int cs35l45_asp_set_sysclk(struct snd_soc_dai *dai,
 788				  int clk_id, unsigned int freq, int dir)
 789{
 790	struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(dai->component);
 791	int ret;
 792
 793	if (clk_id != 0) {
 794		dev_err(cs35l45->dev, "Invalid clk_id %d\n", clk_id);
 795		return -EINVAL;
 796	}
 797
 798	cs35l45->sysclk_set = false;
 799	if (freq == 0)
 800		return 0;
 801
 802	ret = cs35l45_set_pll(cs35l45, freq);
 803	if (ret < 0)
 804		return -EINVAL;
 805
 806	cs35l45->sysclk_set = true;
 807
 808	return 0;
 809}
 810
 811static int cs35l45_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
 812{
 813	struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(dai->component);
 814	unsigned int global_fs, val, hpf_tune;
 815
 816	if (mute)
 817		return 0;
 818
 819	regmap_read(cs35l45->regmap, CS35L45_GLOBAL_SAMPLE_RATE, &global_fs);
 820	global_fs = (global_fs & CS35L45_GLOBAL_FS_MASK) >> CS35L45_GLOBAL_FS_SHIFT;
 821	switch (global_fs) {
 822	case CS35L45_44P100_KHZ:
 823		hpf_tune = CS35L45_HPF_44P1;
 824		break;
 825	case CS35L45_88P200_KHZ:
 826		hpf_tune = CS35L45_HPF_88P2;
 827		break;
 828	default:
 829		hpf_tune = CS35l45_HPF_DEFAULT;
 830		break;
 831	}
 832
 833	regmap_read(cs35l45->regmap, CS35L45_AMP_PCM_HPF_TST, &val);
 834	if (val != hpf_tune) {
 835		struct reg_sequence hpf_override_seq[] = {
 836			{ 0x00000040,			0x00000055 },
 837			{ 0x00000040,			0x000000AA },
 838			{ 0x00000044,			0x00000055 },
 839			{ 0x00000044,			0x000000AA },
 840			{ CS35L45_AMP_PCM_HPF_TST,	hpf_tune },
 841			{ 0x00000040,			0x00000000 },
 842			{ 0x00000044,			0x00000000 },
 843		};
 844		regmap_multi_reg_write(cs35l45->regmap, hpf_override_seq,
 845				       ARRAY_SIZE(hpf_override_seq));
 846	}
 847
 848	return 0;
 849}
 850
 851static const struct snd_soc_dai_ops cs35l45_asp_dai_ops = {
 852	.set_fmt = cs35l45_asp_set_fmt,
 853	.hw_params = cs35l45_asp_hw_params,
 854	.set_tdm_slot = cs35l45_asp_set_tdm_slot,
 855	.set_sysclk = cs35l45_asp_set_sysclk,
 856	.mute_stream = cs35l45_mute_stream,
 857};
 858
 859static struct snd_soc_dai_driver cs35l45_dai[] = {
 860	{
 861		.name = "cs35l45",
 862		.playback = {
 863			.stream_name = "Playback",
 864			.channels_min = 1,
 865			.channels_max = 2,
 866			.rates = CS35L45_RATES,
 867			.formats = CS35L45_FORMATS,
 868		},
 869		.capture = {
 870			.stream_name = "Capture",
 871			.channels_min = 1,
 872			.channels_max = 5,
 873			.rates = CS35L45_RATES,
 874			.formats = CS35L45_FORMATS,
 875		},
 876		.symmetric_rate = true,
 877		.symmetric_sample_bits = true,
 878		.ops = &cs35l45_asp_dai_ops,
 879	},
 880};
 881
 882static int cs35l45_component_probe(struct snd_soc_component *component)
 883{
 884	struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component);
 885
 886	return wm_adsp2_component_probe(&cs35l45->dsp, component);
 887}
 888
 889static void cs35l45_component_remove(struct snd_soc_component *component)
 890{
 891	struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component);
 892
 893	wm_adsp2_component_remove(&cs35l45->dsp, component);
 894}
 895
 896static const struct snd_soc_component_driver cs35l45_component = {
 897	.probe = cs35l45_component_probe,
 898	.remove = cs35l45_component_remove,
 899
 900	.dapm_widgets = cs35l45_dapm_widgets,
 901	.num_dapm_widgets = ARRAY_SIZE(cs35l45_dapm_widgets),
 902
 903	.dapm_routes = cs35l45_dapm_routes,
 904	.num_dapm_routes = ARRAY_SIZE(cs35l45_dapm_routes),
 905
 906	.controls = cs35l45_controls,
 907	.num_controls = ARRAY_SIZE(cs35l45_controls),
 908
 909	.name = "cs35l45",
 910
 911	.endianness = 1,
 912};
 913
 914static void cs35l45_setup_hibernate(struct cs35l45_private *cs35l45)
 915{
 916	unsigned int wksrc;
 917
 918	if (cs35l45->bus_type == CONTROL_BUS_I2C)
 919		wksrc = CS35L45_WKSRC_I2C;
 920	else
 921		wksrc = CS35L45_WKSRC_SPI;
 922
 923	regmap_update_bits(cs35l45->regmap, CS35L45_WAKESRC_CTL,
 924			   CS35L45_WKSRC_EN_MASK,
 925			   wksrc << CS35L45_WKSRC_EN_SHIFT);
 926
 927	regmap_set_bits(cs35l45->regmap, CS35L45_WAKESRC_CTL,
 928			   CS35L45_UPDT_WKCTL_MASK);
 929
 930	regmap_update_bits(cs35l45->regmap, CS35L45_WKI2C_CTL,
 931			   CS35L45_WKI2C_ADDR_MASK, cs35l45->i2c_addr);
 932
 933	regmap_set_bits(cs35l45->regmap, CS35L45_WKI2C_CTL,
 934			   CS35L45_UPDT_WKI2C_MASK);
 935}
 936
 937static int cs35l45_enter_hibernate(struct cs35l45_private *cs35l45)
 938{
 939	dev_dbg(cs35l45->dev, "Enter hibernate\n");
 940
 941	cs35l45_setup_hibernate(cs35l45);
 942
 943	regmap_set_bits(cs35l45->regmap, CS35L45_IRQ1_MASK_2, CS35L45_DSP_VIRT2_MBOX_MASK);
 944
 945	// Don't wait for ACK since bus activity would wake the device
 946	regmap_write(cs35l45->regmap, CS35L45_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE);
 947
 948	return 0;
 949}
 950
 951static int cs35l45_exit_hibernate(struct cs35l45_private *cs35l45)
 952{
 953	const int wake_retries = 20;
 954	const int sleep_retries = 5;
 955	int ret, i, j;
 956
 957	for (i = 0; i < sleep_retries; i++) {
 958		dev_dbg(cs35l45->dev, "Exit hibernate\n");
 959
 960		for (j = 0; j < wake_retries; j++) {
 961			ret = cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap,
 962					  CSPL_MBOX_CMD_OUT_OF_HIBERNATE);
 963			if (!ret) {
 964				dev_dbg(cs35l45->dev, "Wake success at cycle: %d\n", j);
 965				regmap_clear_bits(cs35l45->regmap, CS35L45_IRQ1_MASK_2,
 966						 CS35L45_DSP_VIRT2_MBOX_MASK);
 967				return 0;
 968			}
 969			usleep_range(100, 200);
 970		}
 971
 972		dev_err(cs35l45->dev, "Wake failed, re-enter hibernate: %d\n", ret);
 973
 974		cs35l45_setup_hibernate(cs35l45);
 975	}
 976
 977	dev_err(cs35l45->dev, "Timed out waking device\n");
 978
 979	return -ETIMEDOUT;
 980}
 981
 982static int cs35l45_runtime_suspend(struct device *dev)
 983{
 984	struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
 985
 986	if (!cs35l45->dsp.preloaded || !cs35l45->dsp.cs_dsp.running)
 987		return 0;
 988
 989	cs35l45_enter_hibernate(cs35l45);
 990
 991	regcache_cache_only(cs35l45->regmap, true);
 992	regcache_mark_dirty(cs35l45->regmap);
 993
 994	dev_dbg(cs35l45->dev, "Runtime suspended\n");
 995
 996	return 0;
 997}
 998
 999static int cs35l45_runtime_resume(struct device *dev)
1000{
1001	struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
1002	int ret;
1003
1004	if (!cs35l45->dsp.preloaded || !cs35l45->dsp.cs_dsp.running)
1005		return 0;
1006
1007	dev_dbg(cs35l45->dev, "Runtime resume\n");
1008
1009	regcache_cache_only(cs35l45->regmap, false);
1010
1011	ret = cs35l45_exit_hibernate(cs35l45);
1012	if (ret)
1013		return ret;
1014
1015	ret = regcache_sync(cs35l45->regmap);
1016	if (ret != 0)
1017		dev_warn(cs35l45->dev, "regcache_sync failed: %d\n", ret);
1018
1019	/* Clear global error status */
1020	regmap_clear_bits(cs35l45->regmap, CS35L45_ERROR_RELEASE, CS35L45_GLOBAL_ERR_RLS_MASK);
1021	regmap_set_bits(cs35l45->regmap, CS35L45_ERROR_RELEASE, CS35L45_GLOBAL_ERR_RLS_MASK);
1022	regmap_clear_bits(cs35l45->regmap, CS35L45_ERROR_RELEASE, CS35L45_GLOBAL_ERR_RLS_MASK);
1023	return ret;
1024}
1025
1026static int cs35l45_sys_suspend(struct device *dev)
1027{
1028	struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
1029
1030	dev_dbg(cs35l45->dev, "System suspend, disabling IRQ\n");
1031	disable_irq(cs35l45->irq);
1032
1033	return 0;
1034}
1035
1036static int cs35l45_sys_suspend_noirq(struct device *dev)
1037{
1038	struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
1039
1040	dev_dbg(cs35l45->dev, "Late system suspend, reenabling IRQ\n");
1041	enable_irq(cs35l45->irq);
1042
1043	return 0;
1044}
1045
1046static int cs35l45_sys_resume_noirq(struct device *dev)
1047{
1048	struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
1049
1050	dev_dbg(cs35l45->dev, "Early system resume, disabling IRQ\n");
1051	disable_irq(cs35l45->irq);
1052
1053	return 0;
1054}
1055
1056static int cs35l45_sys_resume(struct device *dev)
1057{
1058	struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
1059
1060	dev_dbg(cs35l45->dev, "System resume, reenabling IRQ\n");
1061	enable_irq(cs35l45->irq);
1062
1063	return 0;
1064}
1065
1066static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45)
1067{
1068	struct device_node *node = cs35l45->dev->of_node;
1069	unsigned int gpio_regs[] = {CS35L45_GPIO1_CTRL1, CS35L45_GPIO2_CTRL1,
1070				    CS35L45_GPIO3_CTRL1};
1071	unsigned int pad_regs[] = {CS35L45_SYNC_GPIO1,
1072				   CS35L45_INTB_GPIO2_MCLK_REF, CS35L45_GPIO3};
1073	struct device_node *child;
1074	unsigned int val;
1075	char of_name[32];
1076	int ret, i;
1077
1078	if (!node)
1079		return 0;
1080
1081	for (i = 0; i < CS35L45_NUM_GPIOS; i++) {
1082		sprintf(of_name, "cirrus,gpio-ctrl%d", i + 1);
1083		child = of_get_child_by_name(node, of_name);
1084		if (!child)
1085			continue;
1086
1087		ret = of_property_read_u32(child, "gpio-dir", &val);
1088		if (!ret)
1089			regmap_update_bits(cs35l45->regmap, gpio_regs[i],
1090					   CS35L45_GPIO_DIR_MASK,
1091					   val << CS35L45_GPIO_DIR_SHIFT);
1092
1093		ret = of_property_read_u32(child, "gpio-lvl", &val);
1094		if (!ret)
1095			regmap_update_bits(cs35l45->regmap, gpio_regs[i],
1096					   CS35L45_GPIO_LVL_MASK,
1097					   val << CS35L45_GPIO_LVL_SHIFT);
1098
1099		ret = of_property_read_u32(child, "gpio-op-cfg", &val);
1100		if (!ret)
1101			regmap_update_bits(cs35l45->regmap, gpio_regs[i],
1102					   CS35L45_GPIO_OP_CFG_MASK,
1103					   val << CS35L45_GPIO_OP_CFG_SHIFT);
1104
1105		ret = of_property_read_u32(child, "gpio-pol", &val);
1106		if (!ret)
1107			regmap_update_bits(cs35l45->regmap, gpio_regs[i],
1108					   CS35L45_GPIO_POL_MASK,
1109					   val << CS35L45_GPIO_POL_SHIFT);
1110
1111		ret = of_property_read_u32(child, "gpio-ctrl", &val);
1112		if (!ret)
1113			regmap_update_bits(cs35l45->regmap, pad_regs[i],
1114					   CS35L45_GPIO_CTRL_MASK,
1115					   val << CS35L45_GPIO_CTRL_SHIFT);
1116
1117		ret = of_property_read_u32(child, "gpio-invert", &val);
1118		if (!ret) {
1119			regmap_update_bits(cs35l45->regmap, pad_regs[i],
1120					   CS35L45_GPIO_INVERT_MASK,
1121					   val << CS35L45_GPIO_INVERT_SHIFT);
1122			if (i == 1)
1123				cs35l45->irq_invert = val;
1124		}
1125
1126		of_node_put(child);
1127	}
1128
1129	if (device_property_read_u32(cs35l45->dev,
1130				     "cirrus,asp-sdout-hiz-ctrl", &val) == 0) {
1131		regmap_update_bits(cs35l45->regmap, CS35L45_ASP_CONTROL3,
1132				   CS35L45_ASP_DOUT_HIZ_CTRL_MASK,
1133				   val << CS35L45_ASP_DOUT_HIZ_CTRL_SHIFT);
1134	}
1135
1136	return 0;
1137}
1138
1139static int cs35l45_dsp_virt2_mbox3_irq_handle(struct cs35l45_private *cs35l45,
1140					      const unsigned int cmd,
1141					      unsigned int data)
1142{
1143	static char *speak_status = "Unknown";
1144
1145	switch (cmd) {
1146	case EVENT_SPEAKER_STATUS:
1147		switch (data) {
1148		case 1:
1149			speak_status = "All Clear";
1150			break;
1151		case 2:
1152			speak_status = "Open Circuit";
1153			break;
1154		case 4:
1155			speak_status = "Short Circuit";
1156			break;
1157		}
1158
1159		dev_info(cs35l45->dev, "MBOX event (SPEAKER_STATUS): %s\n",
1160			 speak_status);
1161		break;
1162	case EVENT_BOOT_DONE:
1163		dev_dbg(cs35l45->dev, "MBOX event (BOOT_DONE)\n");
1164		break;
1165	default:
1166		dev_err(cs35l45->dev, "MBOX event not supported %u\n", cmd);
1167		return -EINVAL;
1168	}
1169
1170	return 0;
1171}
1172
1173static irqreturn_t cs35l45_dsp_virt2_mbox_cb(int irq, void *data)
1174{
1175	struct cs35l45_private *cs35l45 = data;
1176	unsigned int mbox_val;
1177	int ret = 0;
1178
1179	ret = regmap_read(cs35l45->regmap, CS35L45_DSP_VIRT2_MBOX_3, &mbox_val);
1180	if (!ret && mbox_val)
1181		cs35l45_dsp_virt2_mbox3_irq_handle(cs35l45, mbox_val & CS35L45_MBOX3_CMD_MASK,
1182				(mbox_val & CS35L45_MBOX3_DATA_MASK) >> CS35L45_MBOX3_DATA_SHIFT);
1183
1184	/* Handle DSP trace log IRQ */
1185	ret = regmap_read(cs35l45->regmap, CS35L45_DSP_VIRT2_MBOX_4, &mbox_val);
1186	if (!ret && mbox_val != 0) {
1187		dev_err(cs35l45->dev, "Spurious DSP MBOX4 IRQ\n");
1188	}
1189
1190	return IRQ_RETVAL(ret);
1191}
1192
1193static irqreturn_t cs35l45_pll_unlock(int irq, void *data)
1194{
1195	struct cs35l45_private *cs35l45 = data;
1196
1197	dev_dbg(cs35l45->dev, "PLL unlock detected!");
1198
1199	return IRQ_HANDLED;
1200}
1201
1202static irqreturn_t cs35l45_pll_lock(int irq, void *data)
1203{
1204	struct cs35l45_private *cs35l45 = data;
1205
1206	dev_dbg(cs35l45->dev, "PLL lock detected!");
1207
1208	return IRQ_HANDLED;
1209}
1210
1211static irqreturn_t cs35l45_spk_safe_err(int irq, void *data);
1212
1213static const struct cs35l45_irq cs35l45_irqs[] = {
1214	CS35L45_IRQ(AMP_SHORT_ERR, "Amplifier short error", cs35l45_spk_safe_err),
1215	CS35L45_IRQ(UVLO_VDDBATT_ERR, "VDDBATT undervoltage error", cs35l45_spk_safe_err),
1216	CS35L45_IRQ(BST_SHORT_ERR, "Boost inductor error", cs35l45_spk_safe_err),
1217	CS35L45_IRQ(BST_UVP_ERR, "Boost undervoltage error", cs35l45_spk_safe_err),
1218	CS35L45_IRQ(TEMP_ERR, "Overtemperature error", cs35l45_spk_safe_err),
1219	CS35L45_IRQ(AMP_CAL_ERR, "Amplifier calibration error", cs35l45_spk_safe_err),
1220	CS35L45_IRQ(UVLO_VDDLV_ERR, "LV threshold detector error", cs35l45_spk_safe_err),
1221	CS35L45_IRQ(GLOBAL_ERROR, "Global error", cs35l45_spk_safe_err),
1222	CS35L45_IRQ(DSP_WDT_EXPIRE, "DSP Watchdog Timer", cs35l45_spk_safe_err),
1223	CS35L45_IRQ(PLL_UNLOCK_FLAG_RISE, "PLL unlock", cs35l45_pll_unlock),
1224	CS35L45_IRQ(PLL_LOCK_FLAG, "PLL lock", cs35l45_pll_lock),
1225	CS35L45_IRQ(DSP_VIRT2_MBOX, "DSP virtual MBOX 2 write flag", cs35l45_dsp_virt2_mbox_cb),
1226};
1227
1228static irqreturn_t cs35l45_spk_safe_err(int irq, void *data)
1229{
1230	struct cs35l45_private *cs35l45 = data;
1231	int i;
1232
1233	i = irq - regmap_irq_get_virq(cs35l45->irq_data, 0);
1234
1235	if (i < 0 || i >= ARRAY_SIZE(cs35l45_irqs))
1236		dev_err(cs35l45->dev, "Unspecified global error condition (%d) detected!\n", irq);
1237	else
1238		dev_err(cs35l45->dev, "%s condition detected!\n", cs35l45_irqs[i].name);
1239
1240	return IRQ_HANDLED;
1241}
1242
1243static const struct regmap_irq cs35l45_reg_irqs[] = {
1244	CS35L45_REG_IRQ(IRQ1_EINT_1, AMP_SHORT_ERR),
1245	CS35L45_REG_IRQ(IRQ1_EINT_1, UVLO_VDDBATT_ERR),
1246	CS35L45_REG_IRQ(IRQ1_EINT_1, BST_SHORT_ERR),
1247	CS35L45_REG_IRQ(IRQ1_EINT_1, BST_UVP_ERR),
1248	CS35L45_REG_IRQ(IRQ1_EINT_1, TEMP_ERR),
1249	CS35L45_REG_IRQ(IRQ1_EINT_3, AMP_CAL_ERR),
1250	CS35L45_REG_IRQ(IRQ1_EINT_18, UVLO_VDDLV_ERR),
1251	CS35L45_REG_IRQ(IRQ1_EINT_18, GLOBAL_ERROR),
1252	CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_WDT_EXPIRE),
1253	CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_UNLOCK_FLAG_RISE),
1254	CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_LOCK_FLAG),
1255	CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_VIRT2_MBOX),
1256};
1257
1258static const struct regmap_irq_chip cs35l45_regmap_irq_chip = {
1259	.name = "cs35l45 IRQ1 Controller",
1260	.main_status = CS35L45_IRQ1_STATUS,
1261	.status_base = CS35L45_IRQ1_EINT_1,
1262	.mask_base = CS35L45_IRQ1_MASK_1,
1263	.ack_base = CS35L45_IRQ1_EINT_1,
1264	.num_regs = 18,
1265	.irqs = cs35l45_reg_irqs,
1266	.num_irqs = ARRAY_SIZE(cs35l45_reg_irqs),
1267	.runtime_pm = true,
1268};
1269
1270static int cs35l45_initialize(struct cs35l45_private *cs35l45)
1271{
1272	struct device *dev = cs35l45->dev;
1273	unsigned int dev_id[5];
1274	unsigned int sts;
1275	int ret;
1276
1277	ret = regmap_read_poll_timeout(cs35l45->regmap, CS35L45_IRQ1_EINT_4, sts,
1278				       (sts & CS35L45_OTP_BOOT_DONE_STS_MASK),
1279				       1000, 5000);
1280	if (ret < 0) {
1281		dev_err(cs35l45->dev, "Timeout waiting for OTP boot\n");
1282		return ret;
1283	}
1284
1285	ret = regmap_bulk_read(cs35l45->regmap, CS35L45_DEVID, dev_id, ARRAY_SIZE(dev_id));
1286	if (ret) {
1287		dev_err(cs35l45->dev, "Get Device ID failed: %d\n", ret);
1288		return ret;
1289	}
1290
1291	switch (dev_id[0]) {
1292	case 0x35A450:
1293	case 0x35A460:
1294		break;
1295	default:
1296		dev_err(cs35l45->dev, "Bad DEVID 0x%x\n", dev_id[0]);
1297		return -ENODEV;
1298	}
1299
1300	dev_info(cs35l45->dev, "Cirrus Logic CS35L45: REVID %02X OTPID %02X\n",
1301		 dev_id[1], dev_id[4]);
1302
1303	regmap_write(cs35l45->regmap, CS35L45_IRQ1_EINT_4,
1304		     CS35L45_OTP_BOOT_DONE_STS_MASK | CS35L45_OTP_BUSY_MASK);
1305
1306	ret = cs35l45_apply_patch(cs35l45);
1307	if (ret < 0) {
1308		dev_err(dev, "Failed to apply init patch %d\n", ret);
1309		return ret;
1310	}
1311
1312	ret = cs35l45_apply_property_config(cs35l45);
1313	if (ret < 0)
1314		return ret;
1315
1316	cs35l45->amplifier_mode = AMP_MODE_SPK;
1317
1318	return 0;
1319}
1320
1321static const struct reg_sequence cs35l45_fs_errata_patch[] = {
1322	{0x02B80080,			0x00000001},
1323	{0x02B80088,			0x00000001},
1324	{0x02B80090,			0x00000001},
1325	{0x02B80098,			0x00000001},
1326	{0x02B800A0,			0x00000001},
1327	{0x02B800A8,			0x00000001},
1328	{0x02B800B0,			0x00000001},
1329	{0x02B800B8,			0x00000001},
1330	{0x02B80280,			0x00000001},
1331	{0x02B80288,			0x00000001},
1332	{0x02B80290,			0x00000001},
1333	{0x02B80298,			0x00000001},
1334	{0x02B802A0,			0x00000001},
1335	{0x02B802A8,			0x00000001},
1336	{0x02B802B0,			0x00000001},
1337	{0x02B802B8,			0x00000001},
1338};
1339
1340static const struct cs_dsp_region cs35l45_dsp1_regions[] = {
1341	{ .type = WMFW_HALO_PM_PACKED,	.base = CS35L45_DSP1_PMEM_0 },
1342	{ .type = WMFW_HALO_XM_PACKED,	.base = CS35L45_DSP1_XMEM_PACK_0 },
1343	{ .type = WMFW_HALO_YM_PACKED,	.base = CS35L45_DSP1_YMEM_PACK_0 },
1344	{. type = WMFW_ADSP2_XM,	.base = CS35L45_DSP1_XMEM_UNPACK24_0},
1345	{. type = WMFW_ADSP2_YM,	.base = CS35L45_DSP1_YMEM_UNPACK24_0},
1346};
1347
1348static int cs35l45_dsp_init(struct cs35l45_private *cs35l45)
1349{
1350	struct wm_adsp *dsp = &cs35l45->dsp;
1351	int ret;
1352
1353	dsp->part = "cs35l45";
1354	dsp->fw = 9; /* 9 is WM_ADSP_FW_SPK_PROT in wm_adsp.c */
1355	dsp->toggle_preload = true;
1356	dsp->cs_dsp.num = 1;
1357	dsp->cs_dsp.type = WMFW_HALO;
1358	dsp->cs_dsp.rev = 0;
1359	dsp->cs_dsp.dev = cs35l45->dev;
1360	dsp->cs_dsp.regmap = cs35l45->regmap;
1361	dsp->cs_dsp.base = CS35L45_DSP1_CLOCK_FREQ;
1362	dsp->cs_dsp.base_sysinfo = CS35L45_DSP1_SYS_ID;
1363	dsp->cs_dsp.mem = cs35l45_dsp1_regions;
1364	dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l45_dsp1_regions);
1365	dsp->cs_dsp.lock_regions = 0xFFFFFFFF;
1366
1367	ret = wm_halo_init(dsp);
1368
1369	regmap_multi_reg_write(cs35l45->regmap, cs35l45_fs_errata_patch,
1370						   ARRAY_SIZE(cs35l45_fs_errata_patch));
1371
1372	return ret;
1373}
1374
1375int cs35l45_probe(struct cs35l45_private *cs35l45)
1376{
1377	struct device *dev = cs35l45->dev;
1378	unsigned long irq_pol = IRQF_ONESHOT | IRQF_SHARED;
1379	int ret, i, irq;
1380
1381	cs35l45->vdd_batt = devm_regulator_get(dev, "vdd-batt");
1382	if (IS_ERR(cs35l45->vdd_batt))
1383		return dev_err_probe(dev, PTR_ERR(cs35l45->vdd_batt),
1384				     "Failed to request vdd-batt\n");
1385
1386	cs35l45->vdd_a = devm_regulator_get(dev, "vdd-a");
1387	if (IS_ERR(cs35l45->vdd_a))
1388		return dev_err_probe(dev, PTR_ERR(cs35l45->vdd_a),
1389				     "Failed to request vdd-a\n");
1390
1391	/* VDD_BATT must always be enabled before other supplies */
1392	ret = regulator_enable(cs35l45->vdd_batt);
1393	if (ret < 0)
1394		return dev_err_probe(dev, ret, "Failed to enable vdd-batt\n");
1395
1396	ret = regulator_enable(cs35l45->vdd_a);
1397	if (ret < 0)
1398		return dev_err_probe(dev, ret, "Failed to enable vdd-a\n");
1399
1400	/* If reset is shared only one instance can claim it */
1401	cs35l45->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
1402	if (IS_ERR(cs35l45->reset_gpio)) {
1403		ret = PTR_ERR(cs35l45->reset_gpio);
1404		cs35l45->reset_gpio = NULL;
1405		if (ret == -EBUSY) {
1406			dev_dbg(dev, "Reset line busy, assuming shared reset\n");
1407		} else {
1408			dev_err_probe(dev, ret, "Failed to get reset GPIO\n");
1409			goto err;
1410		}
1411	}
1412
1413	if (cs35l45->reset_gpio) {
1414		usleep_range(CS35L45_RESET_HOLD_US, CS35L45_RESET_HOLD_US + 100);
1415		gpiod_set_value_cansleep(cs35l45->reset_gpio, 1);
1416	}
1417
1418	usleep_range(CS35L45_RESET_US, CS35L45_RESET_US + 100);
1419
1420	ret = cs35l45_initialize(cs35l45);
1421	if (ret < 0)
1422		goto err_reset;
1423
1424	ret = cs35l45_dsp_init(cs35l45);
1425	if (ret < 0)
1426		goto err_reset;
1427
1428	pm_runtime_set_autosuspend_delay(cs35l45->dev, 3000);
1429	pm_runtime_use_autosuspend(cs35l45->dev);
1430	pm_runtime_mark_last_busy(cs35l45->dev);
1431	pm_runtime_set_active(cs35l45->dev);
1432	pm_runtime_get_noresume(cs35l45->dev);
1433	pm_runtime_enable(cs35l45->dev);
1434
1435	if (cs35l45->irq) {
1436		if (cs35l45->irq_invert)
1437			irq_pol |= IRQF_TRIGGER_HIGH;
1438		else
1439			irq_pol |= IRQF_TRIGGER_LOW;
1440
1441		ret = devm_regmap_add_irq_chip(dev, cs35l45->regmap, cs35l45->irq, irq_pol, 0,
1442					       &cs35l45_regmap_irq_chip, &cs35l45->irq_data);
1443		if (ret) {
1444			dev_err(dev, "Failed to register IRQ chip: %d\n", ret);
1445			goto err_dsp;
1446		}
1447
1448		for (i = 0; i < ARRAY_SIZE(cs35l45_irqs); i++) {
1449			irq = regmap_irq_get_virq(cs35l45->irq_data, cs35l45_irqs[i].irq);
1450			if (irq < 0) {
1451				dev_err(dev, "Failed to get %s\n", cs35l45_irqs[i].name);
1452				ret = irq;
1453				goto err_dsp;
1454			}
1455
1456			ret = devm_request_threaded_irq(dev, irq, NULL, cs35l45_irqs[i].handler,
1457							irq_pol, cs35l45_irqs[i].name, cs35l45);
1458			if (ret) {
1459				dev_err(dev, "Failed to request IRQ %s: %d\n",
1460					cs35l45_irqs[i].name, ret);
1461				goto err_dsp;
1462			}
1463		}
1464	}
1465
1466	ret = devm_snd_soc_register_component(dev, &cs35l45_component,
1467					      cs35l45_dai,
1468					      ARRAY_SIZE(cs35l45_dai));
1469	if (ret < 0)
1470		goto err_dsp;
1471
1472	pm_runtime_put_autosuspend(cs35l45->dev);
1473
1474	return 0;
1475
1476err_dsp:
1477	pm_runtime_disable(cs35l45->dev);
1478	pm_runtime_put_noidle(cs35l45->dev);
1479	wm_adsp2_remove(&cs35l45->dsp);
1480
1481err_reset:
1482	gpiod_set_value_cansleep(cs35l45->reset_gpio, 0);
1483err:
1484	regulator_disable(cs35l45->vdd_a);
1485	regulator_disable(cs35l45->vdd_batt);
1486
1487	return ret;
1488}
1489EXPORT_SYMBOL_NS_GPL(cs35l45_probe, "SND_SOC_CS35L45");
1490
1491void cs35l45_remove(struct cs35l45_private *cs35l45)
1492{
1493	pm_runtime_get_sync(cs35l45->dev);
1494	pm_runtime_disable(cs35l45->dev);
1495	wm_adsp2_remove(&cs35l45->dsp);
1496
1497	gpiod_set_value_cansleep(cs35l45->reset_gpio, 0);
1498
1499	pm_runtime_put_noidle(cs35l45->dev);
1500	regulator_disable(cs35l45->vdd_a);
1501	/* VDD_BATT must be the last to power-off */
1502	regulator_disable(cs35l45->vdd_batt);
1503}
1504EXPORT_SYMBOL_NS_GPL(cs35l45_remove, "SND_SOC_CS35L45");
1505
1506EXPORT_GPL_DEV_PM_OPS(cs35l45_pm_ops) = {
1507	RUNTIME_PM_OPS(cs35l45_runtime_suspend, cs35l45_runtime_resume, NULL)
1508
1509	SYSTEM_SLEEP_PM_OPS(cs35l45_sys_suspend, cs35l45_sys_resume)
1510	NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l45_sys_suspend_noirq, cs35l45_sys_resume_noirq)
1511};
1512
1513MODULE_DESCRIPTION("ASoC CS35L45 driver");
1514MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
1515MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
1516MODULE_LICENSE("GPL");