1663 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * cs35l35.c -- CS35L35 ALSA SoC audio driver4 *5 * Copyright 2017 Cirrus Logic, Inc.6 *7 * Author: Brian Austin <brian.austin@cirrus.com>8 */9 10#include <linux/module.h>11#include <linux/moduleparam.h>12#include <linux/kernel.h>13#include <linux/init.h>14#include <linux/delay.h>15#include <linux/i2c.h>16#include <linux/slab.h>17#include <linux/platform_device.h>18#include <linux/regulator/consumer.h>19#include <linux/gpio/consumer.h>20#include <linux/of.h>21#include <linux/regmap.h>22#include <sound/core.h>23#include <sound/pcm.h>24#include <sound/pcm_params.h>25#include <sound/soc.h>26#include <sound/soc-dapm.h>27#include <sound/initval.h>28#include <sound/tlv.h>29#include <sound/cs35l35.h>30#include <linux/completion.h>31 32#include "cs35l35.h"33#include "cirrus_legacy.h"34 35/*36 * Some fields take zero as a valid value so use a high bit flag that won't37 * get written to the device to mark those.38 */39#define CS35L35_VALID_PDATA 0x8000000040 41static const struct reg_default cs35l35_reg[] = {42 {CS35L35_PWRCTL1, 0x01},43 {CS35L35_PWRCTL2, 0x11},44 {CS35L35_PWRCTL3, 0x00},45 {CS35L35_CLK_CTL1, 0x04},46 {CS35L35_CLK_CTL2, 0x12},47 {CS35L35_CLK_CTL3, 0xCF},48 {CS35L35_SP_FMT_CTL1, 0x20},49 {CS35L35_SP_FMT_CTL2, 0x00},50 {CS35L35_SP_FMT_CTL3, 0x02},51 {CS35L35_MAG_COMP_CTL, 0x00},52 {CS35L35_AMP_INP_DRV_CTL, 0x01},53 {CS35L35_AMP_DIG_VOL_CTL, 0x12},54 {CS35L35_AMP_DIG_VOL, 0x00},55 {CS35L35_ADV_DIG_VOL, 0x00},56 {CS35L35_PROTECT_CTL, 0x06},57 {CS35L35_AMP_GAIN_AUD_CTL, 0x13},58 {CS35L35_AMP_GAIN_PDM_CTL, 0x00},59 {CS35L35_AMP_GAIN_ADV_CTL, 0x00},60 {CS35L35_GPI_CTL, 0x00},61 {CS35L35_BST_CVTR_V_CTL, 0x00},62 {CS35L35_BST_PEAK_I, 0x07},63 {CS35L35_BST_RAMP_CTL, 0x85},64 {CS35L35_BST_CONV_COEF_1, 0x24},65 {CS35L35_BST_CONV_COEF_2, 0x24},66 {CS35L35_BST_CONV_SLOPE_COMP, 0x4E},67 {CS35L35_BST_CONV_SW_FREQ, 0x04},68 {CS35L35_CLASS_H_CTL, 0x0B},69 {CS35L35_CLASS_H_HEADRM_CTL, 0x0B},70 {CS35L35_CLASS_H_RELEASE_RATE, 0x08},71 {CS35L35_CLASS_H_FET_DRIVE_CTL, 0x41},72 {CS35L35_CLASS_H_VP_CTL, 0xC5},73 {CS35L35_VPBR_CTL, 0x0A},74 {CS35L35_VPBR_VOL_CTL, 0x90},75 {CS35L35_VPBR_TIMING_CTL, 0x6A},76 {CS35L35_VPBR_MODE_VOL_CTL, 0x00},77 {CS35L35_SPKR_MON_CTL, 0xC0},78 {CS35L35_IMON_SCALE_CTL, 0x30},79 {CS35L35_AUDIN_RXLOC_CTL, 0x00},80 {CS35L35_ADVIN_RXLOC_CTL, 0x80},81 {CS35L35_VMON_TXLOC_CTL, 0x00},82 {CS35L35_IMON_TXLOC_CTL, 0x80},83 {CS35L35_VPMON_TXLOC_CTL, 0x04},84 {CS35L35_VBSTMON_TXLOC_CTL, 0x84},85 {CS35L35_VPBR_STATUS_TXLOC_CTL, 0x04},86 {CS35L35_ZERO_FILL_LOC_CTL, 0x00},87 {CS35L35_AUDIN_DEPTH_CTL, 0x0F},88 {CS35L35_SPKMON_DEPTH_CTL, 0x0F},89 {CS35L35_SUPMON_DEPTH_CTL, 0x0F},90 {CS35L35_ZEROFILL_DEPTH_CTL, 0x00},91 {CS35L35_MULT_DEV_SYNCH1, 0x02},92 {CS35L35_MULT_DEV_SYNCH2, 0x80},93 {CS35L35_PROT_RELEASE_CTL, 0x00},94 {CS35L35_DIAG_MODE_REG_LOCK, 0x00},95 {CS35L35_DIAG_MODE_CTL_1, 0x40},96 {CS35L35_DIAG_MODE_CTL_2, 0x00},97 {CS35L35_INT_MASK_1, 0xFF},98 {CS35L35_INT_MASK_2, 0xFF},99 {CS35L35_INT_MASK_3, 0xFF},100 {CS35L35_INT_MASK_4, 0xFF},101 102};103 104static bool cs35l35_volatile_register(struct device *dev, unsigned int reg)105{106 switch (reg) {107 case CS35L35_INT_STATUS_1:108 case CS35L35_INT_STATUS_2:109 case CS35L35_INT_STATUS_3:110 case CS35L35_INT_STATUS_4:111 case CS35L35_PLL_STATUS:112 case CS35L35_OTP_TRIM_STATUS:113 return true;114 default:115 return false;116 }117}118 119static bool cs35l35_readable_register(struct device *dev, unsigned int reg)120{121 switch (reg) {122 case CS35L35_DEVID_AB ... CS35L35_PWRCTL3:123 case CS35L35_CLK_CTL1 ... CS35L35_SP_FMT_CTL3:124 case CS35L35_MAG_COMP_CTL ... CS35L35_AMP_GAIN_AUD_CTL:125 case CS35L35_AMP_GAIN_PDM_CTL ... CS35L35_BST_PEAK_I:126 case CS35L35_BST_RAMP_CTL ... CS35L35_BST_CONV_SW_FREQ:127 case CS35L35_CLASS_H_CTL ... CS35L35_CLASS_H_VP_CTL:128 case CS35L35_CLASS_H_STATUS:129 case CS35L35_VPBR_CTL ... CS35L35_VPBR_MODE_VOL_CTL:130 case CS35L35_VPBR_ATTEN_STATUS:131 case CS35L35_SPKR_MON_CTL:132 case CS35L35_IMON_SCALE_CTL ... CS35L35_ZEROFILL_DEPTH_CTL:133 case CS35L35_MULT_DEV_SYNCH1 ... CS35L35_PROT_RELEASE_CTL:134 case CS35L35_DIAG_MODE_REG_LOCK ... CS35L35_DIAG_MODE_CTL_2:135 case CS35L35_INT_MASK_1 ... CS35L35_PLL_STATUS:136 case CS35L35_OTP_TRIM_STATUS:137 return true;138 default:139 return false;140 }141}142 143static bool cs35l35_precious_register(struct device *dev, unsigned int reg)144{145 switch (reg) {146 case CS35L35_INT_STATUS_1:147 case CS35L35_INT_STATUS_2:148 case CS35L35_INT_STATUS_3:149 case CS35L35_INT_STATUS_4:150 case CS35L35_PLL_STATUS:151 case CS35L35_OTP_TRIM_STATUS:152 return true;153 default:154 return false;155 }156}157 158static void cs35l35_reset(struct cs35l35_private *cs35l35)159{160 gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);161 usleep_range(2000, 2100);162 gpiod_set_value_cansleep(cs35l35->reset_gpio, 1);163 usleep_range(1000, 1100);164}165 166static int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35)167{168 int ret;169 170 if (cs35l35->pdata.ext_bst) {171 usleep_range(5000, 5500);172 return 0;173 }174 175 reinit_completion(&cs35l35->pdn_done);176 177 ret = wait_for_completion_timeout(&cs35l35->pdn_done,178 msecs_to_jiffies(100));179 if (ret == 0) {180 dev_err(cs35l35->dev, "PDN_DONE did not complete\n");181 return -ETIMEDOUT;182 }183 184 return 0;185}186 187static int cs35l35_sdin_event(struct snd_soc_dapm_widget *w,188 struct snd_kcontrol *kcontrol, int event)189{190 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);191 struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);192 int ret = 0;193 194 switch (event) {195 case SND_SOC_DAPM_PRE_PMU:196 regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,197 CS35L35_MCLK_DIS_MASK,198 0 << CS35L35_MCLK_DIS_SHIFT);199 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,200 CS35L35_DISCHG_FILT_MASK,201 0 << CS35L35_DISCHG_FILT_SHIFT);202 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,203 CS35L35_PDN_ALL_MASK, 0);204 break;205 case SND_SOC_DAPM_POST_PMD:206 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,207 CS35L35_DISCHG_FILT_MASK,208 1 << CS35L35_DISCHG_FILT_SHIFT);209 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,210 CS35L35_PDN_ALL_MASK, 1);211 212 /* Already muted, so disable volume ramp for faster shutdown */213 regmap_update_bits(cs35l35->regmap, CS35L35_AMP_DIG_VOL_CTL,214 CS35L35_AMP_DIGSFT_MASK, 0);215 216 ret = cs35l35_wait_for_pdn(cs35l35);217 218 regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,219 CS35L35_MCLK_DIS_MASK,220 1 << CS35L35_MCLK_DIS_SHIFT);221 222 regmap_update_bits(cs35l35->regmap, CS35L35_AMP_DIG_VOL_CTL,223 CS35L35_AMP_DIGSFT_MASK,224 1 << CS35L35_AMP_DIGSFT_SHIFT);225 break;226 default:227 dev_err(component->dev, "Invalid event = 0x%x\n", event);228 ret = -EINVAL;229 }230 return ret;231}232 233static int cs35l35_main_amp_event(struct snd_soc_dapm_widget *w,234 struct snd_kcontrol *kcontrol, int event)235{236 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);237 struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);238 unsigned int reg[4];239 int i;240 241 switch (event) {242 case SND_SOC_DAPM_PRE_PMU:243 if (cs35l35->pdata.bst_pdn_fet_on)244 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,245 CS35L35_PDN_BST_MASK,246 0 << CS35L35_PDN_BST_FETON_SHIFT);247 else248 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,249 CS35L35_PDN_BST_MASK,250 0 << CS35L35_PDN_BST_FETOFF_SHIFT);251 break;252 case SND_SOC_DAPM_POST_PMU:253 usleep_range(5000, 5100);254 /* If in PDM mode we must use VP for Voltage control */255 if (cs35l35->pdm_mode)256 regmap_update_bits(cs35l35->regmap,257 CS35L35_BST_CVTR_V_CTL,258 CS35L35_BST_CTL_MASK,259 0 << CS35L35_BST_CTL_SHIFT);260 261 regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,262 CS35L35_AMP_MUTE_MASK, 0);263 264 for (i = 0; i < 2; i++)265 regmap_bulk_read(cs35l35->regmap, CS35L35_INT_STATUS_1,266 ®, ARRAY_SIZE(reg));267 268 break;269 case SND_SOC_DAPM_PRE_PMD:270 regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,271 CS35L35_AMP_MUTE_MASK,272 1 << CS35L35_AMP_MUTE_SHIFT);273 if (cs35l35->pdata.bst_pdn_fet_on)274 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,275 CS35L35_PDN_BST_MASK,276 1 << CS35L35_PDN_BST_FETON_SHIFT);277 else278 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,279 CS35L35_PDN_BST_MASK,280 1 << CS35L35_PDN_BST_FETOFF_SHIFT);281 break;282 case SND_SOC_DAPM_POST_PMD:283 usleep_range(5000, 5100);284 /*285 * If PDM mode we should switch back to pdata value286 * for Voltage control when we go down287 */288 if (cs35l35->pdm_mode)289 regmap_update_bits(cs35l35->regmap,290 CS35L35_BST_CVTR_V_CTL,291 CS35L35_BST_CTL_MASK,292 cs35l35->pdata.bst_vctl293 << CS35L35_BST_CTL_SHIFT);294 295 break;296 default:297 dev_err(component->dev, "Invalid event = 0x%x\n", event);298 }299 return 0;300}301 302static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 0, 1, 1);303static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10200, 50, 0);304 305static const struct snd_kcontrol_new cs35l35_aud_controls[] = {306 SOC_SINGLE_SX_TLV("Digital Audio Volume", CS35L35_AMP_DIG_VOL,307 0, 0x34, 0xE4, dig_vol_tlv),308 SOC_SINGLE_TLV("Analog Audio Volume", CS35L35_AMP_GAIN_AUD_CTL, 0, 19, 0,309 amp_gain_tlv),310 SOC_SINGLE_TLV("PDM Volume", CS35L35_AMP_GAIN_PDM_CTL, 0, 19, 0,311 amp_gain_tlv),312};313 314static const struct snd_kcontrol_new cs35l35_adv_controls[] = {315 SOC_SINGLE_SX_TLV("Digital Advisory Volume", CS35L35_ADV_DIG_VOL,316 0, 0x34, 0xE4, dig_vol_tlv),317 SOC_SINGLE_TLV("Analog Advisory Volume", CS35L35_AMP_GAIN_ADV_CTL, 0, 19, 0,318 amp_gain_tlv),319};320 321static const struct snd_soc_dapm_widget cs35l35_dapm_widgets[] = {322 SND_SOC_DAPM_AIF_IN_E("SDIN", NULL, 0, CS35L35_PWRCTL3, 1, 1,323 cs35l35_sdin_event, SND_SOC_DAPM_PRE_PMU |324 SND_SOC_DAPM_POST_PMD),325 SND_SOC_DAPM_AIF_OUT("SDOUT", NULL, 0, CS35L35_PWRCTL3, 2, 1),326 327 SND_SOC_DAPM_OUTPUT("SPK"),328 329 SND_SOC_DAPM_INPUT("VP"),330 SND_SOC_DAPM_INPUT("VBST"),331 SND_SOC_DAPM_INPUT("ISENSE"),332 SND_SOC_DAPM_INPUT("VSENSE"),333 334 SND_SOC_DAPM_ADC("VMON ADC", NULL, CS35L35_PWRCTL2, 7, 1),335 SND_SOC_DAPM_ADC("IMON ADC", NULL, CS35L35_PWRCTL2, 6, 1),336 SND_SOC_DAPM_ADC("VPMON ADC", NULL, CS35L35_PWRCTL3, 3, 1),337 SND_SOC_DAPM_ADC("VBSTMON ADC", NULL, CS35L35_PWRCTL3, 4, 1),338 SND_SOC_DAPM_ADC("CLASS H", NULL, CS35L35_PWRCTL2, 5, 1),339 340 SND_SOC_DAPM_OUT_DRV_E("Main AMP", CS35L35_PWRCTL2, 0, 1, NULL, 0,341 cs35l35_main_amp_event, SND_SOC_DAPM_PRE_PMU |342 SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU |343 SND_SOC_DAPM_PRE_PMD),344};345 346static const struct snd_soc_dapm_route cs35l35_audio_map[] = {347 {"VPMON ADC", NULL, "VP"},348 {"VBSTMON ADC", NULL, "VBST"},349 {"IMON ADC", NULL, "ISENSE"},350 {"VMON ADC", NULL, "VSENSE"},351 {"SDOUT", NULL, "IMON ADC"},352 {"SDOUT", NULL, "VMON ADC"},353 {"SDOUT", NULL, "VBSTMON ADC"},354 {"SDOUT", NULL, "VPMON ADC"},355 {"AMP Capture", NULL, "SDOUT"},356 357 {"SDIN", NULL, "AMP Playback"},358 {"CLASS H", NULL, "SDIN"},359 {"Main AMP", NULL, "CLASS H"},360 {"SPK", NULL, "Main AMP"},361};362 363static int cs35l35_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)364{365 struct snd_soc_component *component = codec_dai->component;366 struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);367 368 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {369 case SND_SOC_DAIFMT_CBP_CFP:370 regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,371 CS35L35_MS_MASK, 1 << CS35L35_MS_SHIFT);372 cs35l35->clock_consumer = false;373 break;374 case SND_SOC_DAIFMT_CBC_CFC:375 regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,376 CS35L35_MS_MASK, 0 << CS35L35_MS_SHIFT);377 cs35l35->clock_consumer = true;378 break;379 default:380 return -EINVAL;381 }382 383 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {384 case SND_SOC_DAIFMT_I2S:385 cs35l35->i2s_mode = true;386 cs35l35->pdm_mode = false;387 break;388 case SND_SOC_DAIFMT_PDM:389 cs35l35->pdm_mode = true;390 cs35l35->i2s_mode = false;391 break;392 default:393 return -EINVAL;394 }395 396 return 0;397}398 399struct cs35l35_sysclk_config {400 int sysclk;401 int srate;402 u8 clk_cfg;403};404 405static struct cs35l35_sysclk_config cs35l35_clk_ctl[] = {406 407 /* SYSCLK, Sample Rate, Serial Port Cfg */408 {5644800, 44100, 0x00},409 {5644800, 88200, 0x40},410 {6144000, 48000, 0x10},411 {6144000, 96000, 0x50},412 {11289600, 44100, 0x01},413 {11289600, 88200, 0x41},414 {11289600, 176400, 0x81},415 {12000000, 44100, 0x03},416 {12000000, 48000, 0x13},417 {12000000, 88200, 0x43},418 {12000000, 96000, 0x53},419 {12000000, 176400, 0x83},420 {12000000, 192000, 0x93},421 {12288000, 48000, 0x11},422 {12288000, 96000, 0x51},423 {12288000, 192000, 0x91},424 {13000000, 44100, 0x07},425 {13000000, 48000, 0x17},426 {13000000, 88200, 0x47},427 {13000000, 96000, 0x57},428 {13000000, 176400, 0x87},429 {13000000, 192000, 0x97},430 {22579200, 44100, 0x02},431 {22579200, 88200, 0x42},432 {22579200, 176400, 0x82},433 {24000000, 44100, 0x0B},434 {24000000, 48000, 0x1B},435 {24000000, 88200, 0x4B},436 {24000000, 96000, 0x5B},437 {24000000, 176400, 0x8B},438 {24000000, 192000, 0x9B},439 {24576000, 48000, 0x12},440 {24576000, 96000, 0x52},441 {24576000, 192000, 0x92},442 {26000000, 44100, 0x0F},443 {26000000, 48000, 0x1F},444 {26000000, 88200, 0x4F},445 {26000000, 96000, 0x5F},446 {26000000, 176400, 0x8F},447 {26000000, 192000, 0x9F},448};449 450static int cs35l35_get_clk_config(int sysclk, int srate)451{452 int i;453 454 for (i = 0; i < ARRAY_SIZE(cs35l35_clk_ctl); i++) {455 if (cs35l35_clk_ctl[i].sysclk == sysclk &&456 cs35l35_clk_ctl[i].srate == srate)457 return cs35l35_clk_ctl[i].clk_cfg;458 }459 return -EINVAL;460}461 462static int cs35l35_hw_params(struct snd_pcm_substream *substream,463 struct snd_pcm_hw_params *params,464 struct snd_soc_dai *dai)465{466 struct snd_soc_component *component = dai->component;467 struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);468 struct classh_cfg *classh = &cs35l35->pdata.classh_algo;469 int srate = params_rate(params);470 int ret = 0;471 u8 sp_sclks;472 int audin_format;473 int errata_chk;474 475 int clk_ctl = cs35l35_get_clk_config(cs35l35->sysclk, srate);476 477 if (clk_ctl < 0) {478 dev_err(component->dev, "Invalid CLK:Rate %d:%d\n",479 cs35l35->sysclk, srate);480 return -EINVAL;481 }482 483 ret = regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL2,484 CS35L35_CLK_CTL2_MASK, clk_ctl);485 if (ret != 0) {486 dev_err(component->dev, "Failed to set port config %d\n", ret);487 return ret;488 }489 490 /*491 * Rev A0 Errata492 * When configured for the weak-drive detection path (CH_WKFET_DIS = 0)493 * the Class H algorithm does not enable weak-drive operation for494 * nonzero values of CH_WKFET_DELAY if SP_RATE = 01 or 10495 */496 errata_chk = (clk_ctl & CS35L35_SP_RATE_MASK) >> CS35L35_SP_RATE_SHIFT;497 498 if (classh->classh_wk_fet_disable == 0x00 &&499 (errata_chk == 0x01 || errata_chk == 0x02)) {500 ret = regmap_update_bits(cs35l35->regmap,501 CS35L35_CLASS_H_FET_DRIVE_CTL,502 CS35L35_CH_WKFET_DEL_MASK,503 0 << CS35L35_CH_WKFET_DEL_SHIFT);504 if (ret != 0) {505 dev_err(component->dev, "Failed to set fet config %d\n",506 ret);507 return ret;508 }509 }510 511 /*512 * You can pull more Monitor data from the SDOUT pin than going to SDIN513 * Just make sure your SCLK is fast enough to fill the frame514 */515 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {516 switch (params_width(params)) {517 case 8:518 audin_format = CS35L35_SDIN_DEPTH_8;519 break;520 case 16:521 audin_format = CS35L35_SDIN_DEPTH_16;522 break;523 case 24:524 audin_format = CS35L35_SDIN_DEPTH_24;525 break;526 default:527 dev_err(component->dev, "Unsupported Width %d\n",528 params_width(params));529 return -EINVAL;530 }531 regmap_update_bits(cs35l35->regmap,532 CS35L35_AUDIN_DEPTH_CTL,533 CS35L35_AUDIN_DEPTH_MASK,534 audin_format <<535 CS35L35_AUDIN_DEPTH_SHIFT);536 if (cs35l35->pdata.stereo) {537 regmap_update_bits(cs35l35->regmap,538 CS35L35_AUDIN_DEPTH_CTL,539 CS35L35_ADVIN_DEPTH_MASK,540 audin_format <<541 CS35L35_ADVIN_DEPTH_SHIFT);542 }543 }544 545 if (cs35l35->i2s_mode) {546 /* We have to take the SCLK to derive num sclks547 * to configure the CLOCK_CTL3 register correctly548 */549 if ((cs35l35->sclk / srate) % 4) {550 dev_err(component->dev, "Unsupported sclk/fs ratio %d:%d\n",551 cs35l35->sclk, srate);552 return -EINVAL;553 }554 sp_sclks = ((cs35l35->sclk / srate) / 4) - 1;555 556 /* Only certain ratios supported when device is a clock consumer */557 if (cs35l35->clock_consumer) {558 switch (sp_sclks) {559 case CS35L35_SP_SCLKS_32FS:560 case CS35L35_SP_SCLKS_48FS:561 case CS35L35_SP_SCLKS_64FS:562 break;563 default:564 dev_err(component->dev, "ratio not supported\n");565 return -EINVAL;566 }567 } else {568 /* Only certain ratios supported when device is a clock provider */569 switch (sp_sclks) {570 case CS35L35_SP_SCLKS_32FS:571 case CS35L35_SP_SCLKS_64FS:572 break;573 default:574 dev_err(component->dev, "ratio not supported\n");575 return -EINVAL;576 }577 }578 ret = regmap_update_bits(cs35l35->regmap,579 CS35L35_CLK_CTL3,580 CS35L35_SP_SCLKS_MASK, sp_sclks <<581 CS35L35_SP_SCLKS_SHIFT);582 if (ret != 0) {583 dev_err(component->dev, "Failed to set fsclk %d\n", ret);584 return ret;585 }586 }587 588 return ret;589}590 591static const unsigned int cs35l35_src_rates[] = {592 44100, 48000, 88200, 96000, 176400, 192000593};594 595static const struct snd_pcm_hw_constraint_list cs35l35_constraints = {596 .count = ARRAY_SIZE(cs35l35_src_rates),597 .list = cs35l35_src_rates,598};599 600static int cs35l35_pcm_startup(struct snd_pcm_substream *substream,601 struct snd_soc_dai *dai)602{603 struct snd_soc_component *component = dai->component;604 struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);605 606 if (!substream->runtime)607 return 0;608 609 snd_pcm_hw_constraint_list(substream->runtime, 0,610 SNDRV_PCM_HW_PARAM_RATE, &cs35l35_constraints);611 612 regmap_update_bits(cs35l35->regmap, CS35L35_AMP_INP_DRV_CTL,613 CS35L35_PDM_MODE_MASK,614 0 << CS35L35_PDM_MODE_SHIFT);615 616 return 0;617}618 619static const unsigned int cs35l35_pdm_rates[] = {620 44100, 48000, 88200, 96000621};622 623static const struct snd_pcm_hw_constraint_list cs35l35_pdm_constraints = {624 .count = ARRAY_SIZE(cs35l35_pdm_rates),625 .list = cs35l35_pdm_rates,626};627 628static int cs35l35_pdm_startup(struct snd_pcm_substream *substream,629 struct snd_soc_dai *dai)630{631 struct snd_soc_component *component = dai->component;632 struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);633 634 if (!substream->runtime)635 return 0;636 637 snd_pcm_hw_constraint_list(substream->runtime, 0,638 SNDRV_PCM_HW_PARAM_RATE,639 &cs35l35_pdm_constraints);640 641 regmap_update_bits(cs35l35->regmap, CS35L35_AMP_INP_DRV_CTL,642 CS35L35_PDM_MODE_MASK,643 1 << CS35L35_PDM_MODE_SHIFT);644 645 return 0;646}647 648static int cs35l35_dai_set_sysclk(struct snd_soc_dai *dai,649 int clk_id, unsigned int freq, int dir)650{651 struct snd_soc_component *component = dai->component;652 struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);653 654 /* Need the SCLK Frequency regardless of sysclk source for I2S */655 cs35l35->sclk = freq;656 657 return 0;658}659 660static const struct snd_soc_dai_ops cs35l35_ops = {661 .startup = cs35l35_pcm_startup,662 .set_fmt = cs35l35_set_dai_fmt,663 .hw_params = cs35l35_hw_params,664 .set_sysclk = cs35l35_dai_set_sysclk,665};666 667static const struct snd_soc_dai_ops cs35l35_pdm_ops = {668 .startup = cs35l35_pdm_startup,669 .set_fmt = cs35l35_set_dai_fmt,670 .hw_params = cs35l35_hw_params,671};672 673static struct snd_soc_dai_driver cs35l35_dai[] = {674 {675 .name = "cs35l35-pcm",676 .id = 0,677 .playback = {678 .stream_name = "AMP Playback",679 .channels_min = 1,680 .channels_max = 8,681 .rates = SNDRV_PCM_RATE_KNOT,682 .formats = CS35L35_FORMATS,683 },684 .capture = {685 .stream_name = "AMP Capture",686 .channels_min = 1,687 .channels_max = 8,688 .rates = SNDRV_PCM_RATE_KNOT,689 .formats = CS35L35_FORMATS,690 },691 .ops = &cs35l35_ops,692 .symmetric_rate = 1,693 },694 {695 .name = "cs35l35-pdm",696 .id = 1,697 .playback = {698 .stream_name = "PDM Playback",699 .channels_min = 1,700 .channels_max = 2,701 .rates = SNDRV_PCM_RATE_KNOT,702 .formats = CS35L35_FORMATS,703 },704 .ops = &cs35l35_pdm_ops,705 },706};707 708static int cs35l35_component_set_sysclk(struct snd_soc_component *component,709 int clk_id, int source, unsigned int freq,710 int dir)711{712 struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);713 int clksrc;714 int ret = 0;715 716 switch (clk_id) {717 case 0:718 clksrc = CS35L35_CLK_SOURCE_MCLK;719 break;720 case 1:721 clksrc = CS35L35_CLK_SOURCE_SCLK;722 break;723 case 2:724 clksrc = CS35L35_CLK_SOURCE_PDM;725 break;726 default:727 dev_err(component->dev, "Invalid CLK Source\n");728 return -EINVAL;729 }730 731 switch (freq) {732 case 5644800:733 case 6144000:734 case 11289600:735 case 12000000:736 case 12288000:737 case 13000000:738 case 22579200:739 case 24000000:740 case 24576000:741 case 26000000:742 cs35l35->sysclk = freq;743 break;744 default:745 dev_err(component->dev, "Invalid CLK Frequency Input : %d\n", freq);746 return -EINVAL;747 }748 749 ret = regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,750 CS35L35_CLK_SOURCE_MASK,751 clksrc << CS35L35_CLK_SOURCE_SHIFT);752 if (ret != 0) {753 dev_err(component->dev, "Failed to set sysclk %d\n", ret);754 return ret;755 }756 757 return ret;758}759 760static int cs35l35_boost_inductor(struct cs35l35_private *cs35l35,761 int inductor)762{763 struct regmap *regmap = cs35l35->regmap;764 unsigned int bst_ipk = 0;765 766 /*767 * Digital Boost Converter Configuration for feedback,768 * ramping, switching frequency, and estimation block seeding.769 */770 771 regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,772 CS35L35_BST_CONV_SWFREQ_MASK, 0x00);773 774 regmap_read(regmap, CS35L35_BST_PEAK_I, &bst_ipk);775 bst_ipk &= CS35L35_BST_IPK_MASK;776 777 switch (inductor) {778 case 1000: /* 1 uH */779 regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x24);780 regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x24);781 regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,782 CS35L35_BST_CONV_LBST_MASK, 0x00);783 784 if (bst_ipk < 0x04)785 regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);786 else787 regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x4E);788 break;789 case 1200: /* 1.2 uH */790 regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20);791 regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20);792 regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,793 CS35L35_BST_CONV_LBST_MASK, 0x01);794 795 if (bst_ipk < 0x04)796 regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);797 else798 regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x47);799 break;800 case 1500: /* 1.5uH */801 regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20);802 regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20);803 regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,804 CS35L35_BST_CONV_LBST_MASK, 0x02);805 806 if (bst_ipk < 0x04)807 regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);808 else809 regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x3C);810 break;811 case 2200: /* 2.2uH */812 regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x19);813 regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x25);814 regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,815 CS35L35_BST_CONV_LBST_MASK, 0x03);816 817 if (bst_ipk < 0x04)818 regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);819 else820 regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x23);821 break;822 default:823 dev_err(cs35l35->dev, "Invalid Inductor Value %d uH\n",824 inductor);825 return -EINVAL;826 }827 return 0;828}829 830static int cs35l35_component_probe(struct snd_soc_component *component)831{832 struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);833 struct classh_cfg *classh = &cs35l35->pdata.classh_algo;834 struct monitor_cfg *monitor_config = &cs35l35->pdata.mon_cfg;835 int ret;836 837 /* Set Platform Data */838 if (cs35l35->pdata.bst_vctl)839 regmap_update_bits(cs35l35->regmap, CS35L35_BST_CVTR_V_CTL,840 CS35L35_BST_CTL_MASK,841 cs35l35->pdata.bst_vctl);842 843 if (cs35l35->pdata.bst_ipk)844 regmap_update_bits(cs35l35->regmap, CS35L35_BST_PEAK_I,845 CS35L35_BST_IPK_MASK,846 cs35l35->pdata.bst_ipk <<847 CS35L35_BST_IPK_SHIFT);848 849 ret = cs35l35_boost_inductor(cs35l35, cs35l35->pdata.boost_ind);850 if (ret)851 return ret;852 853 if (cs35l35->pdata.gain_zc)854 regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,855 CS35L35_AMP_GAIN_ZC_MASK,856 cs35l35->pdata.gain_zc <<857 CS35L35_AMP_GAIN_ZC_SHIFT);858 859 if (cs35l35->pdata.aud_channel)860 regmap_update_bits(cs35l35->regmap,861 CS35L35_AUDIN_RXLOC_CTL,862 CS35L35_AUD_IN_LR_MASK,863 cs35l35->pdata.aud_channel <<864 CS35L35_AUD_IN_LR_SHIFT);865 866 if (cs35l35->pdata.stereo) {867 regmap_update_bits(cs35l35->regmap,868 CS35L35_ADVIN_RXLOC_CTL,869 CS35L35_ADV_IN_LR_MASK,870 cs35l35->pdata.adv_channel <<871 CS35L35_ADV_IN_LR_SHIFT);872 if (cs35l35->pdata.shared_bst)873 regmap_update_bits(cs35l35->regmap, CS35L35_CLASS_H_CTL,874 CS35L35_CH_STEREO_MASK,875 1 << CS35L35_CH_STEREO_SHIFT);876 ret = snd_soc_add_component_controls(component, cs35l35_adv_controls,877 ARRAY_SIZE(cs35l35_adv_controls));878 if (ret)879 return ret;880 }881 882 if (cs35l35->pdata.sp_drv_str)883 regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,884 CS35L35_SP_DRV_MASK,885 cs35l35->pdata.sp_drv_str <<886 CS35L35_SP_DRV_SHIFT);887 if (cs35l35->pdata.sp_drv_unused)888 regmap_update_bits(cs35l35->regmap, CS35L35_SP_FMT_CTL3,889 CS35L35_SP_I2S_DRV_MASK,890 cs35l35->pdata.sp_drv_unused <<891 CS35L35_SP_I2S_DRV_SHIFT);892 893 if (classh->classh_algo_enable) {894 if (classh->classh_bst_override)895 regmap_update_bits(cs35l35->regmap,896 CS35L35_CLASS_H_CTL,897 CS35L35_CH_BST_OVR_MASK,898 classh->classh_bst_override <<899 CS35L35_CH_BST_OVR_SHIFT);900 if (classh->classh_bst_max_limit)901 regmap_update_bits(cs35l35->regmap,902 CS35L35_CLASS_H_CTL,903 CS35L35_CH_BST_LIM_MASK,904 classh->classh_bst_max_limit <<905 CS35L35_CH_BST_LIM_SHIFT);906 if (classh->classh_mem_depth)907 regmap_update_bits(cs35l35->regmap,908 CS35L35_CLASS_H_CTL,909 CS35L35_CH_MEM_DEPTH_MASK,910 classh->classh_mem_depth <<911 CS35L35_CH_MEM_DEPTH_SHIFT);912 if (classh->classh_headroom)913 regmap_update_bits(cs35l35->regmap,914 CS35L35_CLASS_H_HEADRM_CTL,915 CS35L35_CH_HDRM_CTL_MASK,916 classh->classh_headroom <<917 CS35L35_CH_HDRM_CTL_SHIFT);918 if (classh->classh_release_rate)919 regmap_update_bits(cs35l35->regmap,920 CS35L35_CLASS_H_RELEASE_RATE,921 CS35L35_CH_REL_RATE_MASK,922 classh->classh_release_rate <<923 CS35L35_CH_REL_RATE_SHIFT);924 if (classh->classh_wk_fet_disable)925 regmap_update_bits(cs35l35->regmap,926 CS35L35_CLASS_H_FET_DRIVE_CTL,927 CS35L35_CH_WKFET_DIS_MASK,928 classh->classh_wk_fet_disable <<929 CS35L35_CH_WKFET_DIS_SHIFT);930 if (classh->classh_wk_fet_delay)931 regmap_update_bits(cs35l35->regmap,932 CS35L35_CLASS_H_FET_DRIVE_CTL,933 CS35L35_CH_WKFET_DEL_MASK,934 classh->classh_wk_fet_delay <<935 CS35L35_CH_WKFET_DEL_SHIFT);936 if (classh->classh_wk_fet_thld)937 regmap_update_bits(cs35l35->regmap,938 CS35L35_CLASS_H_FET_DRIVE_CTL,939 CS35L35_CH_WKFET_THLD_MASK,940 classh->classh_wk_fet_thld <<941 CS35L35_CH_WKFET_THLD_SHIFT);942 if (classh->classh_vpch_auto)943 regmap_update_bits(cs35l35->regmap,944 CS35L35_CLASS_H_VP_CTL,945 CS35L35_CH_VP_AUTO_MASK,946 classh->classh_vpch_auto <<947 CS35L35_CH_VP_AUTO_SHIFT);948 if (classh->classh_vpch_rate)949 regmap_update_bits(cs35l35->regmap,950 CS35L35_CLASS_H_VP_CTL,951 CS35L35_CH_VP_RATE_MASK,952 classh->classh_vpch_rate <<953 CS35L35_CH_VP_RATE_SHIFT);954 if (classh->classh_vpch_man)955 regmap_update_bits(cs35l35->regmap,956 CS35L35_CLASS_H_VP_CTL,957 CS35L35_CH_VP_MAN_MASK,958 classh->classh_vpch_man <<959 CS35L35_CH_VP_MAN_SHIFT);960 }961 962 if (monitor_config->is_present) {963 if (monitor_config->vmon_specs) {964 regmap_update_bits(cs35l35->regmap,965 CS35L35_SPKMON_DEPTH_CTL,966 CS35L35_VMON_DEPTH_MASK,967 monitor_config->vmon_dpth <<968 CS35L35_VMON_DEPTH_SHIFT);969 regmap_update_bits(cs35l35->regmap,970 CS35L35_VMON_TXLOC_CTL,971 CS35L35_MON_TXLOC_MASK,972 monitor_config->vmon_loc <<973 CS35L35_MON_TXLOC_SHIFT);974 regmap_update_bits(cs35l35->regmap,975 CS35L35_VMON_TXLOC_CTL,976 CS35L35_MON_FRM_MASK,977 monitor_config->vmon_frm <<978 CS35L35_MON_FRM_SHIFT);979 }980 if (monitor_config->imon_specs) {981 regmap_update_bits(cs35l35->regmap,982 CS35L35_SPKMON_DEPTH_CTL,983 CS35L35_IMON_DEPTH_MASK,984 monitor_config->imon_dpth <<985 CS35L35_IMON_DEPTH_SHIFT);986 regmap_update_bits(cs35l35->regmap,987 CS35L35_IMON_TXLOC_CTL,988 CS35L35_MON_TXLOC_MASK,989 monitor_config->imon_loc <<990 CS35L35_MON_TXLOC_SHIFT);991 regmap_update_bits(cs35l35->regmap,992 CS35L35_IMON_TXLOC_CTL,993 CS35L35_MON_FRM_MASK,994 monitor_config->imon_frm <<995 CS35L35_MON_FRM_SHIFT);996 regmap_update_bits(cs35l35->regmap,997 CS35L35_IMON_SCALE_CTL,998 CS35L35_IMON_SCALE_MASK,999 monitor_config->imon_scale <<1000 CS35L35_IMON_SCALE_SHIFT);1001 }1002 if (monitor_config->vpmon_specs) {1003 regmap_update_bits(cs35l35->regmap,1004 CS35L35_SUPMON_DEPTH_CTL,1005 CS35L35_VPMON_DEPTH_MASK,1006 monitor_config->vpmon_dpth <<1007 CS35L35_VPMON_DEPTH_SHIFT);1008 regmap_update_bits(cs35l35->regmap,1009 CS35L35_VPMON_TXLOC_CTL,1010 CS35L35_MON_TXLOC_MASK,1011 monitor_config->vpmon_loc <<1012 CS35L35_MON_TXLOC_SHIFT);1013 regmap_update_bits(cs35l35->regmap,1014 CS35L35_VPMON_TXLOC_CTL,1015 CS35L35_MON_FRM_MASK,1016 monitor_config->vpmon_frm <<1017 CS35L35_MON_FRM_SHIFT);1018 }1019 if (monitor_config->vbstmon_specs) {1020 regmap_update_bits(cs35l35->regmap,1021 CS35L35_SUPMON_DEPTH_CTL,1022 CS35L35_VBSTMON_DEPTH_MASK,1023 monitor_config->vpmon_dpth <<1024 CS35L35_VBSTMON_DEPTH_SHIFT);1025 regmap_update_bits(cs35l35->regmap,1026 CS35L35_VBSTMON_TXLOC_CTL,1027 CS35L35_MON_TXLOC_MASK,1028 monitor_config->vbstmon_loc <<1029 CS35L35_MON_TXLOC_SHIFT);1030 regmap_update_bits(cs35l35->regmap,1031 CS35L35_VBSTMON_TXLOC_CTL,1032 CS35L35_MON_FRM_MASK,1033 monitor_config->vbstmon_frm <<1034 CS35L35_MON_FRM_SHIFT);1035 }1036 if (monitor_config->vpbrstat_specs) {1037 regmap_update_bits(cs35l35->regmap,1038 CS35L35_SUPMON_DEPTH_CTL,1039 CS35L35_VPBRSTAT_DEPTH_MASK,1040 monitor_config->vpbrstat_dpth <<1041 CS35L35_VPBRSTAT_DEPTH_SHIFT);1042 regmap_update_bits(cs35l35->regmap,1043 CS35L35_VPBR_STATUS_TXLOC_CTL,1044 CS35L35_MON_TXLOC_MASK,1045 monitor_config->vpbrstat_loc <<1046 CS35L35_MON_TXLOC_SHIFT);1047 regmap_update_bits(cs35l35->regmap,1048 CS35L35_VPBR_STATUS_TXLOC_CTL,1049 CS35L35_MON_FRM_MASK,1050 monitor_config->vpbrstat_frm <<1051 CS35L35_MON_FRM_SHIFT);1052 }1053 if (monitor_config->zerofill_specs) {1054 regmap_update_bits(cs35l35->regmap,1055 CS35L35_SUPMON_DEPTH_CTL,1056 CS35L35_ZEROFILL_DEPTH_MASK,1057 monitor_config->zerofill_dpth <<1058 CS35L35_ZEROFILL_DEPTH_SHIFT);1059 regmap_update_bits(cs35l35->regmap,1060 CS35L35_ZERO_FILL_LOC_CTL,1061 CS35L35_MON_TXLOC_MASK,1062 monitor_config->zerofill_loc <<1063 CS35L35_MON_TXLOC_SHIFT);1064 regmap_update_bits(cs35l35->regmap,1065 CS35L35_ZERO_FILL_LOC_CTL,1066 CS35L35_MON_FRM_MASK,1067 monitor_config->zerofill_frm <<1068 CS35L35_MON_FRM_SHIFT);1069 }1070 }1071 1072 return 0;1073}1074 1075static const struct snd_soc_component_driver soc_component_dev_cs35l35 = {1076 .probe = cs35l35_component_probe,1077 .set_sysclk = cs35l35_component_set_sysclk,1078 .dapm_widgets = cs35l35_dapm_widgets,1079 .num_dapm_widgets = ARRAY_SIZE(cs35l35_dapm_widgets),1080 .dapm_routes = cs35l35_audio_map,1081 .num_dapm_routes = ARRAY_SIZE(cs35l35_audio_map),1082 .controls = cs35l35_aud_controls,1083 .num_controls = ARRAY_SIZE(cs35l35_aud_controls),1084 .idle_bias_on = 1,1085 .use_pmdown_time = 1,1086 .endianness = 1,1087};1088 1089static const struct regmap_config cs35l35_regmap = {1090 .reg_bits = 8,1091 .val_bits = 8,1092 1093 .max_register = CS35L35_MAX_REGISTER,1094 .reg_defaults = cs35l35_reg,1095 .num_reg_defaults = ARRAY_SIZE(cs35l35_reg),1096 .volatile_reg = cs35l35_volatile_register,1097 .readable_reg = cs35l35_readable_register,1098 .precious_reg = cs35l35_precious_register,1099 .cache_type = REGCACHE_MAPLE,1100 .use_single_read = true,1101 .use_single_write = true,1102};1103 1104static irqreturn_t cs35l35_irq(int irq, void *data)1105{1106 struct cs35l35_private *cs35l35 = data;1107 unsigned int sticky1, sticky2, sticky3, sticky4;1108 unsigned int mask1, mask2, mask3, mask4, current1;1109 1110 /* ack the irq by reading all status registers */1111 regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_4, &sticky4);1112 regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_3, &sticky3);1113 regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_2, &sticky2);1114 regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_1, &sticky1);1115 1116 regmap_read(cs35l35->regmap, CS35L35_INT_MASK_4, &mask4);1117 regmap_read(cs35l35->regmap, CS35L35_INT_MASK_3, &mask3);1118 regmap_read(cs35l35->regmap, CS35L35_INT_MASK_2, &mask2);1119 regmap_read(cs35l35->regmap, CS35L35_INT_MASK_1, &mask1);1120 1121 /* Check to see if unmasked bits are active */1122 if (!(sticky1 & ~mask1) && !(sticky2 & ~mask2) && !(sticky3 & ~mask3)1123 && !(sticky4 & ~mask4))1124 return IRQ_NONE;1125 1126 if (sticky2 & CS35L35_PDN_DONE)1127 complete(&cs35l35->pdn_done);1128 1129 /* read the current values */1130 regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_1, ¤t1);1131 1132 /* handle the interrupts */1133 if (sticky1 & CS35L35_CAL_ERR) {1134 dev_crit(cs35l35->dev, "Calibration Error\n");1135 1136 /* error is no longer asserted; safe to reset */1137 if (!(current1 & CS35L35_CAL_ERR)) {1138 pr_debug("%s : Cal error release\n", __func__);1139 regmap_update_bits(cs35l35->regmap,1140 CS35L35_PROT_RELEASE_CTL,1141 CS35L35_CAL_ERR_RLS, 0);1142 regmap_update_bits(cs35l35->regmap,1143 CS35L35_PROT_RELEASE_CTL,1144 CS35L35_CAL_ERR_RLS,1145 CS35L35_CAL_ERR_RLS);1146 regmap_update_bits(cs35l35->regmap,1147 CS35L35_PROT_RELEASE_CTL,1148 CS35L35_CAL_ERR_RLS, 0);1149 }1150 }1151 1152 if (sticky1 & CS35L35_AMP_SHORT) {1153 dev_crit(cs35l35->dev, "AMP Short Error\n");1154 /* error is no longer asserted; safe to reset */1155 if (!(current1 & CS35L35_AMP_SHORT)) {1156 dev_dbg(cs35l35->dev, "Amp short error release\n");1157 regmap_update_bits(cs35l35->regmap,1158 CS35L35_PROT_RELEASE_CTL,1159 CS35L35_SHORT_RLS, 0);1160 regmap_update_bits(cs35l35->regmap,1161 CS35L35_PROT_RELEASE_CTL,1162 CS35L35_SHORT_RLS,1163 CS35L35_SHORT_RLS);1164 regmap_update_bits(cs35l35->regmap,1165 CS35L35_PROT_RELEASE_CTL,1166 CS35L35_SHORT_RLS, 0);1167 }1168 }1169 1170 if (sticky1 & CS35L35_OTW) {1171 dev_warn(cs35l35->dev, "Over temperature warning\n");1172 1173 /* error is no longer asserted; safe to reset */1174 if (!(current1 & CS35L35_OTW)) {1175 dev_dbg(cs35l35->dev, "Over temperature warn release\n");1176 regmap_update_bits(cs35l35->regmap,1177 CS35L35_PROT_RELEASE_CTL,1178 CS35L35_OTW_RLS, 0);1179 regmap_update_bits(cs35l35->regmap,1180 CS35L35_PROT_RELEASE_CTL,1181 CS35L35_OTW_RLS,1182 CS35L35_OTW_RLS);1183 regmap_update_bits(cs35l35->regmap,1184 CS35L35_PROT_RELEASE_CTL,1185 CS35L35_OTW_RLS, 0);1186 }1187 }1188 1189 if (sticky1 & CS35L35_OTE) {1190 dev_crit(cs35l35->dev, "Over temperature error\n");1191 /* error is no longer asserted; safe to reset */1192 if (!(current1 & CS35L35_OTE)) {1193 dev_dbg(cs35l35->dev, "Over temperature error release\n");1194 regmap_update_bits(cs35l35->regmap,1195 CS35L35_PROT_RELEASE_CTL,1196 CS35L35_OTE_RLS, 0);1197 regmap_update_bits(cs35l35->regmap,1198 CS35L35_PROT_RELEASE_CTL,1199 CS35L35_OTE_RLS,1200 CS35L35_OTE_RLS);1201 regmap_update_bits(cs35l35->regmap,1202 CS35L35_PROT_RELEASE_CTL,1203 CS35L35_OTE_RLS, 0);1204 }1205 }1206 1207 if (sticky3 & CS35L35_BST_HIGH) {1208 dev_crit(cs35l35->dev, "VBST error: powering off!\n");1209 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,1210 CS35L35_PDN_AMP, CS35L35_PDN_AMP);1211 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,1212 CS35L35_PDN_ALL, CS35L35_PDN_ALL);1213 }1214 1215 if (sticky3 & CS35L35_LBST_SHORT) {1216 dev_crit(cs35l35->dev, "LBST error: powering off!\n");1217 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,1218 CS35L35_PDN_AMP, CS35L35_PDN_AMP);1219 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,1220 CS35L35_PDN_ALL, CS35L35_PDN_ALL);1221 }1222 1223 if (sticky2 & CS35L35_VPBR_ERR)1224 dev_dbg(cs35l35->dev, "Error: Reactive Brownout\n");1225 1226 if (sticky4 & CS35L35_VMON_OVFL)1227 dev_dbg(cs35l35->dev, "Error: VMON overflow\n");1228 1229 if (sticky4 & CS35L35_IMON_OVFL)1230 dev_dbg(cs35l35->dev, "Error: IMON overflow\n");1231 1232 return IRQ_HANDLED;1233}1234 1235 1236static int cs35l35_handle_of_data(struct i2c_client *i2c_client,1237 struct cs35l35_platform_data *pdata)1238{1239 struct device_node *np = i2c_client->dev.of_node;1240 struct device_node *classh, *signal_format;1241 struct classh_cfg *classh_config = &pdata->classh_algo;1242 struct monitor_cfg *monitor_config = &pdata->mon_cfg;1243 unsigned int val32 = 0;1244 u8 monitor_array[4];1245 const int imon_array_size = ARRAY_SIZE(monitor_array);1246 const int mon_array_size = imon_array_size - 1;1247 int ret = 0;1248 1249 if (!np)1250 return 0;1251 1252 pdata->bst_pdn_fet_on = of_property_read_bool(np,1253 "cirrus,boost-pdn-fet-on");1254 1255 ret = of_property_read_u32(np, "cirrus,boost-ctl-millivolt", &val32);1256 if (ret >= 0) {1257 if (val32 < 2600 || val32 > 9000) {1258 dev_err(&i2c_client->dev,1259 "Invalid Boost Voltage %d mV\n", val32);1260 return -EINVAL;1261 }1262 pdata->bst_vctl = ((val32 - 2600) / 100) + 1;1263 }1264 1265 ret = of_property_read_u32(np, "cirrus,boost-peak-milliamp", &val32);1266 if (ret >= 0) {1267 if (val32 < 1680 || val32 > 4480) {1268 dev_err(&i2c_client->dev,1269 "Invalid Boost Peak Current %u mA\n", val32);1270 return -EINVAL;1271 }1272 1273 pdata->bst_ipk = ((val32 - 1680) / 110) | CS35L35_VALID_PDATA;1274 }1275 1276 ret = of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val32);1277 if (ret >= 0) {1278 pdata->boost_ind = val32;1279 } else {1280 dev_err(&i2c_client->dev, "Inductor not specified.\n");1281 return -EINVAL;1282 }1283 1284 if (of_property_read_u32(np, "cirrus,sp-drv-strength", &val32) >= 0)1285 pdata->sp_drv_str = val32;1286 if (of_property_read_u32(np, "cirrus,sp-drv-unused", &val32) >= 0)1287 pdata->sp_drv_unused = val32 | CS35L35_VALID_PDATA;1288 1289 pdata->stereo = of_property_read_bool(np, "cirrus,stereo-config");1290 1291 if (pdata->stereo) {1292 ret = of_property_read_u32(np, "cirrus,audio-channel", &val32);1293 if (ret >= 0)1294 pdata->aud_channel = val32;1295 1296 ret = of_property_read_u32(np, "cirrus,advisory-channel",1297 &val32);1298 if (ret >= 0)1299 pdata->adv_channel = val32;1300 1301 pdata->shared_bst = of_property_read_bool(np,1302 "cirrus,shared-boost");1303 }1304 1305 pdata->ext_bst = of_property_read_bool(np, "cirrus,external-boost");1306 1307 pdata->gain_zc = of_property_read_bool(np, "cirrus,amp-gain-zc");1308 1309 classh = of_get_child_by_name(np, "cirrus,classh-internal-algo");1310 classh_config->classh_algo_enable = (classh != NULL);1311 1312 if (classh_config->classh_algo_enable) {1313 classh_config->classh_bst_override =1314 of_property_read_bool(np, "cirrus,classh-bst-overide");1315 1316 ret = of_property_read_u32(classh,1317 "cirrus,classh-bst-max-limit",1318 &val32);1319 if (ret >= 0) {1320 val32 |= CS35L35_VALID_PDATA;1321 classh_config->classh_bst_max_limit = val32;1322 }1323 1324 ret = of_property_read_u32(classh,1325 "cirrus,classh-bst-max-limit",1326 &val32);1327 if (ret >= 0) {1328 val32 |= CS35L35_VALID_PDATA;1329 classh_config->classh_bst_max_limit = val32;1330 }1331 1332 ret = of_property_read_u32(classh, "cirrus,classh-mem-depth",1333 &val32);1334 if (ret >= 0) {1335 val32 |= CS35L35_VALID_PDATA;1336 classh_config->classh_mem_depth = val32;1337 }1338 1339 ret = of_property_read_u32(classh, "cirrus,classh-release-rate",1340 &val32);1341 if (ret >= 0)1342 classh_config->classh_release_rate = val32;1343 1344 ret = of_property_read_u32(classh, "cirrus,classh-headroom",1345 &val32);1346 if (ret >= 0) {1347 val32 |= CS35L35_VALID_PDATA;1348 classh_config->classh_headroom = val32;1349 }1350 1351 ret = of_property_read_u32(classh,1352 "cirrus,classh-wk-fet-disable",1353 &val32);1354 if (ret >= 0)1355 classh_config->classh_wk_fet_disable = val32;1356 1357 ret = of_property_read_u32(classh, "cirrus,classh-wk-fet-delay",1358 &val32);1359 if (ret >= 0) {1360 val32 |= CS35L35_VALID_PDATA;1361 classh_config->classh_wk_fet_delay = val32;1362 }1363 1364 ret = of_property_read_u32(classh, "cirrus,classh-wk-fet-thld",1365 &val32);1366 if (ret >= 0)1367 classh_config->classh_wk_fet_thld = val32;1368 1369 ret = of_property_read_u32(classh, "cirrus,classh-vpch-auto",1370 &val32);1371 if (ret >= 0) {1372 val32 |= CS35L35_VALID_PDATA;1373 classh_config->classh_vpch_auto = val32;1374 }1375 1376 ret = of_property_read_u32(classh, "cirrus,classh-vpch-rate",1377 &val32);1378 if (ret >= 0) {1379 val32 |= CS35L35_VALID_PDATA;1380 classh_config->classh_vpch_rate = val32;1381 }1382 1383 ret = of_property_read_u32(classh, "cirrus,classh-vpch-man",1384 &val32);1385 if (ret >= 0)1386 classh_config->classh_vpch_man = val32;1387 }1388 of_node_put(classh);1389 1390 /* frame depth location */1391 signal_format = of_get_child_by_name(np, "cirrus,monitor-signal-format");1392 monitor_config->is_present = signal_format ? true : false;1393 if (monitor_config->is_present) {1394 ret = of_property_read_u8_array(signal_format, "cirrus,imon",1395 monitor_array, imon_array_size);1396 if (!ret) {1397 monitor_config->imon_specs = true;1398 monitor_config->imon_dpth = monitor_array[0];1399 monitor_config->imon_loc = monitor_array[1];1400 monitor_config->imon_frm = monitor_array[2];1401 monitor_config->imon_scale = monitor_array[3];1402 }1403 ret = of_property_read_u8_array(signal_format, "cirrus,vmon",1404 monitor_array, mon_array_size);1405 if (!ret) {1406 monitor_config->vmon_specs = true;1407 monitor_config->vmon_dpth = monitor_array[0];1408 monitor_config->vmon_loc = monitor_array[1];1409 monitor_config->vmon_frm = monitor_array[2];1410 }1411 ret = of_property_read_u8_array(signal_format, "cirrus,vpmon",1412 monitor_array, mon_array_size);1413 if (!ret) {1414 monitor_config->vpmon_specs = true;1415 monitor_config->vpmon_dpth = monitor_array[0];1416 monitor_config->vpmon_loc = monitor_array[1];1417 monitor_config->vpmon_frm = monitor_array[2];1418 }1419 ret = of_property_read_u8_array(signal_format, "cirrus,vbstmon",1420 monitor_array, mon_array_size);1421 if (!ret) {1422 monitor_config->vbstmon_specs = true;1423 monitor_config->vbstmon_dpth = monitor_array[0];1424 monitor_config->vbstmon_loc = monitor_array[1];1425 monitor_config->vbstmon_frm = monitor_array[2];1426 }1427 ret = of_property_read_u8_array(signal_format, "cirrus,vpbrstat",1428 monitor_array, mon_array_size);1429 if (!ret) {1430 monitor_config->vpbrstat_specs = true;1431 monitor_config->vpbrstat_dpth = monitor_array[0];1432 monitor_config->vpbrstat_loc = monitor_array[1];1433 monitor_config->vpbrstat_frm = monitor_array[2];1434 }1435 ret = of_property_read_u8_array(signal_format, "cirrus,zerofill",1436 monitor_array, mon_array_size);1437 if (!ret) {1438 monitor_config->zerofill_specs = true;1439 monitor_config->zerofill_dpth = monitor_array[0];1440 monitor_config->zerofill_loc = monitor_array[1];1441 monitor_config->zerofill_frm = monitor_array[2];1442 }1443 }1444 of_node_put(signal_format);1445 1446 return 0;1447}1448 1449/* Errata Rev A0 */1450static const struct reg_sequence cs35l35_errata_patch[] = {1451 1452 { 0x7F, 0x99 },1453 { 0x00, 0x99 },1454 { 0x52, 0x22 },1455 { 0x04, 0x14 },1456 { 0x6D, 0x44 },1457 { 0x24, 0x10 },1458 { 0x58, 0xC4 },1459 { 0x00, 0x98 },1460 { 0x18, 0x08 },1461 { 0x00, 0x00 },1462 { 0x7F, 0x00 },1463};1464 1465static int cs35l35_i2c_probe(struct i2c_client *i2c_client)1466{1467 struct cs35l35_private *cs35l35;1468 struct device *dev = &i2c_client->dev;1469 struct cs35l35_platform_data *pdata = dev_get_platdata(dev);1470 int i, devid;1471 int ret;1472 unsigned int reg;1473 1474 cs35l35 = devm_kzalloc(dev, sizeof(struct cs35l35_private), GFP_KERNEL);1475 if (!cs35l35)1476 return -ENOMEM;1477 1478 cs35l35->dev = dev;1479 1480 i2c_set_clientdata(i2c_client, cs35l35);1481 cs35l35->regmap = devm_regmap_init_i2c(i2c_client, &cs35l35_regmap);1482 if (IS_ERR(cs35l35->regmap)) {1483 ret = PTR_ERR(cs35l35->regmap);1484 dev_err(dev, "regmap_init() failed: %d\n", ret);1485 return ret;1486 }1487 1488 for (i = 0; i < ARRAY_SIZE(cs35l35_supplies); i++)1489 cs35l35->supplies[i].supply = cs35l35_supplies[i];1490 1491 cs35l35->num_supplies = ARRAY_SIZE(cs35l35_supplies);1492 1493 ret = devm_regulator_bulk_get(dev, cs35l35->num_supplies,1494 cs35l35->supplies);1495 if (ret != 0) {1496 dev_err(dev, "Failed to request core supplies: %d\n", ret);1497 return ret;1498 }1499 1500 if (pdata) {1501 cs35l35->pdata = *pdata;1502 } else {1503 pdata = devm_kzalloc(dev, sizeof(struct cs35l35_platform_data),1504 GFP_KERNEL);1505 if (!pdata)1506 return -ENOMEM;1507 if (i2c_client->dev.of_node) {1508 ret = cs35l35_handle_of_data(i2c_client, pdata);1509 if (ret != 0)1510 return ret;1511 1512 }1513 cs35l35->pdata = *pdata;1514 }1515 1516 ret = regulator_bulk_enable(cs35l35->num_supplies,1517 cs35l35->supplies);1518 if (ret != 0) {1519 dev_err(dev, "Failed to enable core supplies: %d\n", ret);1520 return ret;1521 }1522 1523 /* returning NULL can be valid if in stereo mode */1524 cs35l35->reset_gpio = devm_gpiod_get_optional(dev, "reset",1525 GPIOD_OUT_LOW);1526 if (IS_ERR(cs35l35->reset_gpio)) {1527 ret = PTR_ERR(cs35l35->reset_gpio);1528 cs35l35->reset_gpio = NULL;1529 if (ret == -EBUSY) {1530 dev_info(dev,1531 "Reset line busy, assuming shared reset\n");1532 } else {1533 dev_err(dev, "Failed to get reset GPIO: %d\n", ret);1534 goto err;1535 }1536 }1537 1538 cs35l35_reset(cs35l35);1539 1540 init_completion(&cs35l35->pdn_done);1541 1542 ret = devm_request_threaded_irq(dev, i2c_client->irq, NULL, cs35l35_irq,1543 IRQF_ONESHOT | IRQF_TRIGGER_LOW |1544 IRQF_SHARED, "cs35l35", cs35l35);1545 if (ret != 0) {1546 dev_err(dev, "Failed to request IRQ: %d\n", ret);1547 goto err;1548 }1549 /* initialize codec */1550 devid = cirrus_read_device_id(cs35l35->regmap, CS35L35_DEVID_AB);1551 if (devid < 0) {1552 ret = devid;1553 dev_err(dev, "Failed to read device ID: %d\n", ret);1554 goto err;1555 }1556 1557 if (devid != CS35L35_CHIP_ID) {1558 dev_err(dev, "CS35L35 Device ID (%X). Expected ID %X\n",1559 devid, CS35L35_CHIP_ID);1560 ret = -ENODEV;1561 goto err;1562 }1563 1564 ret = regmap_read(cs35l35->regmap, CS35L35_REV_ID, ®);1565 if (ret < 0) {1566 dev_err(dev, "Get Revision ID failed: %d\n", ret);1567 goto err;1568 }1569 1570 ret = regmap_register_patch(cs35l35->regmap, cs35l35_errata_patch,1571 ARRAY_SIZE(cs35l35_errata_patch));1572 if (ret < 0) {1573 dev_err(dev, "Failed to apply errata patch: %d\n", ret);1574 goto err;1575 }1576 1577 dev_info(dev, "Cirrus Logic CS35L35 (%x), Revision: %02X\n",1578 devid, reg & 0xFF);1579 1580 /* Set the INT Masks for critical errors */1581 regmap_write(cs35l35->regmap, CS35L35_INT_MASK_1,1582 CS35L35_INT1_CRIT_MASK);1583 regmap_write(cs35l35->regmap, CS35L35_INT_MASK_2,1584 CS35L35_INT2_CRIT_MASK);1585 regmap_write(cs35l35->regmap, CS35L35_INT_MASK_3,1586 CS35L35_INT3_CRIT_MASK);1587 regmap_write(cs35l35->regmap, CS35L35_INT_MASK_4,1588 CS35L35_INT4_CRIT_MASK);1589 1590 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,1591 CS35L35_PWR2_PDN_MASK,1592 CS35L35_PWR2_PDN_MASK);1593 1594 if (cs35l35->pdata.bst_pdn_fet_on)1595 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,1596 CS35L35_PDN_BST_MASK,1597 1 << CS35L35_PDN_BST_FETON_SHIFT);1598 else1599 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,1600 CS35L35_PDN_BST_MASK,1601 1 << CS35L35_PDN_BST_FETOFF_SHIFT);1602 1603 regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL3,1604 CS35L35_PWR3_PDN_MASK,1605 CS35L35_PWR3_PDN_MASK);1606 1607 regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,1608 CS35L35_AMP_MUTE_MASK, 1 << CS35L35_AMP_MUTE_SHIFT);1609 1610 ret = devm_snd_soc_register_component(dev, &soc_component_dev_cs35l35,1611 cs35l35_dai, ARRAY_SIZE(cs35l35_dai));1612 if (ret < 0) {1613 dev_err(dev, "Failed to register component: %d\n", ret);1614 goto err;1615 }1616 1617 return 0;1618 1619err:1620 regulator_bulk_disable(cs35l35->num_supplies,1621 cs35l35->supplies);1622 gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);1623 1624 return ret;1625}1626 1627static void cs35l35_i2c_remove(struct i2c_client *i2c_client)1628{1629 struct cs35l35_private *cs35l35 = i2c_get_clientdata(i2c_client);1630 1631 regulator_bulk_disable(cs35l35->num_supplies, cs35l35->supplies);1632 gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);1633}1634 1635static const struct of_device_id cs35l35_of_match[] = {1636 {.compatible = "cirrus,cs35l35"},1637 {},1638};1639MODULE_DEVICE_TABLE(of, cs35l35_of_match);1640 1641static const struct i2c_device_id cs35l35_id[] = {1642 {"cs35l35"},1643 {}1644};1645 1646MODULE_DEVICE_TABLE(i2c, cs35l35_id);1647 1648static struct i2c_driver cs35l35_i2c_driver = {1649 .driver = {1650 .name = "cs35l35",1651 .of_match_table = cs35l35_of_match,1652 },1653 .id_table = cs35l35_id,1654 .probe = cs35l35_i2c_probe,1655 .remove = cs35l35_i2c_remove,1656};1657 1658module_i2c_driver(cs35l35_i2c_driver);1659 1660MODULE_DESCRIPTION("ASoC CS35L35 driver");1661MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");1662MODULE_LICENSE("GPL");1663