Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: cs35l34: Initial commit of the cs35l34 CODEC driver.

Initial commit of the Cirrus Logic cs35l34 8V boosted class D
amplifier.

Signed-off-by: Paul Handrigan <Paul.Handrigan@cirrus.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Paul Handrigan and committed by
Mark Brown
c1124c09 e58dfab6

+1563
+35
include/sound/cs35l34.h
··· 1 + /* 2 + * linux/sound/cs35l34.h -- Platform data for CS35l34 3 + * 4 + * Copyright (c) 2016 Cirrus Logic Inc. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + #ifndef __CS35L34_H 12 + #define __CS35L34_H 13 + 14 + struct cs35l34_platform_data { 15 + /* Set AIF to half drive strength */ 16 + bool aif_half_drv; 17 + /* Digital Soft Ramp Disable */ 18 + bool digsft_disable; 19 + /* Amplifier Invert */ 20 + bool amp_inv; 21 + /* Peak current (mA) */ 22 + unsigned int boost_peak; 23 + /* Boost inductor value (nH) */ 24 + unsigned int boost_ind; 25 + /* Boost Controller Voltage Setting (mV) */ 26 + unsigned int boost_vtge; 27 + /* Gain Change Zero Cross */ 28 + bool gain_zc_disable; 29 + /* SDIN Left/Right Selection */ 30 + unsigned int i2s_sdinloc; 31 + /* TDM Rising Edge */ 32 + bool tdm_rising_edge; 33 + }; 34 + 35 + #endif /* __CS35L34_H */
+5
sound/soc/codecs/Kconfig
··· 48 48 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC 49 49 select SND_SOC_CS35L32 if I2C 50 50 select SND_SOC_CS35L33 if I2C 51 + select SND_SOC_CS35L34 if I2C 51 52 select SND_SOC_CS42L51_I2C if I2C 52 53 select SND_SOC_CS42L52 if I2C && INPUT 53 54 select SND_SOC_CS42L56 if I2C && INPUT ··· 398 397 399 398 config SND_SOC_CS35L33 400 399 tristate "Cirrus Logic CS35L33 CODEC" 400 + depends on I2C 401 + 402 + config SND_SOC_CS35L34 403 + tristate "Cirrus Logic CS35L34 CODEC" 401 404 depends on I2C 402 405 403 406 config SND_SOC_CS42L51
+2
sound/soc/codecs/Makefile
··· 38 38 snd-soc-cq93vc-objs := cq93vc.o 39 39 snd-soc-cs35l32-objs := cs35l32.o 40 40 snd-soc-cs35l33-objs := cs35l33.o 41 + snd-soc-cs35l34-objs := cs35l34.o 41 42 snd-soc-cs42l51-objs := cs42l51.o 42 43 snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o 43 44 snd-soc-cs42l52-objs := cs42l52.o ··· 264 263 obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o 265 264 obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o 266 265 obj-$(CONFIG_SND_SOC_CS35L33) += snd-soc-cs35l33.o 266 + obj-$(CONFIG_SND_SOC_CS35L34) += snd-soc-cs35l34.o 267 267 obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o 268 268 obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o 269 269 obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
+1252
sound/soc/codecs/cs35l34.c
··· 1 + /* 2 + * cs35l34.c -- CS35l34 ALSA SoC audio driver 3 + * 4 + * Copyright 2016 Cirrus Logic, Inc. 5 + * 6 + * Author: Paul Handrigan <Paul.Handrigan@cirrus.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + * 12 + */ 13 + 14 + #include <linux/module.h> 15 + #include <linux/moduleparam.h> 16 + #include <linux/kernel.h> 17 + #include <linux/init.h> 18 + #include <linux/delay.h> 19 + #include <linux/i2c.h> 20 + #include <linux/slab.h> 21 + #include <linux/workqueue.h> 22 + #include <linux/platform_device.h> 23 + #include <linux/regulator/consumer.h> 24 + #include <linux/regulator/machine.h> 25 + #include <linux/pm_runtime.h> 26 + #include <linux/of_device.h> 27 + #include <linux/of_gpio.h> 28 + #include <linux/of_irq.h> 29 + #include <sound/core.h> 30 + #include <sound/pcm.h> 31 + #include <sound/pcm_params.h> 32 + #include <sound/soc.h> 33 + #include <sound/soc-dapm.h> 34 + #include <linux/gpio.h> 35 + #include <linux/gpio/consumer.h> 36 + #include <sound/initval.h> 37 + #include <sound/tlv.h> 38 + #include <sound/cs35l34.h> 39 + 40 + #include "cs35l34.h" 41 + 42 + #define PDN_DONE_ATTEMPTS 10 43 + #define CS35L34_START_DELAY 50 44 + 45 + struct cs35l34_private { 46 + struct snd_soc_codec *codec; 47 + struct cs35l34_platform_data pdata; 48 + struct regmap *regmap; 49 + struct regulator_bulk_data core_supplies[2]; 50 + int num_core_supplies; 51 + int mclk_int; 52 + bool tdm_mode; 53 + struct gpio_desc *reset_gpio; /* Active-low reset GPIO */ 54 + }; 55 + 56 + static const struct reg_default cs35l34_reg[] = { 57 + {CS35L34_PWRCTL1, 0x01}, 58 + {CS35L34_PWRCTL2, 0x19}, 59 + {CS35L34_PWRCTL3, 0x01}, 60 + {CS35L34_ADSP_CLK_CTL, 0x08}, 61 + {CS35L34_MCLK_CTL, 0x11}, 62 + {CS35L34_AMP_INP_DRV_CTL, 0x01}, 63 + {CS35L34_AMP_DIG_VOL_CTL, 0x12}, 64 + {CS35L34_AMP_DIG_VOL, 0x00}, 65 + {CS35L34_AMP_ANLG_GAIN_CTL, 0x0F}, 66 + {CS35L34_PROTECT_CTL, 0x06}, 67 + {CS35L34_AMP_KEEP_ALIVE_CTL, 0x04}, 68 + {CS35L34_BST_CVTR_V_CTL, 0x00}, 69 + {CS35L34_BST_PEAK_I, 0x10}, 70 + {CS35L34_BST_RAMP_CTL, 0x87}, 71 + {CS35L34_BST_CONV_COEF_1, 0x24}, 72 + {CS35L34_BST_CONV_COEF_2, 0x24}, 73 + {CS35L34_BST_CONV_SLOPE_COMP, 0x4E}, 74 + {CS35L34_BST_CONV_SW_FREQ, 0x08}, 75 + {CS35L34_CLASS_H_CTL, 0x0D}, 76 + {CS35L34_CLASS_H_HEADRM_CTL, 0x0D}, 77 + {CS35L34_CLASS_H_RELEASE_RATE, 0x08}, 78 + {CS35L34_CLASS_H_FET_DRIVE_CTL, 0x41}, 79 + {CS35L34_CLASS_H_STATUS, 0x05}, 80 + {CS35L34_VPBR_CTL, 0x0A}, 81 + {CS35L34_VPBR_VOL_CTL, 0x90}, 82 + {CS35L34_VPBR_TIMING_CTL, 0x6A}, 83 + {CS35L34_PRED_MAX_ATTEN_SPK_LOAD, 0x95}, 84 + {CS35L34_PRED_BROWNOUT_THRESH, 0x1C}, 85 + {CS35L34_PRED_BROWNOUT_VOL_CTL, 0x00}, 86 + {CS35L34_PRED_BROWNOUT_RATE_CTL, 0x10}, 87 + {CS35L34_PRED_WAIT_CTL, 0x10}, 88 + {CS35L34_PRED_ZVP_INIT_IMP_CTL, 0x08}, 89 + {CS35L34_PRED_MAN_SAFE_VPI_CTL, 0x80}, 90 + {CS35L34_VPBR_ATTEN_STATUS, 0x00}, 91 + {CS35L34_PRED_BRWNOUT_ATT_STATUS, 0x00}, 92 + {CS35L34_SPKR_MON_CTL, 0xC6}, 93 + {CS35L34_ADSP_I2S_CTL, 0x00}, 94 + {CS35L34_ADSP_TDM_CTL, 0x00}, 95 + {CS35L34_TDM_TX_CTL_1_VMON, 0x00}, 96 + {CS35L34_TDM_TX_CTL_2_IMON, 0x04}, 97 + {CS35L34_TDM_TX_CTL_3_VPMON, 0x03}, 98 + {CS35L34_TDM_TX_CTL_4_VBSTMON, 0x07}, 99 + {CS35L34_TDM_TX_CTL_5_FLAG1, 0x08}, 100 + {CS35L34_TDM_TX_CTL_6_FLAG2, 0x09}, 101 + {CS35L34_TDM_TX_SLOT_EN_1, 0x00}, 102 + {CS35L34_TDM_TX_SLOT_EN_2, 0x00}, 103 + {CS35L34_TDM_TX_SLOT_EN_3, 0x00}, 104 + {CS35L34_TDM_TX_SLOT_EN_4, 0x00}, 105 + {CS35L34_TDM_RX_CTL_1_AUDIN, 0x40}, 106 + {CS35L34_TDM_RX_CTL_3_ALIVE, 0x04}, 107 + {CS35L34_MULT_DEV_SYNCH1, 0x00}, 108 + {CS35L34_MULT_DEV_SYNCH2, 0x80}, 109 + {CS35L34_PROT_RELEASE_CTL, 0x00}, 110 + {CS35L34_DIAG_MODE_REG_LOCK, 0x00}, 111 + {CS35L34_DIAG_MODE_CTL_1, 0x00}, 112 + {CS35L34_DIAG_MODE_CTL_2, 0x00}, 113 + {CS35L34_INT_MASK_1, 0xFF}, 114 + {CS35L34_INT_MASK_2, 0xFF}, 115 + {CS35L34_INT_MASK_3, 0xFF}, 116 + {CS35L34_INT_MASK_4, 0xFF}, 117 + {CS35L34_INT_STATUS_1, 0x30}, 118 + {CS35L34_INT_STATUS_2, 0x05}, 119 + {CS35L34_INT_STATUS_3, 0x00}, 120 + {CS35L34_INT_STATUS_4, 0x00}, 121 + {CS35L34_OTP_TRIM_STATUS, 0x00}, 122 + }; 123 + 124 + static bool cs35l34_volatile_register(struct device *dev, unsigned int reg) 125 + { 126 + switch (reg) { 127 + case CS35L34_DEVID_AB: 128 + case CS35L34_DEVID_CD: 129 + case CS35L34_DEVID_E: 130 + case CS35L34_FAB_ID: 131 + case CS35L34_REV_ID: 132 + case CS35L34_INT_STATUS_1: 133 + case CS35L34_INT_STATUS_2: 134 + case CS35L34_INT_STATUS_3: 135 + case CS35L34_INT_STATUS_4: 136 + case CS35L34_CLASS_H_STATUS: 137 + case CS35L34_VPBR_ATTEN_STATUS: 138 + case CS35L34_OTP_TRIM_STATUS: 139 + return true; 140 + default: 141 + return false; 142 + } 143 + } 144 + 145 + static bool cs35l34_readable_register(struct device *dev, unsigned int reg) 146 + { 147 + switch (reg) { 148 + case CS35L34_CHIP_ID: 149 + case CS35L34_DEVID_AB: 150 + case CS35L34_DEVID_CD: 151 + case CS35L34_DEVID_E: 152 + case CS35L34_FAB_ID: 153 + case CS35L34_REV_ID: 154 + case CS35L34_PWRCTL1: 155 + case CS35L34_PWRCTL2: 156 + case CS35L34_PWRCTL3: 157 + case CS35L34_ADSP_CLK_CTL: 158 + case CS35L34_MCLK_CTL: 159 + case CS35L34_AMP_INP_DRV_CTL: 160 + case CS35L34_AMP_DIG_VOL_CTL: 161 + case CS35L34_AMP_DIG_VOL: 162 + case CS35L34_AMP_ANLG_GAIN_CTL: 163 + case CS35L34_PROTECT_CTL: 164 + case CS35L34_AMP_KEEP_ALIVE_CTL: 165 + case CS35L34_BST_CVTR_V_CTL: 166 + case CS35L34_BST_PEAK_I: 167 + case CS35L34_BST_RAMP_CTL: 168 + case CS35L34_BST_CONV_COEF_1: 169 + case CS35L34_BST_CONV_COEF_2: 170 + case CS35L34_BST_CONV_SLOPE_COMP: 171 + case CS35L34_BST_CONV_SW_FREQ: 172 + case CS35L34_CLASS_H_CTL: 173 + case CS35L34_CLASS_H_HEADRM_CTL: 174 + case CS35L34_CLASS_H_RELEASE_RATE: 175 + case CS35L34_CLASS_H_FET_DRIVE_CTL: 176 + case CS35L34_CLASS_H_STATUS: 177 + case CS35L34_VPBR_CTL: 178 + case CS35L34_VPBR_VOL_CTL: 179 + case CS35L34_VPBR_TIMING_CTL: 180 + case CS35L34_PRED_MAX_ATTEN_SPK_LOAD: 181 + case CS35L34_PRED_BROWNOUT_THRESH: 182 + case CS35L34_PRED_BROWNOUT_VOL_CTL: 183 + case CS35L34_PRED_BROWNOUT_RATE_CTL: 184 + case CS35L34_PRED_WAIT_CTL: 185 + case CS35L34_PRED_ZVP_INIT_IMP_CTL: 186 + case CS35L34_PRED_MAN_SAFE_VPI_CTL: 187 + case CS35L34_VPBR_ATTEN_STATUS: 188 + case CS35L34_PRED_BRWNOUT_ATT_STATUS: 189 + case CS35L34_SPKR_MON_CTL: 190 + case CS35L34_ADSP_I2S_CTL: 191 + case CS35L34_ADSP_TDM_CTL: 192 + case CS35L34_TDM_TX_CTL_1_VMON: 193 + case CS35L34_TDM_TX_CTL_2_IMON: 194 + case CS35L34_TDM_TX_CTL_3_VPMON: 195 + case CS35L34_TDM_TX_CTL_4_VBSTMON: 196 + case CS35L34_TDM_TX_CTL_5_FLAG1: 197 + case CS35L34_TDM_TX_CTL_6_FLAG2: 198 + case CS35L34_TDM_TX_SLOT_EN_1: 199 + case CS35L34_TDM_TX_SLOT_EN_2: 200 + case CS35L34_TDM_TX_SLOT_EN_3: 201 + case CS35L34_TDM_TX_SLOT_EN_4: 202 + case CS35L34_TDM_RX_CTL_1_AUDIN: 203 + case CS35L34_TDM_RX_CTL_3_ALIVE: 204 + case CS35L34_MULT_DEV_SYNCH1: 205 + case CS35L34_MULT_DEV_SYNCH2: 206 + case CS35L34_PROT_RELEASE_CTL: 207 + case CS35L34_DIAG_MODE_REG_LOCK: 208 + case CS35L34_DIAG_MODE_CTL_1: 209 + case CS35L34_DIAG_MODE_CTL_2: 210 + case CS35L34_INT_MASK_1: 211 + case CS35L34_INT_MASK_2: 212 + case CS35L34_INT_MASK_3: 213 + case CS35L34_INT_MASK_4: 214 + case CS35L34_INT_STATUS_1: 215 + case CS35L34_INT_STATUS_2: 216 + case CS35L34_INT_STATUS_3: 217 + case CS35L34_INT_STATUS_4: 218 + case CS35L34_OTP_TRIM_STATUS: 219 + return true; 220 + default: 221 + return false; 222 + } 223 + } 224 + 225 + static bool cs35l34_precious_register(struct device *dev, unsigned int reg) 226 + { 227 + switch (reg) { 228 + case CS35L34_INT_STATUS_1: 229 + case CS35L34_INT_STATUS_2: 230 + case CS35L34_INT_STATUS_3: 231 + case CS35L34_INT_STATUS_4: 232 + return true; 233 + default: 234 + return false; 235 + } 236 + } 237 + 238 + static int cs35l34_sdin_event(struct snd_soc_dapm_widget *w, 239 + struct snd_kcontrol *kcontrol, int event) 240 + { 241 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 242 + struct cs35l34_private *priv = snd_soc_codec_get_drvdata(codec); 243 + int ret; 244 + 245 + switch (event) { 246 + case SND_SOC_DAPM_PRE_PMU: 247 + if (priv->tdm_mode) 248 + regmap_update_bits(priv->regmap, CS35L34_PWRCTL3, 249 + CS35L34_PDN_TDM, 0x00); 250 + 251 + ret = regmap_update_bits(priv->regmap, CS35L34_PWRCTL1, 252 + CS35L34_PDN_ALL, 0); 253 + if (ret < 0) { 254 + dev_err(codec->dev, "Cannot set Power bits %d\n", ret); 255 + return ret; 256 + } 257 + usleep_range(5000, 5100); 258 + break; 259 + case SND_SOC_DAPM_POST_PMD: 260 + if (priv->tdm_mode) { 261 + regmap_update_bits(priv->regmap, CS35L34_PWRCTL3, 262 + CS35L34_PDN_TDM, CS35L34_PDN_TDM); 263 + } 264 + ret = regmap_update_bits(priv->regmap, CS35L34_PWRCTL1, 265 + CS35L34_PDN_ALL, CS35L34_PDN_ALL); 266 + break; 267 + default: 268 + pr_err("Invalid event = 0x%x\n", event); 269 + } 270 + return 0; 271 + } 272 + 273 + static int cs35l34_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 274 + unsigned int rx_mask, int slots, int slot_width) 275 + { 276 + struct snd_soc_codec *codec = dai->codec; 277 + struct cs35l34_private *priv = snd_soc_codec_get_drvdata(codec); 278 + unsigned int reg, bit_pos; 279 + int slot, slot_num; 280 + 281 + if (slot_width != 8) 282 + return -EINVAL; 283 + 284 + priv->tdm_mode = true; 285 + /* scan rx_mask for aud slot */ 286 + slot = ffs(rx_mask) - 1; 287 + if (slot >= 0) 288 + snd_soc_update_bits(codec, CS35L34_TDM_RX_CTL_1_AUDIN, 289 + CS35L34_X_LOC, slot); 290 + 291 + /* scan tx_mask: vmon(2 slots); imon (2 slots); vpmon (1 slot) 292 + * vbstmon (1 slot) 293 + */ 294 + slot = ffs(tx_mask) - 1; 295 + slot_num = 0; 296 + 297 + /* disable vpmon/vbstmon: enable later if set in tx_mask */ 298 + snd_soc_update_bits(codec, CS35L34_TDM_TX_CTL_3_VPMON, 299 + CS35L34_X_STATE | CS35L34_X_LOC, 300 + CS35L34_X_STATE | CS35L34_X_LOC); 301 + snd_soc_update_bits(codec, CS35L34_TDM_TX_CTL_4_VBSTMON, 302 + CS35L34_X_STATE | CS35L34_X_LOC, 303 + CS35L34_X_STATE | CS35L34_X_LOC); 304 + 305 + /* disconnect {vp,vbst}_mon routes: eanble later if set in tx_mask*/ 306 + while (slot >= 0) { 307 + /* configure VMON_TX_LOC */ 308 + if (slot_num == 0) 309 + snd_soc_update_bits(codec, CS35L34_TDM_TX_CTL_1_VMON, 310 + CS35L34_X_STATE | CS35L34_X_LOC, slot); 311 + 312 + /* configure IMON_TX_LOC */ 313 + if (slot_num == 4) { 314 + snd_soc_update_bits(codec, CS35L34_TDM_TX_CTL_2_IMON, 315 + CS35L34_X_STATE | CS35L34_X_LOC, slot); 316 + } 317 + /* configure VPMON_TX_LOC */ 318 + if (slot_num == 3) { 319 + snd_soc_update_bits(codec, CS35L34_TDM_TX_CTL_3_VPMON, 320 + CS35L34_X_STATE | CS35L34_X_LOC, slot); 321 + } 322 + /* configure VBSTMON_TX_LOC */ 323 + if (slot_num == 7) { 324 + snd_soc_update_bits(codec, 325 + CS35L34_TDM_TX_CTL_4_VBSTMON, 326 + CS35L34_X_STATE | CS35L34_X_LOC, slot); 327 + } 328 + 329 + /* Enable the relevant tx slot */ 330 + reg = CS35L34_TDM_TX_SLOT_EN_4 - (slot/8); 331 + bit_pos = slot - ((slot / 8) * (8)); 332 + snd_soc_update_bits(codec, reg, 333 + 1 << bit_pos, 1 << bit_pos); 334 + 335 + tx_mask &= ~(1 << slot); 336 + slot = ffs(tx_mask) - 1; 337 + slot_num++; 338 + } 339 + 340 + return 0; 341 + } 342 + 343 + static int cs35l34_main_amp_event(struct snd_soc_dapm_widget *w, 344 + struct snd_kcontrol *kcontrol, int event) 345 + { 346 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 347 + struct cs35l34_private *priv = snd_soc_codec_get_drvdata(codec); 348 + 349 + switch (event) { 350 + case SND_SOC_DAPM_POST_PMU: 351 + regmap_update_bits(priv->regmap, CS35L34_BST_CVTR_V_CTL, 352 + CS35L34_BST_CVTL_MASK, priv->pdata.boost_vtge); 353 + usleep_range(5000, 5100); 354 + regmap_update_bits(priv->regmap, CS35L34_PROTECT_CTL, 355 + CS35L34_MUTE, 0); 356 + break; 357 + case SND_SOC_DAPM_POST_PMD: 358 + regmap_update_bits(priv->regmap, CS35L34_BST_CVTR_V_CTL, 359 + CS35L34_BST_CVTL_MASK, 0); 360 + regmap_update_bits(priv->regmap, CS35L34_PROTECT_CTL, 361 + CS35L34_MUTE, CS35L34_MUTE); 362 + usleep_range(5000, 5100); 363 + break; 364 + default: 365 + pr_err("Invalid event = 0x%x\n", event); 366 + } 367 + return 0; 368 + } 369 + 370 + static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10200, 50, 0); 371 + 372 + static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 300, 100, 0); 373 + 374 + 375 + static const struct snd_kcontrol_new cs35l34_snd_controls[] = { 376 + SOC_SINGLE_SX_TLV("Digital Volume", CS35L34_AMP_DIG_VOL, 377 + 0, 0x34, 0xE4, dig_vol_tlv), 378 + SOC_SINGLE_TLV("Amp Gain Volume", CS35L34_AMP_ANLG_GAIN_CTL, 379 + 0, 0xF, 0, amp_gain_tlv), 380 + }; 381 + 382 + 383 + static int cs35l34_mclk_event(struct snd_soc_dapm_widget *w, 384 + struct snd_kcontrol *kcontrol, int event) 385 + { 386 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 387 + struct cs35l34_private *priv = snd_soc_codec_get_drvdata(codec); 388 + int ret, i; 389 + unsigned int reg; 390 + 391 + switch (event) { 392 + case SND_SOC_DAPM_PRE_PMD: 393 + ret = regmap_read(priv->regmap, CS35L34_AMP_DIG_VOL_CTL, 394 + &reg); 395 + if (ret != 0) { 396 + pr_err("%s regmap read failure %d\n", __func__, ret); 397 + return ret; 398 + } 399 + if (reg & CS35L34_AMP_DIGSFT) 400 + msleep(40); 401 + else 402 + usleep_range(2000, 2100); 403 + 404 + for (i = 0; i < PDN_DONE_ATTEMPTS; i++) { 405 + ret = regmap_read(priv->regmap, CS35L34_INT_STATUS_2, 406 + &reg); 407 + if (ret != 0) { 408 + pr_err("%s regmap read failure %d\n", 409 + __func__, ret); 410 + return ret; 411 + } 412 + if (reg & CS35L34_PDN_DONE) 413 + break; 414 + 415 + usleep_range(5000, 5100); 416 + } 417 + if (i == PDN_DONE_ATTEMPTS) 418 + pr_err("%s Device did not power down properly\n", 419 + __func__); 420 + break; 421 + default: 422 + pr_err("Invalid event = 0x%x\n", event); 423 + break; 424 + } 425 + return 0; 426 + } 427 + 428 + static const struct snd_soc_dapm_widget cs35l34_dapm_widgets[] = { 429 + SND_SOC_DAPM_AIF_IN_E("SDIN", NULL, 0, CS35L34_PWRCTL3, 430 + 1, 1, cs35l34_sdin_event, 431 + SND_SOC_DAPM_PRE_PMU | 432 + SND_SOC_DAPM_POST_PMD), 433 + SND_SOC_DAPM_AIF_OUT("SDOUT", NULL, 0, CS35L34_PWRCTL3, 2, 1), 434 + 435 + SND_SOC_DAPM_SUPPLY("EXTCLK", CS35L34_PWRCTL3, 7, 1, 436 + cs35l34_mclk_event, SND_SOC_DAPM_PRE_PMD), 437 + 438 + SND_SOC_DAPM_OUTPUT("SPK"), 439 + 440 + SND_SOC_DAPM_INPUT("VP"), 441 + SND_SOC_DAPM_INPUT("VPST"), 442 + SND_SOC_DAPM_INPUT("ISENSE"), 443 + SND_SOC_DAPM_INPUT("VSENSE"), 444 + 445 + SND_SOC_DAPM_ADC("VMON ADC", NULL, CS35L34_PWRCTL2, 7, 1), 446 + SND_SOC_DAPM_ADC("IMON ADC", NULL, CS35L34_PWRCTL2, 6, 1), 447 + SND_SOC_DAPM_ADC("VPMON ADC", NULL, CS35L34_PWRCTL3, 3, 1), 448 + SND_SOC_DAPM_ADC("VBSTMON ADC", NULL, CS35L34_PWRCTL3, 4, 1), 449 + SND_SOC_DAPM_ADC("CLASS H", NULL, CS35L34_PWRCTL2, 5, 1), 450 + SND_SOC_DAPM_ADC("BOOST", NULL, CS35L34_PWRCTL2, 2, 1), 451 + 452 + SND_SOC_DAPM_OUT_DRV_E("Main AMP", CS35L34_PWRCTL2, 0, 1, NULL, 0, 453 + cs35l34_main_amp_event, SND_SOC_DAPM_POST_PMU | 454 + SND_SOC_DAPM_POST_PMD), 455 + }; 456 + 457 + static const struct snd_soc_dapm_route cs35l34_audio_map[] = { 458 + {"SDIN", NULL, "AMP Playback"}, 459 + {"BOOST", NULL, "SDIN"}, 460 + {"CLASS H", NULL, "BOOST"}, 461 + {"Main AMP", NULL, "CLASS H"}, 462 + {"SPK", NULL, "Main AMP"}, 463 + 464 + {"VPMON ADC", NULL, "CLASS H"}, 465 + {"VBSTMON ADC", NULL, "CLASS H"}, 466 + {"SPK", NULL, "VPMON ADC"}, 467 + {"SPK", NULL, "VBSTMON ADC"}, 468 + 469 + {"IMON ADC", NULL, "ISENSE"}, 470 + {"VMON ADC", NULL, "VSENSE"}, 471 + {"SDOUT", NULL, "IMON ADC"}, 472 + {"SDOUT", NULL, "VMON ADC"}, 473 + {"AMP Capture", NULL, "SDOUT"}, 474 + 475 + {"SDIN", NULL, "EXTCLK"}, 476 + {"SDOUT", NULL, "EXTCLK"}, 477 + }; 478 + 479 + struct cs35l34_mclk_div { 480 + int mclk; 481 + int srate; 482 + u8 adsp_rate; 483 + }; 484 + 485 + static struct cs35l34_mclk_div cs35l34_mclk_coeffs[] = { 486 + 487 + /* MCLK, Sample Rate, adsp_rate */ 488 + 489 + {5644800, 11025, 0x1}, 490 + {5644800, 22050, 0x4}, 491 + {5644800, 44100, 0x7}, 492 + 493 + {6000000, 8000, 0x0}, 494 + {6000000, 11025, 0x1}, 495 + {6000000, 12000, 0x2}, 496 + {6000000, 16000, 0x3}, 497 + {6000000, 22050, 0x4}, 498 + {6000000, 24000, 0x5}, 499 + {6000000, 32000, 0x6}, 500 + {6000000, 44100, 0x7}, 501 + {6000000, 48000, 0x8}, 502 + 503 + {6144000, 8000, 0x0}, 504 + {6144000, 11025, 0x1}, 505 + {6144000, 12000, 0x2}, 506 + {6144000, 16000, 0x3}, 507 + {6144000, 22050, 0x4}, 508 + {6144000, 24000, 0x5}, 509 + {6144000, 32000, 0x6}, 510 + {6144000, 44100, 0x7}, 511 + {6144000, 48000, 0x8}, 512 + }; 513 + 514 + static int cs35l34_get_mclk_coeff(int mclk, int srate) 515 + { 516 + int i; 517 + 518 + for (i = 0; i < ARRAY_SIZE(cs35l34_mclk_coeffs); i++) { 519 + if (cs35l34_mclk_coeffs[i].mclk == mclk && 520 + cs35l34_mclk_coeffs[i].srate == srate) 521 + return i; 522 + } 523 + return -EINVAL; 524 + } 525 + 526 + static int cs35l34_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 527 + { 528 + struct snd_soc_codec *codec = codec_dai->codec; 529 + struct cs35l34_private *priv = snd_soc_codec_get_drvdata(codec); 530 + 531 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 532 + case SND_SOC_DAIFMT_CBM_CFM: 533 + regmap_update_bits(priv->regmap, CS35L34_ADSP_CLK_CTL, 534 + 0x80, 0x80); 535 + break; 536 + case SND_SOC_DAIFMT_CBS_CFS: 537 + regmap_update_bits(priv->regmap, CS35L34_ADSP_CLK_CTL, 538 + 0x80, 0x00); 539 + break; 540 + default: 541 + return -EINVAL; 542 + } 543 + return 0; 544 + } 545 + 546 + static int cs35l34_pcm_hw_params(struct snd_pcm_substream *substream, 547 + struct snd_pcm_hw_params *params, 548 + struct snd_soc_dai *dai) 549 + { 550 + struct snd_soc_codec *codec = dai->codec; 551 + struct cs35l34_private *priv = snd_soc_codec_get_drvdata(codec); 552 + int srate = params_rate(params); 553 + int ret; 554 + 555 + int coeff = cs35l34_get_mclk_coeff(priv->mclk_int, srate); 556 + 557 + if (coeff < 0) { 558 + dev_err(codec->dev, "ERROR: Invalid mclk %d and/or srate %d\n", 559 + priv->mclk_int, srate); 560 + return coeff; 561 + } 562 + 563 + ret = regmap_update_bits(priv->regmap, CS35L34_ADSP_CLK_CTL, 564 + CS35L34_ADSP_RATE, cs35l34_mclk_coeffs[coeff].adsp_rate); 565 + if (ret != 0) 566 + dev_err(codec->dev, "Failed to set clock state %d\n", ret); 567 + 568 + return ret; 569 + } 570 + 571 + static unsigned int cs35l34_src_rates[] = { 572 + 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 573 + }; 574 + 575 + 576 + static struct snd_pcm_hw_constraint_list cs35l34_constraints = { 577 + .count = ARRAY_SIZE(cs35l34_src_rates), 578 + .list = cs35l34_src_rates, 579 + }; 580 + 581 + static int cs35l34_pcm_startup(struct snd_pcm_substream *substream, 582 + struct snd_soc_dai *dai) 583 + { 584 + 585 + snd_pcm_hw_constraint_list(substream->runtime, 0, 586 + SNDRV_PCM_HW_PARAM_RATE, &cs35l34_constraints); 587 + return 0; 588 + } 589 + 590 + 591 + static int cs35l34_set_tristate(struct snd_soc_dai *dai, int tristate) 592 + { 593 + 594 + struct snd_soc_codec *codec = dai->codec; 595 + 596 + if (tristate) 597 + snd_soc_update_bits(codec, CS35L34_PWRCTL3, 598 + CS35L34_PDN_SDOUT, CS35L34_PDN_SDOUT); 599 + else 600 + snd_soc_update_bits(codec, CS35L34_PWRCTL3, 601 + CS35L34_PDN_SDOUT, 0); 602 + return 0; 603 + } 604 + 605 + static int cs35l34_dai_set_sysclk(struct snd_soc_dai *dai, 606 + int clk_id, unsigned int freq, int dir) 607 + { 608 + struct snd_soc_codec *codec = dai->codec; 609 + struct cs35l34_private *cs35l34 = snd_soc_codec_get_drvdata(codec); 610 + unsigned int value; 611 + 612 + switch (freq) { 613 + case CS35L34_MCLK_5644: 614 + value = ~CS35L34_MCLK_DIV & CS35L34_MCLK_RATE_5P6448; 615 + cs35l34->mclk_int = freq; 616 + break; 617 + case CS35L34_MCLK_6: 618 + value = ~CS35L34_MCLK_DIV & CS35L34_MCLK_RATE_6P0000; 619 + cs35l34->mclk_int = freq; 620 + break; 621 + case CS35L34_MCLK_6144: 622 + value = ~CS35L34_MCLK_DIV & CS35L34_MCLK_RATE_6P1440; 623 + cs35l34->mclk_int = freq; 624 + break; 625 + case CS35L34_MCLK_11289: 626 + value = CS35L34_MCLK_DIV | CS35L34_MCLK_RATE_5P6448; 627 + cs35l34->mclk_int = freq / 2; 628 + break; 629 + case CS35L34_MCLK_12: 630 + value = CS35L34_MCLK_DIV | CS35L34_MCLK_RATE_6P0000; 631 + cs35l34->mclk_int = freq / 2; 632 + break; 633 + case CS35L34_MCLK_12288: 634 + value = CS35L34_MCLK_DIV | CS35L34_MCLK_RATE_6P1440; 635 + cs35l34->mclk_int = freq / 2; 636 + break; 637 + default: 638 + dev_err(codec->dev, "ERROR: Invalid Frequency %d\n", freq); 639 + cs35l34->mclk_int = 0; 640 + return -EINVAL; 641 + } 642 + regmap_update_bits(cs35l34->regmap, CS35L34_MCLK_CTL, 643 + CS35L34_MCLK_DIV | CS35L34_MCLK_RATE_MASK, value); 644 + return 0; 645 + } 646 + 647 + static const struct snd_soc_dai_ops cs35l34_ops = { 648 + .startup = cs35l34_pcm_startup, 649 + .set_tristate = cs35l34_set_tristate, 650 + .set_fmt = cs35l34_set_dai_fmt, 651 + .hw_params = cs35l34_pcm_hw_params, 652 + .set_sysclk = cs35l34_dai_set_sysclk, 653 + .set_tdm_slot = cs35l34_set_tdm_slot, 654 + }; 655 + 656 + static struct snd_soc_dai_driver cs35l34_dai = { 657 + .name = "cs35l34", 658 + .id = 0, 659 + .playback = { 660 + .stream_name = "AMP Playback", 661 + .channels_min = 1, 662 + .channels_max = 8, 663 + .rates = CS35L34_RATES, 664 + .formats = CS35L34_FORMATS, 665 + }, 666 + .capture = { 667 + .stream_name = "AMP Capture", 668 + .channels_min = 1, 669 + .channels_max = 8, 670 + .rates = CS35L34_RATES, 671 + .formats = CS35L34_FORMATS, 672 + }, 673 + .ops = &cs35l34_ops, 674 + .symmetric_rates = 1, 675 + }; 676 + 677 + static int cs35l34_boost_inductor(struct cs35l34_private *cs35l34, 678 + unsigned int inductor) 679 + { 680 + struct snd_soc_codec *codec = cs35l34->codec; 681 + 682 + switch (inductor) { 683 + case 1000: /* 1 uH */ 684 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_1, 0x24); 685 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_2, 0x24); 686 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SLOPE_COMP, 687 + 0x4E); 688 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SW_FREQ, 0); 689 + break; 690 + case 1200: /* 1.2 uH */ 691 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_1, 0x20); 692 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_2, 0x20); 693 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SLOPE_COMP, 694 + 0x47); 695 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SW_FREQ, 1); 696 + break; 697 + case 1500: /* 1.5uH */ 698 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_1, 0x20); 699 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_2, 0x20); 700 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SLOPE_COMP, 701 + 0x3C); 702 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SW_FREQ, 2); 703 + break; 704 + case 2200: /* 2.2uH */ 705 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_1, 0x19); 706 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_2, 0x25); 707 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SLOPE_COMP, 708 + 0x23); 709 + regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SW_FREQ, 3); 710 + break; 711 + default: 712 + dev_err(codec->dev, "%s Invalid Inductor Value %d uH\n", 713 + __func__, inductor); 714 + return -EINVAL; 715 + } 716 + return 0; 717 + } 718 + 719 + static int cs35l34_probe(struct snd_soc_codec *codec) 720 + { 721 + int ret = 0; 722 + struct cs35l34_private *cs35l34 = snd_soc_codec_get_drvdata(codec); 723 + 724 + pm_runtime_get_sync(codec->dev); 725 + 726 + /* Set over temperature warning attenuation to 6 dB */ 727 + regmap_update_bits(cs35l34->regmap, CS35L34_PROTECT_CTL, 728 + CS35L34_OTW_ATTN_MASK, 0x8); 729 + 730 + /* Set Power control registers 2 and 3 to have everything 731 + * powered down at initialization 732 + */ 733 + regmap_write(cs35l34->regmap, CS35L34_PWRCTL2, 0xFD); 734 + regmap_write(cs35l34->regmap, CS35L34_PWRCTL3, 0x1F); 735 + 736 + /* Set mute bit at startup */ 737 + regmap_update_bits(cs35l34->regmap, CS35L34_PROTECT_CTL, 738 + CS35L34_MUTE, CS35L34_MUTE); 739 + 740 + /* Set Platform Data */ 741 + if (cs35l34->pdata.boost_peak) 742 + regmap_update_bits(cs35l34->regmap, CS35L34_BST_PEAK_I, 743 + CS35L34_BST_PEAK_MASK, 744 + cs35l34->pdata.boost_peak); 745 + 746 + if (cs35l34->pdata.gain_zc_disable) 747 + regmap_update_bits(cs35l34->regmap, CS35L34_PROTECT_CTL, 748 + CS35L34_GAIN_ZC_MASK, 0); 749 + else 750 + regmap_update_bits(cs35l34->regmap, CS35L34_PROTECT_CTL, 751 + CS35L34_GAIN_ZC_MASK, CS35L34_GAIN_ZC_MASK); 752 + 753 + if (cs35l34->pdata.aif_half_drv) 754 + regmap_update_bits(cs35l34->regmap, CS35L34_ADSP_CLK_CTL, 755 + CS35L34_ADSP_DRIVE, 0); 756 + 757 + if (cs35l34->pdata.digsft_disable) 758 + regmap_update_bits(cs35l34->regmap, CS35L34_AMP_DIG_VOL_CTL, 759 + CS35L34_AMP_DIGSFT, 0); 760 + 761 + if (cs35l34->pdata.amp_inv) 762 + regmap_update_bits(cs35l34->regmap, CS35L34_AMP_DIG_VOL_CTL, 763 + CS35L34_INV, CS35L34_INV); 764 + 765 + if (cs35l34->pdata.boost_ind) 766 + ret = cs35l34_boost_inductor(cs35l34, cs35l34->pdata.boost_ind); 767 + 768 + if (cs35l34->pdata.i2s_sdinloc) 769 + regmap_update_bits(cs35l34->regmap, CS35L34_ADSP_I2S_CTL, 770 + CS35L34_I2S_LOC_MASK, 771 + cs35l34->pdata.i2s_sdinloc << CS35L34_I2S_LOC_SHIFT); 772 + 773 + if (cs35l34->pdata.tdm_rising_edge) 774 + regmap_update_bits(cs35l34->regmap, CS35L34_ADSP_TDM_CTL, 775 + 1, 1); 776 + 777 + pm_runtime_put_sync(codec->dev); 778 + 779 + return ret; 780 + } 781 + 782 + 783 + static struct snd_soc_codec_driver soc_codec_dev_cs35l34 = { 784 + .probe = cs35l34_probe, 785 + 786 + .component_driver = { 787 + .dapm_widgets = cs35l34_dapm_widgets, 788 + .num_dapm_widgets = ARRAY_SIZE(cs35l34_dapm_widgets), 789 + .dapm_routes = cs35l34_audio_map, 790 + .num_dapm_routes = ARRAY_SIZE(cs35l34_audio_map), 791 + .controls = cs35l34_snd_controls, 792 + .num_controls = ARRAY_SIZE(cs35l34_snd_controls), 793 + }, 794 + }; 795 + 796 + static struct regmap_config cs35l34_regmap = { 797 + .reg_bits = 8, 798 + .val_bits = 8, 799 + 800 + .max_register = CS35L34_MAX_REGISTER, 801 + .reg_defaults = cs35l34_reg, 802 + .num_reg_defaults = ARRAY_SIZE(cs35l34_reg), 803 + .volatile_reg = cs35l34_volatile_register, 804 + .readable_reg = cs35l34_readable_register, 805 + .precious_reg = cs35l34_precious_register, 806 + .cache_type = REGCACHE_RBTREE, 807 + }; 808 + 809 + static int cs35l34_handle_of_data(struct i2c_client *i2c_client, 810 + struct cs35l34_platform_data *pdata) 811 + { 812 + struct device_node *np = i2c_client->dev.of_node; 813 + unsigned int val; 814 + 815 + if (of_property_read_u32(np, "cirrus,boost-vtge-millivolt", 816 + &val) >= 0) { 817 + /* Boost Voltage has a maximum of 8V */ 818 + if (val > 8000 || (val < 3300 && val > 0)) { 819 + dev_err(&i2c_client->dev, 820 + "Invalid Boost Voltage %d mV\n", val); 821 + return -EINVAL; 822 + } 823 + if (val == 0) 824 + pdata->boost_vtge = 0; /* Use VP */ 825 + else 826 + pdata->boost_vtge = ((val - 3300)/100) + 1; 827 + } else { 828 + dev_warn(&i2c_client->dev, 829 + "Boost Voltage not specified. Using VP\n"); 830 + } 831 + 832 + if (of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val) >= 0) { 833 + pdata->boost_ind = val; 834 + } else { 835 + dev_err(&i2c_client->dev, "Inductor not specified.\n"); 836 + return -EINVAL; 837 + } 838 + 839 + if (of_property_read_u32(np, "cirrus,boost-peak-milliamp", &val) >= 0) { 840 + if (val > 3840 || val < 1200) { 841 + dev_err(&i2c_client->dev, 842 + "Invalid Boost Peak Current %d mA\n", val); 843 + return -EINVAL; 844 + } 845 + pdata->boost_peak = ((val - 1200)/80) + 1; 846 + } 847 + 848 + pdata->aif_half_drv = of_property_read_bool(np, 849 + "cirrus,aif-half-drv"); 850 + pdata->digsft_disable = of_property_read_bool(np, 851 + "cirrus,digsft-disable"); 852 + 853 + pdata->gain_zc_disable = of_property_read_bool(np, 854 + "cirrus,gain-zc-disable"); 855 + pdata->amp_inv = of_property_read_bool(np, "cirrus,amp-inv"); 856 + 857 + if (of_property_read_u32(np, "cirrus,i2s-sdinloc", &val) >= 0) 858 + pdata->i2s_sdinloc = val; 859 + if (of_property_read_u32(np, "cirrus,tdm-rising-edge", &val) >= 0) 860 + pdata->tdm_rising_edge = val; 861 + 862 + return 0; 863 + } 864 + 865 + static irqreturn_t cs35l34_irq_thread(int irq, void *data) 866 + { 867 + struct cs35l34_private *cs35l34 = data; 868 + struct snd_soc_codec *codec = cs35l34->codec; 869 + unsigned int sticky1, sticky2, sticky3, sticky4; 870 + unsigned int mask1, mask2, mask3, mask4, current1; 871 + 872 + 873 + /* ack the irq by reading all status registers */ 874 + regmap_read(cs35l34->regmap, CS35L34_INT_STATUS_4, &sticky4); 875 + regmap_read(cs35l34->regmap, CS35L34_INT_STATUS_3, &sticky3); 876 + regmap_read(cs35l34->regmap, CS35L34_INT_STATUS_2, &sticky2); 877 + regmap_read(cs35l34->regmap, CS35L34_INT_STATUS_1, &sticky1); 878 + 879 + regmap_read(cs35l34->regmap, CS35L34_INT_MASK_4, &mask4); 880 + regmap_read(cs35l34->regmap, CS35L34_INT_MASK_3, &mask3); 881 + regmap_read(cs35l34->regmap, CS35L34_INT_MASK_2, &mask2); 882 + regmap_read(cs35l34->regmap, CS35L34_INT_MASK_1, &mask1); 883 + 884 + if (!(sticky1 & ~mask1) && !(sticky2 & ~mask2) && !(sticky3 & ~mask3) 885 + && !(sticky4 & ~mask4)) 886 + return IRQ_NONE; 887 + 888 + regmap_read(cs35l34->regmap, CS35L34_INT_STATUS_1, &current1); 889 + 890 + if (sticky1 & CS35L34_CAL_ERR) { 891 + dev_err(codec->dev, "Cal error\n"); 892 + 893 + /* error is no longer asserted; safe to reset */ 894 + if (!(current1 & CS35L34_CAL_ERR)) { 895 + dev_dbg(codec->dev, "Cal error release\n"); 896 + regmap_update_bits(cs35l34->regmap, 897 + CS35L34_PROT_RELEASE_CTL, 898 + CS35L34_CAL_ERR_RLS, 0); 899 + regmap_update_bits(cs35l34->regmap, 900 + CS35L34_PROT_RELEASE_CTL, 901 + CS35L34_CAL_ERR_RLS, 902 + CS35L34_CAL_ERR_RLS); 903 + regmap_update_bits(cs35l34->regmap, 904 + CS35L34_PROT_RELEASE_CTL, 905 + CS35L34_CAL_ERR_RLS, 0); 906 + /* note: amp will re-calibrate on next resume */ 907 + } 908 + } 909 + 910 + if (sticky1 & CS35L34_ALIVE_ERR) 911 + dev_err(codec->dev, "Alive error\n"); 912 + 913 + if (sticky1 & CS35L34_AMP_SHORT) { 914 + dev_crit(codec->dev, "Amp short error\n"); 915 + 916 + /* error is no longer asserted; safe to reset */ 917 + if (!(current1 & CS35L34_AMP_SHORT)) { 918 + dev_dbg(codec->dev, 919 + "Amp short error release\n"); 920 + regmap_update_bits(cs35l34->regmap, 921 + CS35L34_PROT_RELEASE_CTL, 922 + CS35L34_SHORT_RLS, 0); 923 + regmap_update_bits(cs35l34->regmap, 924 + CS35L34_PROT_RELEASE_CTL, 925 + CS35L34_SHORT_RLS, 926 + CS35L34_SHORT_RLS); 927 + regmap_update_bits(cs35l34->regmap, 928 + CS35L34_PROT_RELEASE_CTL, 929 + CS35L34_SHORT_RLS, 0); 930 + } 931 + } 932 + 933 + if (sticky1 & CS35L34_OTW) { 934 + dev_crit(codec->dev, "Over temperature warning\n"); 935 + 936 + /* error is no longer asserted; safe to reset */ 937 + if (!(current1 & CS35L34_OTW)) { 938 + dev_dbg(codec->dev, 939 + "Over temperature warning release\n"); 940 + regmap_update_bits(cs35l34->regmap, 941 + CS35L34_PROT_RELEASE_CTL, 942 + CS35L34_OTW_RLS, 0); 943 + regmap_update_bits(cs35l34->regmap, 944 + CS35L34_PROT_RELEASE_CTL, 945 + CS35L34_OTW_RLS, 946 + CS35L34_OTW_RLS); 947 + regmap_update_bits(cs35l34->regmap, 948 + CS35L34_PROT_RELEASE_CTL, 949 + CS35L34_OTW_RLS, 0); 950 + } 951 + } 952 + 953 + if (sticky1 & CS35L34_OTE) { 954 + dev_crit(codec->dev, "Over temperature error\n"); 955 + 956 + /* error is no longer asserted; safe to reset */ 957 + if (!(current1 & CS35L34_OTE)) { 958 + dev_dbg(codec->dev, 959 + "Over temperature error release\n"); 960 + regmap_update_bits(cs35l34->regmap, 961 + CS35L34_PROT_RELEASE_CTL, 962 + CS35L34_OTE_RLS, 0); 963 + regmap_update_bits(cs35l34->regmap, 964 + CS35L34_PROT_RELEASE_CTL, 965 + CS35L34_OTE_RLS, 966 + CS35L34_OTE_RLS); 967 + regmap_update_bits(cs35l34->regmap, 968 + CS35L34_PROT_RELEASE_CTL, 969 + CS35L34_OTE_RLS, 0); 970 + } 971 + } 972 + 973 + if (sticky3 & CS35L34_BST_HIGH) { 974 + dev_crit(codec->dev, "VBST too high error; powering off!\n"); 975 + regmap_update_bits(cs35l34->regmap, CS35L34_PWRCTL2, 976 + CS35L34_PDN_AMP, CS35L34_PDN_AMP); 977 + regmap_update_bits(cs35l34->regmap, CS35L34_PWRCTL1, 978 + CS35L34_PDN_ALL, CS35L34_PDN_ALL); 979 + } 980 + 981 + if (sticky3 & CS35L34_LBST_SHORT) { 982 + dev_crit(codec->dev, "LBST short error; powering off!\n"); 983 + regmap_update_bits(cs35l34->regmap, CS35L34_PWRCTL2, 984 + CS35L34_PDN_AMP, CS35L34_PDN_AMP); 985 + regmap_update_bits(cs35l34->regmap, CS35L34_PWRCTL1, 986 + CS35L34_PDN_ALL, CS35L34_PDN_ALL); 987 + } 988 + 989 + return IRQ_HANDLED; 990 + } 991 + 992 + static const char * const cs35l34_core_supplies[] = { 993 + "VA", 994 + "VP", 995 + }; 996 + 997 + static int cs35l34_i2c_probe(struct i2c_client *i2c_client, 998 + const struct i2c_device_id *id) 999 + { 1000 + struct cs35l34_private *cs35l34; 1001 + struct cs35l34_platform_data *pdata = 1002 + dev_get_platdata(&i2c_client->dev); 1003 + int i; 1004 + int ret; 1005 + unsigned int devid = 0; 1006 + unsigned int reg; 1007 + 1008 + cs35l34 = devm_kzalloc(&i2c_client->dev, 1009 + sizeof(struct cs35l34_private), 1010 + GFP_KERNEL); 1011 + if (!cs35l34) { 1012 + dev_err(&i2c_client->dev, "could not allocate codec\n"); 1013 + return -ENOMEM; 1014 + } 1015 + 1016 + i2c_set_clientdata(i2c_client, cs35l34); 1017 + cs35l34->regmap = devm_regmap_init_i2c(i2c_client, &cs35l34_regmap); 1018 + if (IS_ERR(cs35l34->regmap)) { 1019 + ret = PTR_ERR(cs35l34->regmap); 1020 + dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); 1021 + return ret; 1022 + } 1023 + 1024 + cs35l34->num_core_supplies = ARRAY_SIZE(cs35l34_core_supplies); 1025 + for (i = 0; i < ARRAY_SIZE(cs35l34_core_supplies); i++) 1026 + cs35l34->core_supplies[i].supply = cs35l34_core_supplies[i]; 1027 + 1028 + ret = devm_regulator_bulk_get(&i2c_client->dev, 1029 + cs35l34->num_core_supplies, 1030 + cs35l34->core_supplies); 1031 + if (ret != 0) { 1032 + dev_err(&i2c_client->dev, 1033 + "Failed to request core supplies %d\n", ret); 1034 + return ret; 1035 + } 1036 + 1037 + ret = regulator_bulk_enable(cs35l34->num_core_supplies, 1038 + cs35l34->core_supplies); 1039 + if (ret != 0) { 1040 + dev_err(&i2c_client->dev, 1041 + "Failed to enable core supplies: %d\n", ret); 1042 + return ret; 1043 + } 1044 + 1045 + if (pdata) { 1046 + cs35l34->pdata = *pdata; 1047 + } else { 1048 + pdata = devm_kzalloc(&i2c_client->dev, 1049 + sizeof(struct cs35l34_platform_data), 1050 + GFP_KERNEL); 1051 + if (!pdata) { 1052 + dev_err(&i2c_client->dev, 1053 + "could not allocate pdata\n"); 1054 + return -ENOMEM; 1055 + } 1056 + if (i2c_client->dev.of_node) { 1057 + ret = cs35l34_handle_of_data(i2c_client, pdata); 1058 + if (ret != 0) 1059 + return ret; 1060 + 1061 + } 1062 + cs35l34->pdata = *pdata; 1063 + } 1064 + 1065 + ret = devm_request_threaded_irq(&i2c_client->dev, i2c_client->irq, NULL, 1066 + cs35l34_irq_thread, IRQF_ONESHOT | IRQF_TRIGGER_LOW, 1067 + "cs35l34", cs35l34); 1068 + if (ret != 0) 1069 + dev_err(&i2c_client->dev, "Failed to request IRQ: %d\n", ret); 1070 + 1071 + cs35l34->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, 1072 + "reset-gpios", GPIOD_OUT_LOW); 1073 + if (IS_ERR(cs35l34->reset_gpio)) 1074 + return PTR_ERR(cs35l34->reset_gpio); 1075 + 1076 + gpiod_set_value_cansleep(cs35l34->reset_gpio, 1); 1077 + 1078 + msleep(CS35L34_START_DELAY); 1079 + 1080 + ret = regmap_read(cs35l34->regmap, CS35L34_DEVID_AB, &reg); 1081 + 1082 + devid = (reg & 0xFF) << 12; 1083 + ret = regmap_read(cs35l34->regmap, CS35L34_DEVID_CD, &reg); 1084 + devid |= (reg & 0xFF) << 4; 1085 + ret = regmap_read(cs35l34->regmap, CS35L34_DEVID_E, &reg); 1086 + devid |= (reg & 0xF0) >> 4; 1087 + 1088 + if (devid != CS35L34_CHIP_ID) { 1089 + dev_err(&i2c_client->dev, 1090 + "CS35l34 Device ID (%X). Expected ID %X\n", 1091 + devid, CS35L34_CHIP_ID); 1092 + ret = -ENODEV; 1093 + goto err_regulator; 1094 + } 1095 + 1096 + ret = regmap_read(cs35l34->regmap, CS35L34_REV_ID, &reg); 1097 + if (ret < 0) { 1098 + dev_err(&i2c_client->dev, "Get Revision ID failed\n"); 1099 + goto err_regulator; 1100 + } 1101 + 1102 + dev_info(&i2c_client->dev, 1103 + "Cirrus Logic CS35l34 (%x), Revision: %02X\n", devid, 1104 + reg & 0xFF); 1105 + 1106 + /* Unmask critical interrupts */ 1107 + regmap_update_bits(cs35l34->regmap, CS35L34_INT_MASK_1, 1108 + CS35L34_M_CAL_ERR | CS35L34_M_ALIVE_ERR | 1109 + CS35L34_M_AMP_SHORT | CS35L34_M_OTW | 1110 + CS35L34_M_OTE, 0); 1111 + regmap_update_bits(cs35l34->regmap, CS35L34_INT_MASK_3, 1112 + CS35L34_M_BST_HIGH | CS35L34_M_LBST_SHORT, 0); 1113 + 1114 + pm_runtime_set_autosuspend_delay(&i2c_client->dev, 100); 1115 + pm_runtime_use_autosuspend(&i2c_client->dev); 1116 + pm_runtime_set_active(&i2c_client->dev); 1117 + pm_runtime_enable(&i2c_client->dev); 1118 + 1119 + ret = snd_soc_register_codec(&i2c_client->dev, 1120 + &soc_codec_dev_cs35l34, &cs35l34_dai, 1); 1121 + if (ret < 0) { 1122 + dev_err(&i2c_client->dev, 1123 + "%s: Register codec failed\n", __func__); 1124 + goto err_regulator; 1125 + } 1126 + 1127 + return 0; 1128 + 1129 + err_regulator: 1130 + regulator_bulk_disable(cs35l34->num_core_supplies, 1131 + cs35l34->core_supplies); 1132 + 1133 + return ret; 1134 + } 1135 + 1136 + static int cs35l34_i2c_remove(struct i2c_client *client) 1137 + { 1138 + struct cs35l34_private *cs35l34 = i2c_get_clientdata(client); 1139 + 1140 + snd_soc_unregister_codec(&client->dev); 1141 + 1142 + if (cs35l34->reset_gpio) 1143 + gpiod_set_value_cansleep(cs35l34->reset_gpio, 0); 1144 + 1145 + pm_runtime_disable(&client->dev); 1146 + regulator_bulk_disable(cs35l34->num_core_supplies, 1147 + cs35l34->core_supplies); 1148 + 1149 + return 0; 1150 + } 1151 + 1152 + static int __maybe_unused cs35l34_runtime_resume(struct device *dev) 1153 + { 1154 + struct cs35l34_private *cs35l34 = dev_get_drvdata(dev); 1155 + int ret; 1156 + 1157 + ret = regulator_bulk_enable(cs35l34->num_core_supplies, 1158 + cs35l34->core_supplies); 1159 + 1160 + if (ret != 0) { 1161 + dev_err(dev, "Failed to enable core supplies: %d\n", 1162 + ret); 1163 + return ret; 1164 + } 1165 + 1166 + regcache_cache_only(cs35l34->regmap, false); 1167 + 1168 + gpiod_set_value_cansleep(cs35l34->reset_gpio, 1); 1169 + msleep(CS35L34_START_DELAY); 1170 + 1171 + ret = regcache_sync(cs35l34->regmap); 1172 + if (ret != 0) { 1173 + dev_err(dev, "Failed to restore register cache\n"); 1174 + goto err; 1175 + } 1176 + return 0; 1177 + err: 1178 + regcache_cache_only(cs35l34->regmap, true); 1179 + regulator_bulk_disable(cs35l34->num_core_supplies, 1180 + cs35l34->core_supplies); 1181 + 1182 + return ret; 1183 + } 1184 + 1185 + static int __maybe_unused cs35l34_runtime_suspend(struct device *dev) 1186 + { 1187 + struct cs35l34_private *cs35l34 = dev_get_drvdata(dev); 1188 + 1189 + regcache_cache_only(cs35l34->regmap, true); 1190 + regcache_mark_dirty(cs35l34->regmap); 1191 + 1192 + gpiod_set_value_cansleep(cs35l34->reset_gpio, 0); 1193 + 1194 + regulator_bulk_disable(cs35l34->num_core_supplies, 1195 + cs35l34->core_supplies); 1196 + 1197 + return 0; 1198 + } 1199 + 1200 + static const struct dev_pm_ops cs35l34_pm_ops = { 1201 + SET_RUNTIME_PM_OPS(cs35l34_runtime_suspend, 1202 + cs35l34_runtime_resume, 1203 + NULL) 1204 + }; 1205 + 1206 + static const struct of_device_id cs35l34_of_match[] = { 1207 + {.compatible = "cirrus,cs35l34"}, 1208 + {}, 1209 + }; 1210 + MODULE_DEVICE_TABLE(of, cs35l34_of_match); 1211 + 1212 + static const struct i2c_device_id cs35l34_id[] = { 1213 + {"cs35l34", 0}, 1214 + {} 1215 + }; 1216 + MODULE_DEVICE_TABLE(i2c, cs35l34_id); 1217 + 1218 + static struct i2c_driver cs35l34_i2c_driver = { 1219 + .driver = { 1220 + .name = "cs35l34", 1221 + .pm = &cs35l34_pm_ops, 1222 + .of_match_table = cs35l34_of_match, 1223 + 1224 + }, 1225 + .id_table = cs35l34_id, 1226 + .probe = cs35l34_i2c_probe, 1227 + .remove = cs35l34_i2c_remove, 1228 + 1229 + }; 1230 + 1231 + static int __init cs35l34_modinit(void) 1232 + { 1233 + int ret; 1234 + 1235 + ret = i2c_add_driver(&cs35l34_i2c_driver); 1236 + if (ret != 0) { 1237 + pr_err("Failed to register CS35l34 I2C driver: %d\n", ret); 1238 + return ret; 1239 + } 1240 + return 0; 1241 + } 1242 + module_init(cs35l34_modinit); 1243 + 1244 + static void __exit cs35l34_exit(void) 1245 + { 1246 + i2c_del_driver(&cs35l34_i2c_driver); 1247 + } 1248 + module_exit(cs35l34_exit); 1249 + 1250 + MODULE_DESCRIPTION("ASoC CS35l34 driver"); 1251 + MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <Paul.Handrigan@cirrus.com>"); 1252 + MODULE_LICENSE("GPL");
+269
sound/soc/codecs/cs35l34.h
··· 1 + /* 2 + * cs35l34.h -- CS35L34 ALSA SoC audio driver 3 + * 4 + * Copyright 2016 Cirrus Logic, Inc. 5 + * 6 + * Author: Paul Handrigan <Paul.Handrigan@cirrus.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + * 12 + */ 13 + 14 + #ifndef __CS35L34_H__ 15 + #define __CS35L34_H__ 16 + 17 + #define CS35L34_CHIP_ID 0x00035A34 18 + #define CS35L34_DEVID_AB 0x01 /* Device ID A & B [RO] */ 19 + #define CS35L34_DEVID_CD 0x02 /* Device ID C & D [RO] */ 20 + #define CS35L34_DEVID_E 0x03 /* Device ID E [RO] */ 21 + #define CS35L34_FAB_ID 0x04 /* Fab ID [RO] */ 22 + #define CS35L34_REV_ID 0x05 /* Revision ID [RO] */ 23 + #define CS35L34_PWRCTL1 0x06 /* Power Ctl 1 */ 24 + #define CS35L34_PWRCTL2 0x07 /* Power Ctl 2 */ 25 + #define CS35L34_PWRCTL3 0x08 /* Power Ctl 3 */ 26 + #define CS35L34_ADSP_CLK_CTL 0x0A /* (ADSP) Clock Ctl */ 27 + #define CS35L34_MCLK_CTL 0x0B /* Master Clocking Ctl */ 28 + #define CS35L34_AMP_INP_DRV_CTL 0x14 /* Amp Input Drive Ctl */ 29 + #define CS35L34_AMP_DIG_VOL_CTL 0x15 /* Amplifier Dig Volume Ctl */ 30 + #define CS35L34_AMP_DIG_VOL 0x16 /* Amplifier Dig Volume */ 31 + #define CS35L34_AMP_ANLG_GAIN_CTL 0x17 /* Amplifier Analog Gain Ctl */ 32 + #define CS35L34_PROTECT_CTL 0x18 /* Amp Gain - Prot Ctl Param */ 33 + #define CS35L34_AMP_KEEP_ALIVE_CTL 0x1A /* Amplifier Keep Alive Ctl */ 34 + #define CS35L34_BST_CVTR_V_CTL 0x1D /* Boost Conv Voltage Ctl */ 35 + #define CS35L34_BST_PEAK_I 0x1E /* Boost Conv Peak Current */ 36 + #define CS35L34_BST_RAMP_CTL 0x20 /* Boost Conv Soft Ramp Ctl */ 37 + #define CS35L34_BST_CONV_COEF_1 0x21 /* Boost Conv Coefficients 1 */ 38 + #define CS35L34_BST_CONV_COEF_2 0x22 /* Boost Conv Coefficients 2 */ 39 + #define CS35L34_BST_CONV_SLOPE_COMP 0x23 /* Boost Conv Slope Comp */ 40 + #define CS35L34_BST_CONV_SW_FREQ 0x24 /* Boost Conv L BST SW Freq */ 41 + #define CS35L34_CLASS_H_CTL 0x30 /* CLS H Control */ 42 + #define CS35L34_CLASS_H_HEADRM_CTL 0x31 /* CLS H Headroom Ctl */ 43 + #define CS35L34_CLASS_H_RELEASE_RATE 0x32 /* CLS H Release Rate */ 44 + #define CS35L34_CLASS_H_FET_DRIVE_CTL 0x33 /* CLS H Weak FET Drive Ctl */ 45 + #define CS35L34_CLASS_H_STATUS 0x38 /* CLS H Status */ 46 + #define CS35L34_VPBR_CTL 0x3A /* VPBR Ctl */ 47 + #define CS35L34_VPBR_VOL_CTL 0x3B /* VPBR Volume Ctl */ 48 + #define CS35L34_VPBR_TIMING_CTL 0x3C /* VPBR Timing Ctl */ 49 + #define CS35L34_PRED_MAX_ATTEN_SPK_LOAD 0x40 /* PRD Max Atten / Spkr Load */ 50 + #define CS35L34_PRED_BROWNOUT_THRESH 0x41 /* PRD Brownout Threshold */ 51 + #define CS35L34_PRED_BROWNOUT_VOL_CTL 0x42 /* PRD Brownout Volume Ctl */ 52 + #define CS35L34_PRED_BROWNOUT_RATE_CTL 0x43 /* PRD Brownout Rate Ctl */ 53 + #define CS35L34_PRED_WAIT_CTL 0x44 /* PRD Wait Ctl */ 54 + #define CS35L34_PRED_ZVP_INIT_IMP_CTL 0x46 /* PRD ZVP Initial Imp Ctl */ 55 + #define CS35L34_PRED_MAN_SAFE_VPI_CTL 0x47 /* PRD Manual Safe VPI Ctl */ 56 + #define CS35L34_VPBR_ATTEN_STATUS 0x4B /* VPBR Attenuation Status */ 57 + #define CS35L34_PRED_BRWNOUT_ATT_STATUS 0x4C /* PRD Brownout Atten Status */ 58 + #define CS35L34_SPKR_MON_CTL 0x4E /* Speaker Monitoring Ctl */ 59 + #define CS35L34_ADSP_I2S_CTL 0x50 /* ADSP I2S Ctl */ 60 + #define CS35L34_ADSP_TDM_CTL 0x51 /* ADSP TDM Ctl */ 61 + #define CS35L34_TDM_TX_CTL_1_VMON 0x52 /* TDM TX Ctl 1 (VMON) */ 62 + #define CS35L34_TDM_TX_CTL_2_IMON 0x53 /* TDM TX Ctl 2 (IMON) */ 63 + #define CS35L34_TDM_TX_CTL_3_VPMON 0x54 /* TDM TX Ctl 3 (VPMON) */ 64 + #define CS35L34_TDM_TX_CTL_4_VBSTMON 0x55 /* TDM TX Ctl 4 (VBSTMON) */ 65 + #define CS35L34_TDM_TX_CTL_5_FLAG1 0x56 /* TDM TX Ctl 5 (FLAG1) */ 66 + #define CS35L34_TDM_TX_CTL_6_FLAG2 0x57 /* TDM TX Ctl 6 (FLAG2) */ 67 + #define CS35L34_TDM_TX_SLOT_EN_1 0x5A /* TDM TX Slot Enable */ 68 + #define CS35L34_TDM_TX_SLOT_EN_2 0x5B /* TDM TX Slot Enable */ 69 + #define CS35L34_TDM_TX_SLOT_EN_3 0x5C /* TDM TX Slot Enable */ 70 + #define CS35L34_TDM_TX_SLOT_EN_4 0x5D /* TDM TX Slot Enable */ 71 + #define CS35L34_TDM_RX_CTL_1_AUDIN 0x5E /* TDM RX Ctl 1 */ 72 + #define CS35L34_TDM_RX_CTL_3_ALIVE 0x60 /* TDM RX Ctl 3 (ALIVE) */ 73 + #define CS35L34_MULT_DEV_SYNCH1 0x62 /* Multidevice Synch */ 74 + #define CS35L34_MULT_DEV_SYNCH2 0x63 /* Multidevice Synch 2 */ 75 + #define CS35L34_PROT_RELEASE_CTL 0x64 /* Protection Release Ctl */ 76 + #define CS35L34_DIAG_MODE_REG_LOCK 0x68 /* Diagnostic Mode Reg Lock */ 77 + #define CS35L34_DIAG_MODE_CTL_1 0x69 /* Diagnostic Mode Ctl 1 */ 78 + #define CS35L34_DIAG_MODE_CTL_2 0x6A /* Diagnostic Mode Ctl 2 */ 79 + #define CS35L34_INT_MASK_1 0x70 /* Interrupt Mask 1 */ 80 + #define CS35L34_INT_MASK_2 0x71 /* Interrupt Mask 2 */ 81 + #define CS35L34_INT_MASK_3 0x72 /* Interrupt Mask 3 */ 82 + #define CS35L34_INT_MASK_4 0x73 /* Interrupt Mask 4 */ 83 + #define CS35L34_INT_STATUS_1 0x74 /* Interrupt Status 1 */ 84 + #define CS35L34_INT_STATUS_2 0x75 /* Interrupt Status 2 */ 85 + #define CS35L34_INT_STATUS_3 0x76 /* Interrupt Status 3 */ 86 + #define CS35L34_INT_STATUS_4 0x77 /* Interrupt Status 4 */ 87 + #define CS35L34_OTP_TRIM_STATUS 0x7E /* OTP Trim Status */ 88 + 89 + #define CS35L34_MAX_REGISTER 0x7F 90 + #define CS35L34_REGISTER_COUNT 0x4E 91 + 92 + #define CS35L34_MCLK_5644 5644800 93 + #define CS35L34_MCLK_6144 6144000 94 + #define CS35L34_MCLK_6 6000000 95 + #define CS35L34_MCLK_11289 11289600 96 + #define CS35L34_MCLK_12 12000000 97 + #define CS35L34_MCLK_12288 12288000 98 + 99 + /* CS35L34_PWRCTL1 */ 100 + #define CS35L34_SFT_RST (1 << 7) 101 + #define CS35L34_DISCHG_FLT (1 << 1) 102 + #define CS35L34_PDN_ALL 1 103 + 104 + /* CS35L34_PWRCTL2 */ 105 + #define CS35L34_PDN_VMON (1 << 7) 106 + #define CS35L34_PDN_IMON (1 << 6) 107 + #define CS35L34_PDN_CLASSH (1 << 5) 108 + #define CS35L34_PDN_VPBR (1 << 4) 109 + #define CS35L34_PDN_PRED (1 << 3) 110 + #define CS35L34_PDN_BST (1 << 2) 111 + #define CS35L34_PDN_AMP 1 112 + 113 + /* CS35L34_PWRCTL3 */ 114 + #define CS35L34_MCLK_DIS (1 << 7) 115 + #define CS35L34_PDN_VBSTMON_OUT (1 << 4) 116 + #define CS35L34_PDN_VMON_OUT (1 << 3) 117 + /* Tristate the ADSP SDOUT when in I2C mode */ 118 + #define CS35L34_PDN_SDOUT (1 << 2) 119 + #define CS35L34_PDN_SDIN (1 << 1) 120 + #define CS35L34_PDN_TDM 1 121 + 122 + /* CS35L34_ADSP_CLK_CTL */ 123 + #define CS35L34_ADSP_RATE 0xF 124 + #define CS35L34_ADSP_DRIVE (1 << 4) 125 + #define CS35L34_ADSP_M_S (1 << 7) 126 + 127 + /* CS35L34_MCLK_CTL */ 128 + #define CS35L34_MCLK_DIV (1 << 4) 129 + #define CS35L34_MCLK_RATE_MASK 0x7 130 + #define CS35L34_MCLK_RATE_6P1440 0x2 131 + #define CS35L34_MCLK_RATE_6P0000 0x1 132 + #define CS35L34_MCLK_RATE_5P6448 0x0 133 + #define CS35L34_MCLKDIS (1 << 7) 134 + #define CS35L34_MCLKDIV2 (1 << 6) 135 + #define CS35L34_SDOUT_3ST_TDM (1 << 5) 136 + #define CS35L34_INT_FS_RATE (1 << 4) 137 + #define CS35L34_ADSP_FS 0xF 138 + 139 + /* CS35L34_AMP_INP_DRV_CTL */ 140 + #define CS35L34_DRV_STR_SRC (1 << 1) 141 + #define CS35L34_DRV_STR 1 142 + 143 + /* CS35L34_AMP_DIG_VOL_CTL */ 144 + #define CS35L34_AMP_DSR_RATE_MASK 0xF0 145 + #define CS35L34_AMP_DSR_RATE_SHIFT (1 << 4) 146 + #define CS35L34_NOTCH_DIS (1 << 3) 147 + #define CS35L34_AMP_DIGSFT (1 << 1) 148 + #define CS35L34_INV 1 149 + 150 + /* CS35L34_PROTECT_CTL */ 151 + #define CS35L34_OTW_ATTN_MASK 0xC 152 + #define CS35L34_OTW_THRD_MASK 0x3 153 + #define CS35L34_MUTE (1 << 5) 154 + #define CS35L34_GAIN_ZC (1 << 4) 155 + #define CS35L34_GAIN_ZC_MASK 0x10 156 + #define CS35L34_GAIN_ZC_SHIFT 4 157 + 158 + /* CS35L34_AMP_KEEP_ALIVE_CTL */ 159 + #define CS35L34_ALIVE_WD_DIS (1 << 2) 160 + 161 + /* CS35L34_BST_CVTR_V_CTL */ 162 + #define CS35L34_BST_CVTL_MASK 0x3F 163 + 164 + /* CS35L34_BST_PEAK_I */ 165 + #define CS35L34_BST_PEAK_MASK 0x3F 166 + 167 + /* CS35L34_ADSP_I2S_CTL */ 168 + #define CS35L34_I2S_LOC_MASK 0xC 169 + #define CS35L34_I2S_LOC_SHIFT 2 170 + 171 + /* CS35L34_MULT_DEV_SYNCH2 */ 172 + #define CS35L34_SYNC2_MASK 0xF 173 + 174 + /* CS35L34_PROT_RELEASE_CTL */ 175 + #define CS35L34_CAL_ERR_RLS (1 << 7) 176 + #define CS35L34_SHORT_RLS (1 << 2) 177 + #define CS35L34_OTW_RLS (1 << 1) 178 + #define CS35L34_OTE_RLS 1 179 + 180 + /* CS35L34_INT_MASK_1 */ 181 + #define CS35L34_M_CAL_ERR_SHIFT 7 182 + #define CS35L34_M_CAL_ERR (1 << CS35L34_M_CAL_ERR_SHIFT) 183 + #define CS35L34_M_ALIVE_ERR_SHIFT 5 184 + #define CS35L34_M_ALIVE_ERR (1 << CS35L34_M_ALIVE_ERR_SHIFT) 185 + #define CS35L34_M_ADSP_CLK_SHIFT 4 186 + #define CS35L34_M_ADSP_CLK_ERR (1 << CS35L34_M_ADSP_CLK_SHIFT) 187 + #define CS35L34_M_MCLK_SHIFT 3 188 + #define CS35L34_M_MCLK_ERR (1 << CS35L34_M_MCLK_SHIFT) 189 + #define CS35L34_M_AMP_SHORT_SHIFT 2 190 + #define CS35L34_M_AMP_SHORT (1 << CS35L34_M_AMP_SHORT_SHIFT) 191 + #define CS35L34_M_OTW_SHIFT 1 192 + #define CS35L34_M_OTW (1 << CS35L34_M_OTW_SHIFT) 193 + #define CS35L34_M_OTE_SHIFT 0 194 + #define CS35L34_M_OTE (1 << CS35L34_M_OTE_SHIFT) 195 + 196 + /* CS35L34_INT_MASK_2 */ 197 + #define CS35L34_M_PDN_DONE_SHIFT 4 198 + #define CS35L34_M_PDN_DONE (1 << CS35L34_M_PDN_DONE_SHIFT) 199 + #define CS35L34_M_PRED_SHIFT 3 200 + #define CS35L34_M_PRED_ERR (1 << CS35L34_M_PRED_SHIFT) 201 + #define CS35L34_M_PRED_CLR_SHIFT 2 202 + #define CS35L34_M_PRED_CLR (1 << CS35L34_M_PRED_CLR_SHIFT) 203 + #define CS35L34_M_VPBR_SHIFT 1 204 + #define CS35L34_M_VPBR_ERR (1 << CS35L34_M_VPBR_SHIFT) 205 + #define CS35L34_M_VPBR_CLR_SHIFT 0 206 + #define CS35L34_M_VPBR_CLR (1 << CS35L34_M_VPBR_CLR_SHIFT) 207 + 208 + /* CS35L34_INT_MASK_3 */ 209 + #define CS35L34_M_BST_HIGH_SHIFT 4 210 + #define CS35L34_M_BST_HIGH (1 << CS35L34_M_BST_HIGH_SHIFT) 211 + #define CS35L34_M_BST_HIGH_FLAG_SHIFT 3 212 + #define CS35L34_M_BST_HIGH_FLAG (1 << CS35L34_M_BST_HIGH_FLAG_SHIFT) 213 + #define CS35L34_M_BST_IPK_FLAG_SHIFT 2 214 + #define CS35L34_M_BST_IPK_FLAG (1 << CS35L34_M_BST_IPK_FLAG_SHIFT) 215 + #define CS35L34_M_LBST_SHORT_SHIFT 0 216 + #define CS35L34_M_LBST_SHORT (1 << CS35L34_M_LBST_SHORT_SHIFT) 217 + 218 + /* CS35L34_INT_MASK_4 */ 219 + #define CS35L34_M_VMON_OVFL_SHIFT 3 220 + #define CS35L34_M_VMON_OVFL (1 << CS35L34_M_VMON_OVFL_SHIFT) 221 + #define CS35L34_M_IMON_OVFL_SHIFT 2 222 + #define CS35L34_M_IMON_OVFL (1 << CS35L34_M_IMON_OVFL_SHIFT) 223 + #define CS35L34_M_VPMON_OVFL_SHIFT 1 224 + #define CS35L34_M_VPMON_OVFL (1 << CS35L34_M_VPMON_OVFL_SHIFT) 225 + #define CS35L34_M_VBSTMON_OVFL_SHIFT 1 226 + #define CS35L34_M_VBSTMON_OVFL (1 << CS35L34_M_VBSTMON_OVFL_SHIFT) 227 + 228 + /* CS35L34_INT_1 */ 229 + #define CS35L34_CAL_ERR (1 << CS35L34_M_CAL_ERR_SHIFT) 230 + #define CS35L34_ALIVE_ERR (1 << CS35L34_M_ALIVE_ERR_SHIFT) 231 + #define CS35L34_M_ADSP_CLK_ERR (1 << CS35L34_M_ADSP_CLK_SHIFT) 232 + #define CS35L34_MCLK_ERR (1 << CS35L34_M_MCLK_SHIFT) 233 + #define CS35L34_AMP_SHORT (1 << CS35L34_M_AMP_SHORT_SHIFT) 234 + #define CS35L34_OTW (1 << CS35L34_M_OTW_SHIFT) 235 + #define CS35L34_OTE (1 << CS35L34_M_OTE_SHIFT) 236 + 237 + /* CS35L34_INT_2 */ 238 + #define CS35L34_PDN_DONE (1 << CS35L34_M_PDN_DONE_SHIFT) 239 + #define CS35L34_PRED_ERR (1 << CS35L34_M_PRED_SHIFT) 240 + #define CS35L34_PRED_CLR (1 << CS35L34_M_PRED_CLR_SHIFT) 241 + #define CS35L34_VPBR_ERR (1 << CS35L34_M_VPBR_SHIFT) 242 + #define CS35L34_VPBR_CLR (1 << CS35L34_M_VPBR_CLR_SHIFT) 243 + 244 + /* CS35L34_INT_3 */ 245 + #define CS35L34_BST_HIGH (1 << CS35L34_M_BST_HIGH_SHIFT) 246 + #define CS35L34_BST_HIGH_FLAG (1 << CS35L34_M_BST_HIGH_FLAG_SHIFT) 247 + #define CS35L34_BST_IPK_FLAG (1 << CS35L34_M_BST_IPK_FLAG_SHIFT) 248 + #define CS35L34_LBST_SHORT (1 << CS35L34_M_LBST_SHORT_SHIFT) 249 + 250 + /* CS35L34_INT_4 */ 251 + #define CS35L34_VMON_OVFL (1 << CS35L34_M_VMON_OVFL_SHIFT) 252 + #define CS35L34_IMON_OVFL (1 << CS35L34_M_IMON_OVFL_SHIFT) 253 + #define CS35L34_VPMON_OVFL (1 << CS35L34_M_VPMON_OVFL_SHIFT) 254 + #define CS35L34_VBSTMON_OVFL (1 << CS35L34_M_VBSTMON_OVFL_SHIFT) 255 + 256 + /* CS35L34_{RX,TX}_X */ 257 + #define CS35L34_X_STATE_SHIFT 7 258 + #define CS35L34_X_STATE (1 << CS35L34_X_STATE_SHIFT) 259 + #define CS35L34_X_LOC_SHIFT 0 260 + #define CS35L34_X_LOC (0x1F << CS35L34_X_LOC_SHIFT) 261 + 262 + #define CS35L34_RATES (SNDRV_PCM_RATE_48000 | \ 263 + SNDRV_PCM_RATE_44100 | \ 264 + SNDRV_PCM_RATE_32000) 265 + #define CS35L34_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 266 + SNDRV_PCM_FMTBIT_S24_LE | \ 267 + SNDRV_PCM_FMTBIT_S32_LE) 268 + 269 + #endif