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

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

Initial commit of the Cirrus Logic cs35l33 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
3333cb71 1a695a90

+1591
+48
include/sound/cs35l33.h
··· 1 + /* 2 + * linux/sound/cs35l33.h -- Platform data for CS35l33 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 __CS35L33_H 12 + #define __CS35L33_H 13 + 14 + struct cs35l33_hg { 15 + bool enable_hg_algo; 16 + unsigned int mem_depth; 17 + unsigned int release_rate; 18 + unsigned int hd_rm; 19 + unsigned int ldo_thld; 20 + unsigned int ldo_path_disable; 21 + unsigned int ldo_entry_delay; 22 + bool vp_hg_auto; 23 + unsigned int vp_hg; 24 + unsigned int vp_hg_rate; 25 + unsigned int vp_hg_va; 26 + }; 27 + 28 + struct cs35l33_pdata { 29 + /* Boost Controller Voltage Setting */ 30 + unsigned int boost_ctl; 31 + 32 + /* Boost Controller Peak Current */ 33 + unsigned int boost_ipk; 34 + 35 + /* Amplifier Drive Select */ 36 + unsigned int amp_drv_sel; 37 + 38 + /* soft volume ramp */ 39 + unsigned int ramp_rate; 40 + 41 + /* IMON adc scale */ 42 + unsigned int imon_adc_scale; 43 + 44 + /* H/G algo configuration */ 45 + struct cs35l33_hg hg_config; 46 + }; 47 + 48 + #endif /* __CS35L33_H */
+5
sound/soc/codecs/Kconfig
··· 46 46 select SND_SOC_BT_SCO 47 47 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC 48 48 select SND_SOC_CS35L32 if I2C 49 + select SND_SOC_CS35L33 if I2C 49 50 select SND_SOC_CS42L51_I2C if I2C 50 51 select SND_SOC_CS42L52 if I2C && INPUT 51 52 select SND_SOC_CS42L56 if I2C && INPUT ··· 379 378 380 379 config SND_SOC_CS35L32 381 380 tristate "Cirrus Logic CS35L32 CODEC" 381 + depends on I2C 382 + 383 + config SND_SOC_CS35L33 384 + tristate "Cirrus Logic CS35L33 CODEC" 382 385 depends on I2C 383 386 384 387 config SND_SOC_CS42L51
+2
sound/soc/codecs/Makefile
··· 35 35 snd-soc-bt-sco-objs := bt-sco.o 36 36 snd-soc-cq93vc-objs := cq93vc.o 37 37 snd-soc-cs35l32-objs := cs35l32.o 38 + snd-soc-cs35l33-objs := cs35l33.o 38 39 snd-soc-cs42l51-objs := cs42l51.o 39 40 snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o 40 41 snd-soc-cs42l52-objs := cs42l52.o ··· 251 250 obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o 252 251 obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o 253 252 obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o 253 + obj-$(CONFIG_SND_SOC_CS35L33) += snd-soc-cs35l33.o 254 254 obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o 255 255 obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o 256 256 obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
+1315
sound/soc/codecs/cs35l33.c
··· 1 + /* 2 + * cs35l33.c -- CS35L33 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 + #include <linux/module.h> 14 + #include <linux/moduleparam.h> 15 + #include <linux/version.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 <sound/core.h> 24 + #include <sound/pcm.h> 25 + #include <sound/pcm_params.h> 26 + #include <sound/soc.h> 27 + #include <sound/soc-dapm.h> 28 + #include <sound/initval.h> 29 + #include <sound/tlv.h> 30 + #include <linux/gpio.h> 31 + #include <linux/gpio/consumer.h> 32 + #include <sound/cs35l33.h> 33 + #include <linux/pm_runtime.h> 34 + #include <linux/regulator/consumer.h> 35 + #include <linux/regulator/machine.h> 36 + #include <linux/of_gpio.h> 37 + #include <linux/of.h> 38 + #include <linux/of_device.h> 39 + #include <linux/of_irq.h> 40 + 41 + #include "cs35l33.h" 42 + 43 + #define CS35L33_BOOT_DELAY 50 44 + 45 + struct cs35l33_private { 46 + struct snd_soc_codec *codec; 47 + struct cs35l33_pdata pdata; 48 + struct regmap *regmap; 49 + struct gpio_desc *reset_gpio; 50 + bool amp_cal; 51 + int mclk_int; 52 + struct regulator_bulk_data core_supplies[2]; 53 + int num_core_supplies; 54 + bool is_tdm_mode; 55 + bool enable_soft_ramp; 56 + }; 57 + 58 + static const struct reg_default cs35l33_reg[] = { 59 + {CS35L33_PWRCTL1, 0x85}, 60 + {CS35L33_PWRCTL2, 0xFE}, 61 + {CS35L33_CLK_CTL, 0x0C}, 62 + {CS35L33_BST_PEAK_CTL, 0x90}, 63 + {CS35L33_PROTECT_CTL, 0x55}, 64 + {CS35L33_BST_CTL1, 0x00}, 65 + {CS35L33_BST_CTL2, 0x01}, 66 + {CS35L33_ADSP_CTL, 0x00}, 67 + {CS35L33_ADC_CTL, 0xC8}, 68 + {CS35L33_DAC_CTL, 0x14}, 69 + {CS35L33_DIG_VOL_CTL, 0x00}, 70 + {CS35L33_CLASSD_CTL, 0x04}, 71 + {CS35L33_AMP_CTL, 0x90}, 72 + {CS35L33_INT_MASK_1, 0xFF}, 73 + {CS35L33_INT_MASK_2, 0xFF}, 74 + {CS35L33_DIAG_LOCK, 0x00}, 75 + {CS35L33_DIAG_CTRL_1, 0x40}, 76 + {CS35L33_DIAG_CTRL_2, 0x00}, 77 + {CS35L33_HG_MEMLDO_CTL, 0x62}, 78 + {CS35L33_HG_REL_RATE, 0x03}, 79 + {CS35L33_LDO_DEL, 0x12}, 80 + {CS35L33_HG_HEAD, 0x0A}, 81 + {CS35L33_HG_EN, 0x05}, 82 + {CS35L33_TX_VMON, 0x00}, 83 + {CS35L33_TX_IMON, 0x03}, 84 + {CS35L33_TX_VPMON, 0x02}, 85 + {CS35L33_TX_VBSTMON, 0x05}, 86 + {CS35L33_TX_FLAG, 0x06}, 87 + {CS35L33_TX_EN1, 0x00}, 88 + {CS35L33_TX_EN2, 0x00}, 89 + {CS35L33_TX_EN3, 0x00}, 90 + {CS35L33_TX_EN4, 0x00}, 91 + {CS35L33_RX_AUD, 0x40}, 92 + {CS35L33_RX_SPLY, 0x03}, 93 + {CS35L33_RX_ALIVE, 0x04}, 94 + {CS35L33_BST_CTL4, 0x63}, 95 + }; 96 + 97 + static const struct reg_sequence cs35l33_patch[] = { 98 + { 0x00, 0x99, 0 }, 99 + { 0x59, 0x02, 0 }, 100 + { 0x52, 0x30, 0 }, 101 + { 0x39, 0x45, 0 }, 102 + { 0x57, 0x30, 0 }, 103 + { 0x2C, 0x68, 0 }, 104 + { 0x00, 0x00, 0 }, 105 + }; 106 + 107 + static bool cs35l33_volatile_register(struct device *dev, unsigned int reg) 108 + { 109 + switch (reg) { 110 + case CS35L33_DEVID_AB: 111 + case CS35L33_DEVID_CD: 112 + case CS35L33_DEVID_E: 113 + case CS35L33_REV_ID: 114 + case CS35L33_INT_STATUS_1: 115 + case CS35L33_INT_STATUS_2: 116 + case CS35L33_HG_STATUS: 117 + return true; 118 + default: 119 + return false; 120 + } 121 + } 122 + 123 + static bool cs35l33_writeable_register(struct device *dev, unsigned int reg) 124 + { 125 + switch (reg) { 126 + /* these are read only registers */ 127 + case CS35L33_DEVID_AB: 128 + case CS35L33_DEVID_CD: 129 + case CS35L33_DEVID_E: 130 + case CS35L33_REV_ID: 131 + case CS35L33_INT_STATUS_1: 132 + case CS35L33_INT_STATUS_2: 133 + case CS35L33_HG_STATUS: 134 + return false; 135 + default: 136 + return true; 137 + } 138 + } 139 + 140 + static bool cs35l33_readable_register(struct device *dev, unsigned int reg) 141 + { 142 + switch (reg) { 143 + case CS35L33_DEVID_AB: 144 + case CS35L33_DEVID_CD: 145 + case CS35L33_DEVID_E: 146 + case CS35L33_REV_ID: 147 + case CS35L33_PWRCTL1: 148 + case CS35L33_PWRCTL2: 149 + case CS35L33_CLK_CTL: 150 + case CS35L33_BST_PEAK_CTL: 151 + case CS35L33_PROTECT_CTL: 152 + case CS35L33_BST_CTL1: 153 + case CS35L33_BST_CTL2: 154 + case CS35L33_ADSP_CTL: 155 + case CS35L33_ADC_CTL: 156 + case CS35L33_DAC_CTL: 157 + case CS35L33_DIG_VOL_CTL: 158 + case CS35L33_CLASSD_CTL: 159 + case CS35L33_AMP_CTL: 160 + case CS35L33_INT_MASK_1: 161 + case CS35L33_INT_MASK_2: 162 + case CS35L33_INT_STATUS_1: 163 + case CS35L33_INT_STATUS_2: 164 + case CS35L33_DIAG_LOCK: 165 + case CS35L33_DIAG_CTRL_1: 166 + case CS35L33_DIAG_CTRL_2: 167 + case CS35L33_HG_MEMLDO_CTL: 168 + case CS35L33_HG_REL_RATE: 169 + case CS35L33_LDO_DEL: 170 + case CS35L33_HG_HEAD: 171 + case CS35L33_HG_EN: 172 + case CS35L33_TX_VMON: 173 + case CS35L33_TX_IMON: 174 + case CS35L33_TX_VPMON: 175 + case CS35L33_TX_VBSTMON: 176 + case CS35L33_TX_FLAG: 177 + case CS35L33_TX_EN1: 178 + case CS35L33_TX_EN2: 179 + case CS35L33_TX_EN3: 180 + case CS35L33_TX_EN4: 181 + case CS35L33_RX_AUD: 182 + case CS35L33_RX_SPLY: 183 + case CS35L33_RX_ALIVE: 184 + case CS35L33_BST_CTL4: 185 + return true; 186 + default: 187 + return false; 188 + } 189 + } 190 + 191 + static DECLARE_TLV_DB_SCALE(classd_ctl_tlv, 900, 100, 0); 192 + static DECLARE_TLV_DB_SCALE(dac_tlv, -10200, 50, 0); 193 + 194 + static const struct snd_kcontrol_new cs35l33_snd_controls[] = { 195 + 196 + SOC_SINGLE_TLV("SPK Amp Volume", CS35L33_AMP_CTL, 197 + 4, 0x09, 0, classd_ctl_tlv), 198 + SOC_SINGLE_SX_TLV("DAC Volume", CS35L33_DIG_VOL_CTL, 199 + 0, 0x34, 0xE4, dac_tlv), 200 + }; 201 + 202 + static int cs35l33_spkrdrv_event(struct snd_soc_dapm_widget *w, 203 + struct snd_kcontrol *kcontrol, int event) 204 + { 205 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 206 + struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); 207 + 208 + switch (event) { 209 + case SND_SOC_DAPM_POST_PMU: 210 + if (!priv->amp_cal) { 211 + usleep_range(8000, 9000); 212 + priv->amp_cal = true; 213 + regmap_update_bits(priv->regmap, CS35L33_CLASSD_CTL, 214 + CS35L33_AMP_CAL, 0); 215 + dev_dbg(codec->dev, "Amp calibration done\n"); 216 + } 217 + dev_dbg(codec->dev, "Amp turned on\n"); 218 + break; 219 + case SND_SOC_DAPM_POST_PMD: 220 + dev_dbg(codec->dev, "Amp turned off\n"); 221 + break; 222 + default: 223 + dev_err(codec->dev, "Invalid event = 0x%x\n", event); 224 + break; 225 + } 226 + 227 + return 0; 228 + } 229 + 230 + static int cs35l33_sdin_event(struct snd_soc_dapm_widget *w, 231 + struct snd_kcontrol *kcontrol, int event) 232 + { 233 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 234 + struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); 235 + unsigned int val; 236 + 237 + switch (event) { 238 + case SND_SOC_DAPM_PRE_PMU: 239 + regmap_update_bits(priv->regmap, CS35L33_PWRCTL1, 240 + CS35L33_PDN_BST, 0); 241 + val = priv->is_tdm_mode ? 0 : CS35L33_PDN_TDM; 242 + regmap_update_bits(priv->regmap, CS35L33_PWRCTL2, 243 + CS35L33_PDN_TDM, val); 244 + dev_dbg(codec->dev, "BST turned on\n"); 245 + break; 246 + case SND_SOC_DAPM_POST_PMU: 247 + dev_dbg(codec->dev, "SDIN turned on\n"); 248 + if (!priv->amp_cal) { 249 + regmap_update_bits(priv->regmap, CS35L33_CLASSD_CTL, 250 + CS35L33_AMP_CAL, CS35L33_AMP_CAL); 251 + dev_dbg(codec->dev, "Amp calibration started\n"); 252 + usleep_range(10000, 11000); 253 + } 254 + break; 255 + case SND_SOC_DAPM_POST_PMD: 256 + regmap_update_bits(priv->regmap, CS35L33_PWRCTL2, 257 + CS35L33_PDN_TDM, CS35L33_PDN_TDM); 258 + usleep_range(4000, 4100); 259 + regmap_update_bits(priv->regmap, CS35L33_PWRCTL1, 260 + CS35L33_PDN_BST, CS35L33_PDN_BST); 261 + dev_dbg(codec->dev, "BST and SDIN turned off\n"); 262 + break; 263 + default: 264 + dev_err(codec->dev, "Invalid event = 0x%x\n", event); 265 + 266 + } 267 + 268 + return 0; 269 + } 270 + 271 + static int cs35l33_sdout_event(struct snd_soc_dapm_widget *w, 272 + struct snd_kcontrol *kcontrol, int event) 273 + { 274 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 275 + struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); 276 + unsigned int mask = CS35L33_SDOUT_3ST_I2S | CS35L33_PDN_TDM; 277 + unsigned int mask2 = CS35L33_SDOUT_3ST_TDM; 278 + unsigned int val, val2; 279 + 280 + switch (event) { 281 + case SND_SOC_DAPM_PRE_PMU: 282 + if (priv->is_tdm_mode) { 283 + /* set sdout_3st_i2s and reset pdn_tdm */ 284 + val = CS35L33_SDOUT_3ST_I2S; 285 + /* reset sdout_3st_tdm */ 286 + val2 = 0; 287 + } else { 288 + /* reset sdout_3st_i2s and set pdn_tdm */ 289 + val = CS35L33_PDN_TDM; 290 + /* set sdout_3st_tdm */ 291 + val2 = CS35L33_SDOUT_3ST_TDM; 292 + } 293 + dev_dbg(codec->dev, "SDOUT turned on\n"); 294 + break; 295 + case SND_SOC_DAPM_PRE_PMD: 296 + val = CS35L33_SDOUT_3ST_I2S | CS35L33_PDN_TDM; 297 + val2 = CS35L33_SDOUT_3ST_TDM; 298 + dev_dbg(codec->dev, "SDOUT turned off\n"); 299 + break; 300 + default: 301 + dev_err(codec->dev, "Invalid event = 0x%x\n", event); 302 + return 0; 303 + } 304 + 305 + regmap_update_bits(priv->regmap, CS35L33_PWRCTL2, 306 + mask, val); 307 + regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 308 + mask2, val2); 309 + 310 + return 0; 311 + } 312 + 313 + static const struct snd_soc_dapm_widget cs35l33_dapm_widgets[] = { 314 + 315 + SND_SOC_DAPM_OUTPUT("SPK"), 316 + SND_SOC_DAPM_OUT_DRV_E("SPKDRV", CS35L33_PWRCTL1, 7, 1, NULL, 0, 317 + cs35l33_spkrdrv_event, 318 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 319 + SND_SOC_DAPM_AIF_IN_E("SDIN", NULL, 0, CS35L33_PWRCTL2, 320 + 2, 1, cs35l33_sdin_event, SND_SOC_DAPM_PRE_PMU | 321 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 322 + 323 + SND_SOC_DAPM_INPUT("MON"), 324 + 325 + SND_SOC_DAPM_ADC("VMON", NULL, 326 + CS35L33_PWRCTL2, CS35L33_PDN_VMON_SHIFT, 1), 327 + SND_SOC_DAPM_ADC("IMON", NULL, 328 + CS35L33_PWRCTL2, CS35L33_PDN_IMON_SHIFT, 1), 329 + SND_SOC_DAPM_ADC("VPMON", NULL, 330 + CS35L33_PWRCTL2, CS35L33_PDN_VPMON_SHIFT, 1), 331 + SND_SOC_DAPM_ADC("VBSTMON", NULL, 332 + CS35L33_PWRCTL2, CS35L33_PDN_VBSTMON_SHIFT, 1), 333 + 334 + SND_SOC_DAPM_AIF_OUT_E("SDOUT", NULL, 0, SND_SOC_NOPM, 0, 0, 335 + cs35l33_sdout_event, SND_SOC_DAPM_PRE_PMU | 336 + SND_SOC_DAPM_PRE_PMD), 337 + }; 338 + 339 + static const struct snd_soc_dapm_route cs35l33_audio_map[] = { 340 + {"SDIN", NULL, "CS35L33 Playback"}, 341 + {"SPKDRV", NULL, "SDIN"}, 342 + {"SPK", NULL, "SPKDRV"}, 343 + 344 + {"VMON", NULL, "MON"}, 345 + {"IMON", NULL, "MON"}, 346 + 347 + {"SDOUT", NULL, "VMON"}, 348 + {"SDOUT", NULL, "IMON"}, 349 + {"CS35L33 Capture", NULL, "SDOUT"}, 350 + }; 351 + 352 + static const struct snd_soc_dapm_route cs35l33_vphg_auto_route[] = { 353 + {"SPKDRV", NULL, "VPMON"}, 354 + {"VPMON", NULL, "CS35L33 Playback"}, 355 + }; 356 + 357 + static const struct snd_soc_dapm_route cs35l33_vp_vbst_mon_route[] = { 358 + {"SDOUT", NULL, "VPMON"}, 359 + {"VPMON", NULL, "MON"}, 360 + {"SDOUT", NULL, "VBSTMON"}, 361 + {"VBSTMON", NULL, "MON"}, 362 + }; 363 + 364 + static int cs35l33_set_bias_level(struct snd_soc_codec *codec, 365 + enum snd_soc_bias_level level) 366 + { 367 + unsigned int val; 368 + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 369 + struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); 370 + 371 + switch (level) { 372 + case SND_SOC_BIAS_ON: 373 + break; 374 + case SND_SOC_BIAS_PREPARE: 375 + regmap_update_bits(priv->regmap, CS35L33_PWRCTL1, 376 + CS35L33_PDN_ALL, 0); 377 + regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 378 + CS35L33_MCLKDIS, 0); 379 + break; 380 + case SND_SOC_BIAS_STANDBY: 381 + regmap_update_bits(priv->regmap, CS35L33_PWRCTL1, 382 + CS35L33_PDN_ALL, CS35L33_PDN_ALL); 383 + regmap_read(priv->regmap, CS35L33_INT_STATUS_2, &val); 384 + usleep_range(1000, 1100); 385 + if (val & CS35L33_PDN_DONE) 386 + regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 387 + CS35L33_MCLKDIS, CS35L33_MCLKDIS); 388 + break; 389 + case SND_SOC_BIAS_OFF: 390 + break; 391 + default: 392 + return -EINVAL; 393 + } 394 + 395 + dapm->bias_level = level; 396 + 397 + return 0; 398 + } 399 + 400 + struct cs35l33_mclk_div { 401 + int mclk; 402 + int srate; 403 + u8 adsp_rate; 404 + u8 int_fs_ratio; 405 + }; 406 + 407 + static const struct cs35l33_mclk_div cs35l33_mclk_coeffs[] = { 408 + /* MCLK, Sample Rate, adsp_rate, int_fs_ratio */ 409 + {5644800, 11025, 0x4, CS35L33_INT_FS_RATE}, 410 + {5644800, 22050, 0x8, CS35L33_INT_FS_RATE}, 411 + {5644800, 44100, 0xC, CS35L33_INT_FS_RATE}, 412 + 413 + {6000000, 8000, 0x1, 0}, 414 + {6000000, 11025, 0x2, 0}, 415 + {6000000, 11029, 0x3, 0}, 416 + {6000000, 12000, 0x4, 0}, 417 + {6000000, 16000, 0x5, 0}, 418 + {6000000, 22050, 0x6, 0}, 419 + {6000000, 22059, 0x7, 0}, 420 + {6000000, 24000, 0x8, 0}, 421 + {6000000, 32000, 0x9, 0}, 422 + {6000000, 44100, 0xA, 0}, 423 + {6000000, 44118, 0xB, 0}, 424 + {6000000, 48000, 0xC, 0}, 425 + 426 + {6144000, 8000, 0x1, CS35L33_INT_FS_RATE}, 427 + {6144000, 12000, 0x4, CS35L33_INT_FS_RATE}, 428 + {6144000, 16000, 0x5, CS35L33_INT_FS_RATE}, 429 + {6144000, 24000, 0x8, CS35L33_INT_FS_RATE}, 430 + {6144000, 32000, 0x9, CS35L33_INT_FS_RATE}, 431 + {6144000, 48000, 0xC, CS35L33_INT_FS_RATE}, 432 + }; 433 + 434 + static int cs35l33_get_mclk_coeff(int mclk, int srate) 435 + { 436 + int i; 437 + 438 + for (i = 0; i < ARRAY_SIZE(cs35l33_mclk_coeffs); i++) { 439 + if (cs35l33_mclk_coeffs[i].mclk == mclk && 440 + cs35l33_mclk_coeffs[i].srate == srate) 441 + return i; 442 + } 443 + return -EINVAL; 444 + } 445 + 446 + static int cs35l33_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 447 + { 448 + struct snd_soc_codec *codec = codec_dai->codec; 449 + struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); 450 + 451 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 452 + case SND_SOC_DAIFMT_CBM_CFM: 453 + regmap_update_bits(priv->regmap, CS35L33_ADSP_CTL, 454 + CS35L33_MS_MASK, CS35L33_MS_MASK); 455 + dev_dbg(codec->dev, "Audio port in master mode\n"); 456 + break; 457 + case SND_SOC_DAIFMT_CBS_CFS: 458 + regmap_update_bits(priv->regmap, CS35L33_ADSP_CTL, 459 + CS35L33_MS_MASK, 0); 460 + dev_dbg(codec->dev, "Audio port in slave mode\n"); 461 + break; 462 + default: 463 + return -EINVAL; 464 + } 465 + 466 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 467 + case SND_SOC_DAIFMT_DSP_A: 468 + /* 469 + * tdm mode in cs35l33 resembles dsp-a mode very 470 + * closely, it is dsp-a with fsync shifted left by half bclk 471 + */ 472 + priv->is_tdm_mode = true; 473 + dev_dbg(codec->dev, "Audio port in TDM mode\n"); 474 + break; 475 + case SND_SOC_DAIFMT_I2S: 476 + priv->is_tdm_mode = false; 477 + dev_dbg(codec->dev, "Audio port in I2S mode\n"); 478 + break; 479 + default: 480 + return -EINVAL; 481 + } 482 + 483 + return 0; 484 + } 485 + 486 + static int cs35l33_pcm_hw_params(struct snd_pcm_substream *substream, 487 + struct snd_pcm_hw_params *params, 488 + struct snd_soc_dai *dai) 489 + { 490 + struct snd_soc_codec *codec = dai->codec; 491 + struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); 492 + int sample_size = params_width(params); 493 + int coeff = cs35l33_get_mclk_coeff(priv->mclk_int, params_rate(params)); 494 + 495 + if (coeff < 0) 496 + return coeff; 497 + 498 + regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 499 + CS35L33_ADSP_FS | CS35L33_INT_FS_RATE, 500 + cs35l33_mclk_coeffs[coeff].int_fs_ratio 501 + | cs35l33_mclk_coeffs[coeff].adsp_rate); 502 + 503 + if (priv->is_tdm_mode) { 504 + sample_size = (sample_size / 8) - 1; 505 + if (sample_size > 2) 506 + sample_size = 2; 507 + regmap_update_bits(priv->regmap, CS35L33_RX_AUD, 508 + CS35L33_AUDIN_RX_DEPTH, 509 + sample_size << CS35L33_AUDIN_RX_DEPTH_SHIFT); 510 + } 511 + 512 + dev_dbg(codec->dev, "sample rate=%d, bits per sample=%d\n", 513 + params_rate(params), params_width(params)); 514 + 515 + return 0; 516 + } 517 + 518 + static const unsigned int cs35l33_src_rates[] = { 519 + 8000, 11025, 11029, 12000, 16000, 22050, 520 + 22059, 24000, 32000, 44100, 44118, 48000 521 + }; 522 + 523 + static const struct snd_pcm_hw_constraint_list cs35l33_constraints = { 524 + .count = ARRAY_SIZE(cs35l33_src_rates), 525 + .list = cs35l33_src_rates, 526 + }; 527 + 528 + static int cs35l33_pcm_startup(struct snd_pcm_substream *substream, 529 + struct snd_soc_dai *dai) 530 + { 531 + snd_pcm_hw_constraint_list(substream->runtime, 0, 532 + SNDRV_PCM_HW_PARAM_RATE, 533 + &cs35l33_constraints); 534 + return 0; 535 + } 536 + 537 + static int cs35l33_set_tristate(struct snd_soc_dai *dai, int tristate) 538 + { 539 + struct snd_soc_codec *codec = dai->codec; 540 + struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); 541 + 542 + if (tristate) { 543 + regmap_update_bits(priv->regmap, CS35L33_PWRCTL2, 544 + CS35L33_SDOUT_3ST_I2S, CS35L33_SDOUT_3ST_I2S); 545 + regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 546 + CS35L33_SDOUT_3ST_TDM, CS35L33_SDOUT_3ST_TDM); 547 + } else { 548 + regmap_update_bits(priv->regmap, CS35L33_PWRCTL2, 549 + CS35L33_SDOUT_3ST_I2S, 0); 550 + regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 551 + CS35L33_SDOUT_3ST_TDM, 0); 552 + } 553 + 554 + return 0; 555 + } 556 + 557 + static int cs35l33_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 558 + unsigned int rx_mask, int slots, int slot_width) 559 + { 560 + struct snd_soc_codec *codec = dai->codec; 561 + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 562 + struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); 563 + unsigned int reg, bit_pos, i; 564 + int slot, slot_num; 565 + 566 + if (slot_width != 8) 567 + return -EINVAL; 568 + 569 + /* scan rx_mask for aud slot */ 570 + slot = ffs(rx_mask) - 1; 571 + if (slot >= 0) { 572 + regmap_update_bits(priv->regmap, CS35L33_RX_AUD, 573 + CS35L33_X_LOC, slot); 574 + dev_dbg(codec->dev, "Audio starts from slots %d", slot); 575 + } 576 + 577 + /* 578 + * scan tx_mask: vmon(2 slots); imon (2 slots); 579 + * vpmon (1 slot) vbstmon (1 slot) 580 + */ 581 + slot = ffs(tx_mask) - 1; 582 + slot_num = 0; 583 + 584 + for (i = 0; i < 2 ; i++) { 585 + /* disable vpmon/vbstmon: enable later if set in tx_mask */ 586 + regmap_update_bits(priv->regmap, CS35L33_TX_VPMON + i, 587 + CS35L33_X_STATE | CS35L33_X_LOC, CS35L33_X_STATE 588 + | CS35L33_X_LOC); 589 + } 590 + 591 + /* disconnect {vp,vbst}_mon routes: eanble later if set in tx_mask*/ 592 + snd_soc_dapm_del_routes(dapm, cs35l33_vp_vbst_mon_route, 593 + ARRAY_SIZE(cs35l33_vp_vbst_mon_route)); 594 + 595 + while (slot >= 0) { 596 + /* configure VMON_TX_LOC */ 597 + if (slot_num == 0) { 598 + regmap_update_bits(priv->regmap, CS35L33_TX_VMON, 599 + CS35L33_X_STATE | CS35L33_X_LOC, slot); 600 + dev_dbg(codec->dev, "VMON enabled in slots %d-%d", 601 + slot, slot + 1); 602 + } 603 + 604 + /* configure IMON_TX_LOC */ 605 + if (slot_num == 3) { 606 + regmap_update_bits(priv->regmap, CS35L33_TX_IMON, 607 + CS35L33_X_STATE | CS35L33_X_LOC, slot); 608 + dev_dbg(codec->dev, "IMON enabled in slots %d-%d", 609 + slot, slot + 1); 610 + } 611 + 612 + /* configure VPMON_TX_LOC */ 613 + if (slot_num == 4) { 614 + regmap_update_bits(priv->regmap, CS35L33_TX_VPMON, 615 + CS35L33_X_STATE | CS35L33_X_LOC, slot); 616 + snd_soc_dapm_add_routes(dapm, 617 + &cs35l33_vp_vbst_mon_route[0], 2); 618 + dev_dbg(codec->dev, "VPMON enabled in slots %d", slot); 619 + } 620 + 621 + /* configure VBSTMON_TX_LOC */ 622 + if (slot_num == 5) { 623 + regmap_update_bits(priv->regmap, CS35L33_TX_VBSTMON, 624 + CS35L33_X_STATE | CS35L33_X_LOC, slot); 625 + snd_soc_dapm_add_routes(dapm, 626 + &cs35l33_vp_vbst_mon_route[2], 2); 627 + dev_dbg(codec->dev, 628 + "VBSTMON enabled in slots %d", slot); 629 + } 630 + 631 + /* Enable the relevant tx slot */ 632 + reg = CS35L33_TX_EN4 - (slot/8); 633 + bit_pos = slot - ((slot / 8) * (8)); 634 + regmap_update_bits(priv->regmap, reg, 635 + 1 << bit_pos, 1 << bit_pos); 636 + 637 + tx_mask &= ~(1 << slot); 638 + slot = ffs(tx_mask) - 1; 639 + slot_num++; 640 + } 641 + 642 + return 0; 643 + } 644 + 645 + static int cs35l33_codec_set_sysclk(struct snd_soc_codec *codec, 646 + int clk_id, int source, unsigned int freq, int dir) 647 + { 648 + struct cs35l33_private *cs35l33 = snd_soc_codec_get_drvdata(codec); 649 + 650 + switch (freq) { 651 + case CS35L33_MCLK_5644: 652 + case CS35L33_MCLK_6: 653 + case CS35L33_MCLK_6144: 654 + regmap_update_bits(cs35l33->regmap, CS35L33_CLK_CTL, 655 + CS35L33_MCLKDIV2, 0); 656 + cs35l33->mclk_int = freq; 657 + break; 658 + case CS35L33_MCLK_11289: 659 + case CS35L33_MCLK_12: 660 + case CS35L33_MCLK_12288: 661 + regmap_update_bits(cs35l33->regmap, CS35L33_CLK_CTL, 662 + CS35L33_MCLKDIV2, CS35L33_MCLKDIV2); 663 + cs35l33->mclk_int = freq/2; 664 + break; 665 + default: 666 + cs35l33->mclk_int = 0; 667 + return -EINVAL; 668 + } 669 + 670 + dev_dbg(codec->dev, "external mclk freq=%d, internal mclk freq=%d\n", 671 + freq, cs35l33->mclk_int); 672 + 673 + return 0; 674 + } 675 + 676 + static const struct snd_soc_dai_ops cs35l33_ops = { 677 + .startup = cs35l33_pcm_startup, 678 + .set_tristate = cs35l33_set_tristate, 679 + .set_fmt = cs35l33_set_dai_fmt, 680 + .hw_params = cs35l33_pcm_hw_params, 681 + .set_tdm_slot = cs35l33_set_tdm_slot, 682 + }; 683 + 684 + static struct snd_soc_dai_driver cs35l33_dai = { 685 + .name = "cs35l33-dai", 686 + .id = 0, 687 + .playback = { 688 + .stream_name = "CS35L33 Playback", 689 + .channels_min = 1, 690 + .channels_max = 1, 691 + .rates = CS35L33_RATES, 692 + .formats = CS35L33_FORMATS, 693 + }, 694 + .capture = { 695 + .stream_name = "CS35L33 Capture", 696 + .channels_min = 2, 697 + .channels_max = 2, 698 + .rates = CS35L33_RATES, 699 + .formats = CS35L33_FORMATS, 700 + }, 701 + .ops = &cs35l33_ops, 702 + .symmetric_rates = 1, 703 + }; 704 + 705 + static int cs35l33_set_hg_data(struct snd_soc_codec *codec, 706 + struct cs35l33_pdata *pdata) 707 + { 708 + struct cs35l33_hg *hg_config = &pdata->hg_config; 709 + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 710 + struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); 711 + 712 + if (hg_config->enable_hg_algo) { 713 + regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL, 714 + CS35L33_MEM_DEPTH_MASK, 715 + hg_config->mem_depth << CS35L33_MEM_DEPTH_SHIFT); 716 + regmap_write(priv->regmap, CS35L33_HG_REL_RATE, 717 + hg_config->release_rate); 718 + regmap_update_bits(priv->regmap, CS35L33_HG_HEAD, 719 + CS35L33_HD_RM_MASK, 720 + hg_config->hd_rm << CS35L33_HD_RM_SHIFT); 721 + regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL, 722 + CS35L33_LDO_THLD_MASK, 723 + hg_config->ldo_thld << CS35L33_LDO_THLD_SHIFT); 724 + regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL, 725 + CS35L33_LDO_DISABLE_MASK, 726 + hg_config->ldo_path_disable << 727 + CS35L33_LDO_DISABLE_SHIFT); 728 + regmap_update_bits(priv->regmap, CS35L33_LDO_DEL, 729 + CS35L33_LDO_ENTRY_DELAY_MASK, 730 + hg_config->ldo_entry_delay << 731 + CS35L33_LDO_ENTRY_DELAY_SHIFT); 732 + if (hg_config->vp_hg_auto) { 733 + regmap_update_bits(priv->regmap, CS35L33_HG_EN, 734 + CS35L33_VP_HG_AUTO_MASK, 735 + CS35L33_VP_HG_AUTO_MASK); 736 + snd_soc_dapm_add_routes(dapm, cs35l33_vphg_auto_route, 737 + ARRAY_SIZE(cs35l33_vphg_auto_route)); 738 + } 739 + regmap_update_bits(priv->regmap, CS35L33_HG_EN, 740 + CS35L33_VP_HG_MASK, 741 + hg_config->vp_hg << CS35L33_VP_HG_SHIFT); 742 + regmap_update_bits(priv->regmap, CS35L33_LDO_DEL, 743 + CS35L33_VP_HG_RATE_MASK, 744 + hg_config->vp_hg_rate << CS35L33_VP_HG_RATE_SHIFT); 745 + regmap_update_bits(priv->regmap, CS35L33_LDO_DEL, 746 + CS35L33_VP_HG_VA_MASK, 747 + hg_config->vp_hg_va << CS35L33_VP_HG_VA_SHIFT); 748 + regmap_update_bits(priv->regmap, CS35L33_HG_EN, 749 + CS35L33_CLASS_HG_EN_MASK, CS35L33_CLASS_HG_EN_MASK); 750 + } 751 + return 0; 752 + } 753 + 754 + static int cs35l33_set_bst_ipk(struct snd_soc_codec *codec, unsigned int bst) 755 + { 756 + struct cs35l33_private *cs35l33 = snd_soc_codec_get_drvdata(codec); 757 + int ret = 0, steps = 0; 758 + 759 + /* Boost current in uA */ 760 + if (bst > 3600000 || bst < 1850000) { 761 + dev_err(codec->dev, "Invalid boost current %d\n", bst); 762 + ret = -EINVAL; 763 + goto err; 764 + } 765 + 766 + if (bst % 15625) { 767 + dev_err(codec->dev, "Current not a multiple of 15625uA (%d)\n", 768 + bst); 769 + ret = -EINVAL; 770 + goto err; 771 + } 772 + 773 + while (bst > 1850000) { 774 + bst -= 15625; 775 + steps++; 776 + } 777 + 778 + regmap_write(cs35l33->regmap, CS35L33_BST_PEAK_CTL, 779 + steps+0x70); 780 + 781 + err: 782 + return ret; 783 + } 784 + 785 + static int cs35l33_probe(struct snd_soc_codec *codec) 786 + { 787 + struct cs35l33_private *cs35l33 = snd_soc_codec_get_drvdata(codec); 788 + 789 + cs35l33->codec = codec; 790 + pm_runtime_get_sync(codec->dev); 791 + 792 + regmap_update_bits(cs35l33->regmap, CS35L33_PROTECT_CTL, 793 + CS35L33_ALIVE_WD_DIS, 0x8); 794 + regmap_update_bits(cs35l33->regmap, CS35L33_BST_CTL2, 795 + CS35L33_ALIVE_WD_DIS2, 796 + CS35L33_ALIVE_WD_DIS2); 797 + 798 + /* Set Platform Data */ 799 + regmap_update_bits(cs35l33->regmap, CS35L33_BST_CTL1, 800 + CS35L33_BST_CTL_MASK, cs35l33->pdata.boost_ctl); 801 + regmap_update_bits(cs35l33->regmap, CS35L33_CLASSD_CTL, 802 + CS35L33_AMP_DRV_SEL_MASK, 803 + cs35l33->pdata.amp_drv_sel << CS35L33_AMP_DRV_SEL_SHIFT); 804 + 805 + if (cs35l33->pdata.boost_ipk) 806 + cs35l33_set_bst_ipk(codec, cs35l33->pdata.boost_ipk); 807 + 808 + if (cs35l33->enable_soft_ramp) { 809 + snd_soc_update_bits(codec, CS35L33_DAC_CTL, 810 + CS35L33_DIGSFT, CS35L33_DIGSFT); 811 + snd_soc_update_bits(codec, CS35L33_DAC_CTL, 812 + CS35L33_DSR_RATE, cs35l33->pdata.ramp_rate); 813 + } else { 814 + snd_soc_update_bits(codec, CS35L33_DAC_CTL, 815 + CS35L33_DIGSFT, 0); 816 + } 817 + 818 + /* update IMON scaling rate if different from default of 0x8 */ 819 + if (cs35l33->pdata.imon_adc_scale != 0x8) 820 + snd_soc_update_bits(codec, CS35L33_ADC_CTL, 821 + CS35L33_IMON_SCALE, cs35l33->pdata.imon_adc_scale); 822 + 823 + cs35l33_set_hg_data(codec, &(cs35l33->pdata)); 824 + 825 + /* 826 + * unmask important interrupts that causes the chip to enter 827 + * speaker safe mode and hence deserves user attention 828 + */ 829 + regmap_update_bits(cs35l33->regmap, CS35L33_INT_MASK_1, 830 + CS35L33_M_OTE | CS35L33_M_OTW | CS35L33_M_AMP_SHORT | 831 + CS35L33_M_CAL_ERR, 0); 832 + 833 + pm_runtime_put_sync(codec->dev); 834 + 835 + return 0; 836 + } 837 + 838 + static struct snd_soc_codec_driver soc_codec_dev_cs35l33 = { 839 + .probe = cs35l33_probe, 840 + 841 + .set_bias_level = cs35l33_set_bias_level, 842 + .set_sysclk = cs35l33_codec_set_sysclk, 843 + 844 + .dapm_widgets = cs35l33_dapm_widgets, 845 + .num_dapm_widgets = ARRAY_SIZE(cs35l33_dapm_widgets), 846 + .dapm_routes = cs35l33_audio_map, 847 + .num_dapm_routes = ARRAY_SIZE(cs35l33_audio_map), 848 + .controls = cs35l33_snd_controls, 849 + .num_controls = ARRAY_SIZE(cs35l33_snd_controls), 850 + 851 + .idle_bias_off = true, 852 + }; 853 + 854 + static const struct regmap_config cs35l33_regmap = { 855 + .reg_bits = 8, 856 + .val_bits = 8, 857 + 858 + .max_register = CS35L33_MAX_REGISTER, 859 + .reg_defaults = cs35l33_reg, 860 + .num_reg_defaults = ARRAY_SIZE(cs35l33_reg), 861 + .volatile_reg = cs35l33_volatile_register, 862 + .readable_reg = cs35l33_readable_register, 863 + .writeable_reg = cs35l33_writeable_register, 864 + .cache_type = REGCACHE_RBTREE, 865 + .use_single_rw = true, 866 + }; 867 + 868 + static int cs35l33_runtime_resume(struct device *dev) 869 + { 870 + struct cs35l33_private *cs35l33 = dev_get_drvdata(dev); 871 + int ret; 872 + 873 + dev_dbg(dev, "%s\n", __func__); 874 + 875 + if (cs35l33->reset_gpio) 876 + gpiod_set_value_cansleep(cs35l33->reset_gpio, 0); 877 + 878 + ret = regulator_bulk_enable(cs35l33->num_core_supplies, 879 + cs35l33->core_supplies); 880 + if (ret != 0) { 881 + dev_err(dev, "Failed to enable core supplies: %d\n", ret); 882 + return ret; 883 + } 884 + 885 + regcache_cache_only(cs35l33->regmap, false); 886 + 887 + if (cs35l33->reset_gpio) 888 + gpiod_set_value_cansleep(cs35l33->reset_gpio, 1); 889 + 890 + msleep(CS35L33_BOOT_DELAY); 891 + 892 + ret = regcache_sync(cs35l33->regmap); 893 + if (ret != 0) { 894 + dev_err(dev, "Failed to restore register cache\n"); 895 + goto err; 896 + } 897 + 898 + return 0; 899 + 900 + err: 901 + regcache_cache_only(cs35l33->regmap, true); 902 + regulator_bulk_disable(cs35l33->num_core_supplies, 903 + cs35l33->core_supplies); 904 + 905 + return ret; 906 + } 907 + 908 + static int cs35l33_runtime_suspend(struct device *dev) 909 + { 910 + struct cs35l33_private *cs35l33 = dev_get_drvdata(dev); 911 + 912 + dev_dbg(dev, "%s\n", __func__); 913 + 914 + /* redo the calibration in next power up */ 915 + cs35l33->amp_cal = false; 916 + 917 + regcache_cache_only(cs35l33->regmap, true); 918 + regcache_mark_dirty(cs35l33->regmap); 919 + regulator_bulk_disable(cs35l33->num_core_supplies, 920 + cs35l33->core_supplies); 921 + 922 + return 0; 923 + } 924 + 925 + static const struct dev_pm_ops cs35l33_pm_ops = { 926 + SET_RUNTIME_PM_OPS(cs35l33_runtime_suspend, 927 + cs35l33_runtime_resume, 928 + NULL) 929 + }; 930 + 931 + static int cs35l33_get_hg_data(const struct device_node *np, 932 + struct cs35l33_pdata *pdata) 933 + { 934 + struct device_node *hg; 935 + struct cs35l33_hg *hg_config = &pdata->hg_config; 936 + u32 val32; 937 + 938 + hg = of_get_child_by_name(np, "cirrus,hg-algo"); 939 + hg_config->enable_hg_algo = hg ? true : false; 940 + 941 + if (hg_config->enable_hg_algo) { 942 + if (of_property_read_u32(hg, "cirrus,mem-depth", &val32) >= 0) 943 + hg_config->mem_depth = val32; 944 + if (of_property_read_u32(hg, "cirrus,release-rate", 945 + &val32) >= 0) 946 + hg_config->release_rate = val32; 947 + if (of_property_read_u32(hg, "cirrus,ldo-thld", &val32) >= 0) 948 + hg_config->ldo_thld = val32; 949 + if (of_property_read_u32(hg, "cirrus,ldo-path-disable", 950 + &val32) >= 0) 951 + hg_config->ldo_path_disable = val32; 952 + if (of_property_read_u32(hg, "cirrus,ldo-entry-delay", 953 + &val32) >= 0) 954 + hg_config->ldo_entry_delay = val32; 955 + 956 + hg_config->vp_hg_auto = of_property_read_bool(hg, 957 + "cirrus,vp-hg-auto"); 958 + 959 + if (of_property_read_u32(hg, "cirrus,vp-hg", &val32) >= 0) 960 + hg_config->vp_hg = val32; 961 + if (of_property_read_u32(hg, "cirrus,vp-hg-rate", &val32) >= 0) 962 + hg_config->vp_hg_rate = val32; 963 + if (of_property_read_u32(hg, "cirrus,vp-hg-va", &val32) >= 0) 964 + hg_config->vp_hg_va = val32; 965 + } 966 + 967 + of_node_put(hg); 968 + 969 + return 0; 970 + } 971 + 972 + static irqreturn_t cs35l33_irq_thread(int irq, void *data) 973 + { 974 + struct cs35l33_private *cs35l33 = data; 975 + struct snd_soc_codec *codec = cs35l33->codec; 976 + unsigned int sticky_val1, sticky_val2, current_val, mask1, mask2; 977 + 978 + regmap_read(cs35l33->regmap, CS35L33_INT_STATUS_2, 979 + &sticky_val2); 980 + regmap_read(cs35l33->regmap, CS35L33_INT_STATUS_1, 981 + &sticky_val1); 982 + regmap_read(cs35l33->regmap, CS35L33_INT_MASK_2, &mask2); 983 + regmap_read(cs35l33->regmap, CS35L33_INT_MASK_1, &mask1); 984 + 985 + /* Check to see if the unmasked bits are active, 986 + * if not then exit. 987 + */ 988 + if (!(sticky_val1 & ~mask1) && !(sticky_val2 & ~mask2)) 989 + return IRQ_NONE; 990 + 991 + regmap_read(cs35l33->regmap, CS35L33_INT_STATUS_1, 992 + &current_val); 993 + 994 + /* handle the interrupts */ 995 + 996 + if (sticky_val1 & CS35L33_AMP_SHORT) { 997 + dev_crit(codec->dev, "Amp short error\n"); 998 + if (!(current_val & CS35L33_AMP_SHORT)) { 999 + dev_dbg(codec->dev, 1000 + "Amp short error release\n"); 1001 + regmap_update_bits(cs35l33->regmap, 1002 + CS35L33_AMP_CTL, 1003 + CS35L33_AMP_SHORT_RLS, 0); 1004 + regmap_update_bits(cs35l33->regmap, 1005 + CS35L33_AMP_CTL, 1006 + CS35L33_AMP_SHORT_RLS, 1007 + CS35L33_AMP_SHORT_RLS); 1008 + regmap_update_bits(cs35l33->regmap, 1009 + CS35L33_AMP_CTL, CS35L33_AMP_SHORT_RLS, 1010 + 0); 1011 + } 1012 + } 1013 + 1014 + if (sticky_val1 & CS35L33_CAL_ERR) { 1015 + dev_err(codec->dev, "Cal error\n"); 1016 + 1017 + /* redo the calibration in next power up */ 1018 + cs35l33->amp_cal = false; 1019 + 1020 + if (!(current_val & CS35L33_CAL_ERR)) { 1021 + dev_dbg(codec->dev, "Cal error release\n"); 1022 + regmap_update_bits(cs35l33->regmap, 1023 + CS35L33_AMP_CTL, CS35L33_CAL_ERR_RLS, 1024 + 0); 1025 + regmap_update_bits(cs35l33->regmap, 1026 + CS35L33_AMP_CTL, CS35L33_CAL_ERR_RLS, 1027 + CS35L33_CAL_ERR_RLS); 1028 + regmap_update_bits(cs35l33->regmap, 1029 + CS35L33_AMP_CTL, CS35L33_CAL_ERR_RLS, 1030 + 0); 1031 + } 1032 + } 1033 + 1034 + if (sticky_val1 & CS35L33_OTE) { 1035 + dev_crit(codec->dev, "Over temperature error\n"); 1036 + if (!(current_val & CS35L33_OTE)) { 1037 + dev_dbg(codec->dev, 1038 + "Over temperature error release\n"); 1039 + regmap_update_bits(cs35l33->regmap, 1040 + CS35L33_AMP_CTL, CS35L33_OTE_RLS, 0); 1041 + regmap_update_bits(cs35l33->regmap, 1042 + CS35L33_AMP_CTL, CS35L33_OTE_RLS, 1043 + CS35L33_OTE_RLS); 1044 + regmap_update_bits(cs35l33->regmap, 1045 + CS35L33_AMP_CTL, CS35L33_OTE_RLS, 0); 1046 + } 1047 + } 1048 + 1049 + if (sticky_val1 & CS35L33_OTW) { 1050 + dev_err(codec->dev, "Over temperature warning\n"); 1051 + if (!(current_val & CS35L33_OTW)) { 1052 + dev_dbg(codec->dev, 1053 + "Over temperature warning release\n"); 1054 + regmap_update_bits(cs35l33->regmap, 1055 + CS35L33_AMP_CTL, CS35L33_OTW_RLS, 0); 1056 + regmap_update_bits(cs35l33->regmap, 1057 + CS35L33_AMP_CTL, CS35L33_OTW_RLS, 1058 + CS35L33_OTW_RLS); 1059 + regmap_update_bits(cs35l33->regmap, 1060 + CS35L33_AMP_CTL, CS35L33_OTW_RLS, 0); 1061 + } 1062 + } 1063 + if (CS35L33_ALIVE_ERR & sticky_val1) 1064 + dev_err(codec->dev, "ERROR: ADSPCLK Interrupt\n"); 1065 + 1066 + if (CS35L33_MCLK_ERR & sticky_val1) 1067 + dev_err(codec->dev, "ERROR: MCLK Interrupt\n"); 1068 + 1069 + if (CS35L33_VMON_OVFL & sticky_val2) 1070 + dev_err(codec->dev, 1071 + "ERROR: VMON Overflow Interrupt\n"); 1072 + 1073 + if (CS35L33_IMON_OVFL & sticky_val2) 1074 + dev_err(codec->dev, 1075 + "ERROR: IMON Overflow Interrupt\n"); 1076 + 1077 + if (CS35L33_VPMON_OVFL & sticky_val2) 1078 + dev_err(codec->dev, 1079 + "ERROR: VPMON Overflow Interrupt\n"); 1080 + 1081 + return IRQ_HANDLED; 1082 + } 1083 + 1084 + static const char * const cs35l33_core_supplies[] = { 1085 + "VA", 1086 + "VP", 1087 + }; 1088 + 1089 + static int cs35l33_of_get_pdata(struct device *dev, 1090 + struct cs35l33_private *cs35l33) 1091 + { 1092 + struct device_node *np = dev->of_node; 1093 + struct cs35l33_pdata *pdata = &cs35l33->pdata; 1094 + u32 val32; 1095 + 1096 + if (!np) 1097 + return 0; 1098 + 1099 + if (of_property_read_u32(np, "cirrus,boost-ctl", &val32) >= 0) { 1100 + pdata->boost_ctl = val32; 1101 + pdata->amp_drv_sel = 1; 1102 + } 1103 + 1104 + if (of_property_read_u32(np, "cirrus,ramp-rate", &val32) >= 0) { 1105 + pdata->ramp_rate = val32; 1106 + cs35l33->enable_soft_ramp = true; 1107 + } 1108 + 1109 + if (of_property_read_u32(np, "cirrus,boost-ipk", &val32) >= 0) 1110 + pdata->boost_ipk = val32; 1111 + 1112 + if (of_property_read_u32(np, "cirrus,imon-adc-scale", &val32) >= 0) { 1113 + if ((val32 == 0x0) || (val32 == 0x7) || (val32 == 0x6)) 1114 + pdata->imon_adc_scale = val32; 1115 + else 1116 + /* use default value */ 1117 + pdata->imon_adc_scale = 0x8; 1118 + } else { 1119 + /* use default value */ 1120 + pdata->imon_adc_scale = 0x8; 1121 + } 1122 + 1123 + cs35l33_get_hg_data(np, pdata); 1124 + 1125 + return 0; 1126 + } 1127 + 1128 + static int cs35l33_i2c_probe(struct i2c_client *i2c_client, 1129 + const struct i2c_device_id *id) 1130 + { 1131 + struct cs35l33_private *cs35l33; 1132 + struct cs35l33_pdata *pdata = dev_get_platdata(&i2c_client->dev); 1133 + int ret, devid, i; 1134 + unsigned int reg; 1135 + 1136 + cs35l33 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs35l33_private), 1137 + GFP_KERNEL); 1138 + if (!cs35l33) 1139 + return -ENOMEM; 1140 + 1141 + i2c_set_clientdata(i2c_client, cs35l33); 1142 + cs35l33->regmap = devm_regmap_init_i2c(i2c_client, &cs35l33_regmap); 1143 + if (IS_ERR(cs35l33->regmap)) { 1144 + ret = PTR_ERR(cs35l33->regmap); 1145 + dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); 1146 + return ret; 1147 + } 1148 + 1149 + regcache_cache_only(cs35l33->regmap, true); 1150 + 1151 + for (i = 0; i < ARRAY_SIZE(cs35l33_core_supplies); i++) 1152 + cs35l33->core_supplies[i].supply 1153 + = cs35l33_core_supplies[i]; 1154 + cs35l33->num_core_supplies = ARRAY_SIZE(cs35l33_core_supplies); 1155 + 1156 + ret = devm_regulator_bulk_get(&i2c_client->dev, 1157 + cs35l33->num_core_supplies, 1158 + cs35l33->core_supplies); 1159 + if (ret != 0) { 1160 + dev_err(&i2c_client->dev, 1161 + "Failed to request core supplies: %d\n", 1162 + ret); 1163 + return ret; 1164 + } 1165 + 1166 + if (pdata) { 1167 + cs35l33->pdata = *pdata; 1168 + } else { 1169 + cs35l33_of_get_pdata(&i2c_client->dev, cs35l33); 1170 + pdata = &cs35l33->pdata; 1171 + } 1172 + 1173 + ret = devm_request_threaded_irq(&i2c_client->dev, i2c_client->irq, NULL, 1174 + cs35l33_irq_thread, IRQF_ONESHOT | IRQF_TRIGGER_LOW, 1175 + "cs35l33", cs35l33); 1176 + if (ret != 0) 1177 + dev_warn(&i2c_client->dev, "Failed to request IRQ: %d\n", ret); 1178 + 1179 + /* We could issue !RST or skip it based on AMP topology */ 1180 + cs35l33->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, 1181 + "reset-gpios", GPIOD_OUT_HIGH); 1182 + 1183 + if (PTR_ERR(cs35l33->reset_gpio) == -ENOENT) { 1184 + dev_warn(&i2c_client->dev, 1185 + "%s WARNING: No reset gpio assigned\n", __func__); 1186 + } else if (IS_ERR(cs35l33->reset_gpio)) { 1187 + dev_err(&i2c_client->dev, "%s ERROR: Can't get reset GPIO\n", 1188 + __func__); 1189 + return PTR_ERR(cs35l33->reset_gpio); 1190 + } 1191 + 1192 + ret = regulator_bulk_enable(cs35l33->num_core_supplies, 1193 + cs35l33->core_supplies); 1194 + if (ret != 0) { 1195 + dev_err(&i2c_client->dev, 1196 + "Failed to enable core supplies: %d\n", 1197 + ret); 1198 + goto err_irq; 1199 + } 1200 + 1201 + if (cs35l33->reset_gpio) 1202 + gpiod_set_value_cansleep(cs35l33->reset_gpio, 1); 1203 + 1204 + msleep(CS35L33_BOOT_DELAY); 1205 + regcache_cache_only(cs35l33->regmap, false); 1206 + 1207 + /* initialize codec */ 1208 + ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_AB, &reg); 1209 + devid = (reg & 0xFF) << 12; 1210 + ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_CD, &reg); 1211 + devid |= (reg & 0xFF) << 4; 1212 + ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_E, &reg); 1213 + devid |= (reg & 0xF0) >> 4; 1214 + 1215 + if (devid != CS35L33_CHIP_ID) { 1216 + dev_err(&i2c_client->dev, 1217 + "CS35L33 Device ID (%X). Expected ID %X\n", 1218 + devid, CS35L33_CHIP_ID); 1219 + goto err_enable; 1220 + } 1221 + 1222 + ret = regmap_read(cs35l33->regmap, CS35L33_REV_ID, &reg); 1223 + if (ret < 0) { 1224 + dev_err(&i2c_client->dev, "Get Revision ID failed\n"); 1225 + goto err_enable; 1226 + } 1227 + 1228 + dev_info(&i2c_client->dev, 1229 + "Cirrus Logic CS35L33, Revision: %02X\n", ret & 0xFF); 1230 + 1231 + ret = regmap_register_patch(cs35l33->regmap, 1232 + cs35l33_patch, ARRAY_SIZE(cs35l33_patch)); 1233 + if (ret < 0) { 1234 + dev_err(&i2c_client->dev, 1235 + "Error in applying regmap patch: %d\n", ret); 1236 + goto err_enable; 1237 + } 1238 + 1239 + /* disable mclk and tdm */ 1240 + regmap_update_bits(cs35l33->regmap, CS35L33_CLK_CTL, 1241 + CS35L33_MCLKDIS | CS35L33_SDOUT_3ST_TDM, 1242 + CS35L33_MCLKDIS | CS35L33_SDOUT_3ST_TDM); 1243 + 1244 + pm_runtime_set_autosuspend_delay(&i2c_client->dev, 100); 1245 + pm_runtime_use_autosuspend(&i2c_client->dev); 1246 + pm_runtime_set_active(&i2c_client->dev); 1247 + pm_runtime_enable(&i2c_client->dev); 1248 + 1249 + ret = snd_soc_register_codec(&i2c_client->dev, 1250 + &soc_codec_dev_cs35l33, &cs35l33_dai, 1); 1251 + if (ret < 0) { 1252 + dev_err(&i2c_client->dev, "%s: Register codec failed\n", 1253 + __func__); 1254 + goto err_irq; 1255 + } 1256 + 1257 + return 0; 1258 + 1259 + err_enable: 1260 + regulator_bulk_disable(cs35l33->num_core_supplies, 1261 + cs35l33->core_supplies); 1262 + err_irq: 1263 + free_irq(i2c_client->irq, cs35l33); 1264 + 1265 + return ret; 1266 + } 1267 + 1268 + static int cs35l33_i2c_remove(struct i2c_client *client) 1269 + { 1270 + struct cs35l33_private *cs35l33 = i2c_get_clientdata(client); 1271 + 1272 + snd_soc_unregister_codec(&client->dev); 1273 + 1274 + if (cs35l33->reset_gpio) 1275 + gpiod_set_value_cansleep(cs35l33->reset_gpio, 0); 1276 + 1277 + pm_runtime_disable(&client->dev); 1278 + regulator_bulk_disable(cs35l33->num_core_supplies, 1279 + cs35l33->core_supplies); 1280 + free_irq(client->irq, cs35l33); 1281 + 1282 + return 0; 1283 + } 1284 + 1285 + static const struct of_device_id cs35l33_of_match[] = { 1286 + { .compatible = "cirrus,cs35l33", }, 1287 + {}, 1288 + }; 1289 + MODULE_DEVICE_TABLE(of, cs35l33_of_match); 1290 + 1291 + static const struct i2c_device_id cs35l33_id[] = { 1292 + {"cs35l33", 0}, 1293 + {} 1294 + }; 1295 + 1296 + MODULE_DEVICE_TABLE(i2c, cs35l33_id); 1297 + 1298 + static struct i2c_driver cs35l33_i2c_driver = { 1299 + .driver = { 1300 + .name = "cs35l33", 1301 + .owner = THIS_MODULE, 1302 + .pm = &cs35l33_pm_ops, 1303 + .of_match_table = cs35l33_of_match, 1304 + 1305 + }, 1306 + .id_table = cs35l33_id, 1307 + .probe = cs35l33_i2c_probe, 1308 + .remove = cs35l33_i2c_remove, 1309 + 1310 + }; 1311 + module_i2c_driver(cs35l33_i2c_driver); 1312 + 1313 + MODULE_DESCRIPTION("ASoC CS35L33 driver"); 1314 + MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paul.handrigan@cirrus.com>"); 1315 + MODULE_LICENSE("GPL");
+221
sound/soc/codecs/cs35l33.h
··· 1 + /* 2 + * cs35l33.h -- CS35L33 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 __CS35L33_H__ 15 + #define __CS35L33_H__ 16 + 17 + #define CS35L33_CHIP_ID 0x00035A33 18 + #define CS35L33_DEVID_AB 0x01 /* Device ID A & B [RO] */ 19 + #define CS35L33_DEVID_CD 0x02 /* Device ID C & D [RO] */ 20 + #define CS35L33_DEVID_E 0x03 /* Device ID E [RO] */ 21 + #define CS35L33_FAB_ID 0x04 /* Fab ID [RO] */ 22 + #define CS35L33_REV_ID 0x05 /* Revision ID [RO] */ 23 + #define CS35L33_PWRCTL1 0x06 /* Power Ctl 1 */ 24 + #define CS35L33_PWRCTL2 0x07 /* Power Ctl 2 */ 25 + #define CS35L33_CLK_CTL 0x08 /* Clock Ctl */ 26 + #define CS35L33_BST_PEAK_CTL 0x09 /* Max Current for Boost */ 27 + #define CS35L33_PROTECT_CTL 0x0A /* Amp Protection Parameters */ 28 + #define CS35L33_BST_CTL1 0x0B /* Boost Converter CTL1 */ 29 + #define CS35L33_BST_CTL2 0x0C /* Boost Converter CTL2 */ 30 + #define CS35L33_ADSP_CTL 0x0D /* Serial Port Control */ 31 + #define CS35L33_ADC_CTL 0x0E /* ADC Control */ 32 + #define CS35L33_DAC_CTL 0x0F /* DAC Control */ 33 + #define CS35L33_DIG_VOL_CTL 0x10 /* Digital Volume CTL */ 34 + #define CS35L33_CLASSD_CTL 0x11 /* Class D Amp CTL */ 35 + #define CS35L33_AMP_CTL 0x12 /* Amp Gain/Protecton Release CTL */ 36 + #define CS35L33_INT_MASK_1 0x13 /* Interrupt Mask 1 */ 37 + #define CS35L33_INT_MASK_2 0x14 /* Interrupt Mask 2 */ 38 + #define CS35L33_INT_STATUS_1 0x15 /* Interrupt Status 1 [RO] */ 39 + #define CS35L33_INT_STATUS_2 0x16 /* Interrupt Status 2 [RO] */ 40 + #define CS35L33_DIAG_LOCK 0x17 /* Diagnostic Mode Register Lock */ 41 + #define CS35L33_DIAG_CTRL_1 0x18 /* Diagnostic Mode Register Control */ 42 + #define CS35L33_DIAG_CTRL_2 0x19 /* Diagnostic Mode Register Control 2 */ 43 + #define CS35L33_HG_MEMLDO_CTL 0x23 /* H/G Memory/LDO CTL */ 44 + #define CS35L33_HG_REL_RATE 0x24 /* H/G Release Rate */ 45 + #define CS35L33_LDO_DEL 0x25 /* LDO Entry Delay/VPhg Control 1 */ 46 + #define CS35L33_HG_HEAD 0x29 /* H/G Headroom */ 47 + #define CS35L33_HG_EN 0x2A /* H/G Enable/VPhg CNT2 */ 48 + #define CS35L33_TX_VMON 0x2D /* TDM TX Control 1 (VMON) */ 49 + #define CS35L33_TX_IMON 0x2E /* TDM TX Control 2 (IMON) */ 50 + #define CS35L33_TX_VPMON 0x2F /* TDM TX Control 3 (VPMON) */ 51 + #define CS35L33_TX_VBSTMON 0x30 /* TDM TX Control 4 (VBSTMON) */ 52 + #define CS35L33_TX_FLAG 0x31 /* TDM TX Control 5 (FLAG) */ 53 + #define CS35L33_TX_EN1 0x32 /* TDM TX Enable 1 */ 54 + #define CS35L33_TX_EN2 0x33 /* TDM TX Enable 2 */ 55 + #define CS35L33_TX_EN3 0x34 /* TDM TX Enable 3 */ 56 + #define CS35L33_TX_EN4 0x35 /* TDM TX Enable 4 */ 57 + #define CS35L33_RX_AUD 0x36 /* TDM RX Control 1 */ 58 + #define CS35L33_RX_SPLY 0x37 /* TDM RX Control 2 */ 59 + #define CS35L33_RX_ALIVE 0x38 /* TDM RX Control 3 */ 60 + #define CS35L33_BST_CTL4 0x39 /* Boost Converter Control 4 */ 61 + #define CS35L33_HG_STATUS 0x3F /* H/G Status */ 62 + #define CS35L33_MAX_REGISTER 0x59 63 + 64 + #define CS35L33_MCLK_5644 5644800 65 + #define CS35L33_MCLK_6144 6144000 66 + #define CS35L33_MCLK_6 6000000 67 + #define CS35L33_MCLK_11289 11289600 68 + #define CS35L33_MCLK_12 12000000 69 + #define CS35L33_MCLK_12288 12288000 70 + 71 + /* CS35L33_PWRCTL1 */ 72 + #define CS35L33_PDN_AMP (1 << 7) 73 + #define CS35L33_PDN_BST (1 << 2) 74 + #define CS35L33_PDN_ALL 1 75 + 76 + /* CS35L33_PWRCTL2 */ 77 + #define CS35L33_PDN_VMON_SHIFT 7 78 + #define CS35L33_PDN_VMON (1 << CS35L33_PDN_VMON_SHIFT) 79 + #define CS35L33_PDN_IMON_SHIFT 6 80 + #define CS35L33_PDN_IMON (1 << CS35L33_PDN_IMON_SHIFT) 81 + #define CS35L33_PDN_VPMON_SHIFT 5 82 + #define CS35L33_PDN_VPMON (1 << CS35L33_PDN_VPMON_SHIFT) 83 + #define CS35L33_PDN_VBSTMON_SHIFT 4 84 + #define CS35L33_PDN_VBSTMON (1 << CS35L33_PDN_VBSTMON_SHIFT) 85 + #define CS35L33_SDOUT_3ST_I2S_SHIFT 3 86 + #define CS35L33_SDOUT_3ST_I2S (1 << CS35L33_SDOUT_3ST_I2S_SHIFT) 87 + #define CS35L33_PDN_SDIN_SHIFT 2 88 + #define CS35L33_PDN_SDIN (1 << CS35L33_PDN_SDIN_SHIFT) 89 + #define CS35L33_PDN_TDM_SHIFT 1 90 + #define CS35L33_PDN_TDM (1 << CS35L33_PDN_TDM_SHIFT) 91 + 92 + /* CS35L33_CLK_CTL */ 93 + #define CS35L33_MCLKDIS (1 << 7) 94 + #define CS35L33_MCLKDIV2 (1 << 6) 95 + #define CS35L33_SDOUT_3ST_TDM (1 << 5) 96 + #define CS35L33_INT_FS_RATE (1 << 4) 97 + #define CS35L33_ADSP_FS 0xF 98 + 99 + /* CS35L33_PROTECT_CTL */ 100 + #define CS35L33_ALIVE_WD_DIS (3 << 2) 101 + 102 + /* CS35L33_BST_CTL1 */ 103 + #define CS35L33_BST_CTL_SRC (1 << 6) 104 + #define CS35L33_BST_CTL_SHIFT (1 << 5) 105 + #define CS35L33_BST_CTL_MASK 0x3F 106 + 107 + /* CS35L33_BST_CTL2 */ 108 + #define CS35L33_TDM_WD_SEL (1 << 4) 109 + #define CS35L33_ALIVE_WD_DIS2 (1 << 3) 110 + #define CS35L33_VBST_SR_STEP 0x3 111 + 112 + /* CS35L33_ADSP_CTL */ 113 + #define CS35L33_ADSP_DRIVE (1 << 7) 114 + #define CS35L33_MS_MASK (1 << 6) 115 + #define CS35L33_SDIN_LOC (3 << 4) 116 + #define CS35L33_ALIVE_RATE 0x3 117 + 118 + /* CS35L33_ADC_CTL */ 119 + #define CS35L33_INV_VMON (1 << 7) 120 + #define CS35L33_INV_IMON (1 << 6) 121 + #define CS35L33_ADC_NOTCH_DIS (1 << 5) 122 + #define CS35L33_IMON_SCALE 0xF 123 + 124 + /* CS35L33_DAC_CTL */ 125 + #define CS35L33_INV_DAC (1 << 7) 126 + #define CS35L33_DAC_NOTCH_DIS (1 << 5) 127 + #define CS35L33_DIGSFT (1 << 4) 128 + #define CS35L33_DSR_RATE 0xF 129 + 130 + /* CS35L33_CLASSD_CTL */ 131 + #define CS35L33_AMP_SD (1 << 6) 132 + #define CS35L33_AMP_DRV_SEL_SRC (1 << 5) 133 + #define CS35L33_AMP_DRV_SEL_MASK 0x10 134 + #define CS35L33_AMP_DRV_SEL_SHIFT 4 135 + #define CS35L33_AMP_CAL (1 << 3) 136 + #define CS35L33_GAIN_CHG_ZC_MASK 0x04 137 + #define CS35L33_GAIN_CHG_ZC_SHIFT 2 138 + #define CS35L33_CLASS_D_CTL_MASK 0x3F 139 + 140 + /* CS35L33_AMP_CTL */ 141 + #define CS35L33_AMP_GAIN 0xF0 142 + #define CS35L33_CAL_ERR_RLS (1 << 3) 143 + #define CS35L33_AMP_SHORT_RLS (1 << 2) 144 + #define CS35L33_OTW_RLS (1 << 1) 145 + #define CS35L33_OTE_RLS 1 146 + 147 + /* CS35L33_INT_MASK_1 */ 148 + #define CS35L33_M_CAL_ERR_SHIFT 6 149 + #define CS35L33_M_CAL_ERR (1 << CS35L33_M_CAL_ERR_SHIFT) 150 + #define CS35L33_M_ALIVE_ERR_SHIFT 5 151 + #define CS35L33_M_ALIVE_ERR (1 << CS35L33_M_ALIVE_ERR_SHIFT) 152 + #define CS35L33_M_AMP_SHORT_SHIFT 2 153 + #define CS35L33_M_AMP_SHORT (1 << CS35L33_M_AMP_SHORT_SHIFT) 154 + #define CS35L33_M_OTW_SHIFT 1 155 + #define CS35L33_M_OTW (1 << CS35L33_M_OTW_SHIFT) 156 + #define CS35L33_M_OTE_SHIFT 0 157 + #define CS35L33_M_OTE (1 << CS35L33_M_OTE_SHIFT) 158 + 159 + /* CS35L33_INT_STATUS_1 */ 160 + #define CS35L33_CAL_ERR (1 << 6) 161 + #define CS35L33_ALIVE_ERR (1 << 5) 162 + #define CS35L33_ADSPCLK_ERR (1 << 4) 163 + #define CS35L33_MCLK_ERR (1 << 3) 164 + #define CS35L33_AMP_SHORT (1 << 2) 165 + #define CS35L33_OTW (1 << 1) 166 + #define CS35L33_OTE (1 << 0) 167 + 168 + /* CS35L33_INT_STATUS_2 */ 169 + #define CS35L33_VMON_OVFL (1 << 7) 170 + #define CS35L33_IMON_OVFL (1 << 6) 171 + #define CS35L33_VPMON_OVFL (1 << 5) 172 + #define CS35L33_VBSTMON_OVFL (1 << 4) 173 + #define CS35L33_PDN_DONE 1 174 + 175 + /* CS35L33_BST_CTL4 */ 176 + #define CS35L33_BST_RGS 0x70 177 + #define CS35L33_BST_COEFF3 0xF 178 + 179 + /* CS35L33_HG_MEMLDO_CTL */ 180 + #define CS35L33_MEM_DEPTH_SHIFT 5 181 + #define CS35L33_MEM_DEPTH_MASK (0x3 << CS35L33_MEM_DEPTH_SHIFT) 182 + #define CS35L33_LDO_THLD_SHIFT 1 183 + #define CS35L33_LDO_THLD_MASK (0xF << CS35L33_LDO_THLD_SHIFT) 184 + #define CS35L33_LDO_DISABLE_SHIFT 0 185 + #define CS35L33_LDO_DISABLE_MASK (0x1 << CS35L33_LDO_DISABLE_SHIFT) 186 + 187 + /* CS35L33_LDO_DEL */ 188 + #define CS35L33_VP_HG_VA_SHIFT 5 189 + #define CS35L33_VP_HG_VA_MASK (0x7 << CS35L33_VP_HG_VA_SHIFT) 190 + #define CS35L33_LDO_ENTRY_DELAY_SHIFT 2 191 + #define CS35L33_LDO_ENTRY_DELAY_MASK (0x7 << CS35L33_LDO_ENTRY_DELAY_SHIFT) 192 + #define CS35L33_VP_HG_RATE_SHIFT 0 193 + #define CS35L33_VP_HG_RATE_MASK (0x3 << CS35L33_VP_HG_RATE_SHIFT) 194 + 195 + /* CS35L33_HG_HEAD */ 196 + #define CS35L33_HD_RM_SHIFT 0 197 + #define CS35L33_HD_RM_MASK (0x7F << CS35L33_HD_RM_SHIFT) 198 + 199 + /* CS35L33_HG_EN */ 200 + #define CS35L33_CLASS_HG_ENA_SHIFT 7 201 + #define CS35L33_CLASS_HG_EN_MASK (0x1 << CS35L33_CLASS_HG_ENA_SHIFT) 202 + #define CS35L33_VP_HG_AUTO_SHIFT 6 203 + #define CS35L33_VP_HG_AUTO_MASK (0x1 << 6) 204 + #define CS35L33_VP_HG_SHIFT 0 205 + #define CS35L33_VP_HG_MASK (0x1F << CS35L33_VP_HG_SHIFT) 206 + 207 + #define CS35L33_RATES (SNDRV_PCM_RATE_8000_48000) 208 + #define CS35L33_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 209 + SNDRV_PCM_FMTBIT_S24_LE) 210 + 211 + /* CS35L33_{RX,TX}_X */ 212 + #define CS35L33_X_STATE_SHIFT 7 213 + #define CS35L33_X_STATE (1 << CS35L33_X_STATE_SHIFT) 214 + #define CS35L33_X_LOC_SHIFT 0 215 + #define CS35L33_X_LOC (0x1F << CS35L33_X_LOC_SHIFT) 216 + 217 + /* CS35L33_RX_AUD */ 218 + #define CS35L33_AUDIN_RX_DEPTH_SHIFT 5 219 + #define CS35L33_AUDIN_RX_DEPTH (0x7 << CS35L33_AUDIN_RX_DEPTH_SHIFT) 220 + 221 + #endif