/* * Some fields take zero as a valid value so use a high bit flag that won't * get written to the device to mark those.
*/ #define CS35L35_VALID_PDATA 0x80000000
staticbool cs35l35_volatile_register(struct device *dev, unsignedint reg)
{ switch (reg) { case CS35L35_INT_STATUS_1: case CS35L35_INT_STATUS_2: case CS35L35_INT_STATUS_3: case CS35L35_INT_STATUS_4: case CS35L35_PLL_STATUS: case CS35L35_OTP_TRIM_STATUS: returntrue; default: returnfalse;
}
}
staticbool cs35l35_readable_register(struct device *dev, unsignedint reg)
{ switch (reg) { case CS35L35_DEVID_AB ... CS35L35_PWRCTL3: case CS35L35_CLK_CTL1 ... CS35L35_SP_FMT_CTL3: case CS35L35_MAG_COMP_CTL ... CS35L35_AMP_GAIN_AUD_CTL: case CS35L35_AMP_GAIN_PDM_CTL ... CS35L35_BST_PEAK_I: case CS35L35_BST_RAMP_CTL ... CS35L35_BST_CONV_SW_FREQ: case CS35L35_CLASS_H_CTL ... CS35L35_CLASS_H_VP_CTL: case CS35L35_CLASS_H_STATUS: case CS35L35_VPBR_CTL ... CS35L35_VPBR_MODE_VOL_CTL: case CS35L35_VPBR_ATTEN_STATUS: case CS35L35_SPKR_MON_CTL: case CS35L35_IMON_SCALE_CTL ... CS35L35_ZEROFILL_DEPTH_CTL: case CS35L35_MULT_DEV_SYNCH1 ... CS35L35_PROT_RELEASE_CTL: case CS35L35_DIAG_MODE_REG_LOCK ... CS35L35_DIAG_MODE_CTL_2: case CS35L35_INT_MASK_1 ... CS35L35_PLL_STATUS: case CS35L35_OTP_TRIM_STATUS: returntrue; default: returnfalse;
}
}
staticbool cs35l35_precious_register(struct device *dev, unsignedint reg)
{ switch (reg) { case CS35L35_INT_STATUS_1: case CS35L35_INT_STATUS_2: case CS35L35_INT_STATUS_3: case CS35L35_INT_STATUS_4: case CS35L35_PLL_STATUS: case CS35L35_OTP_TRIM_STATUS: returntrue; default: returnfalse;
}
}
staticint cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35)
{ int ret;
if (cs35l35->pdata.ext_bst) {
usleep_range(5000, 5500); return 0;
}
reinit_completion(&cs35l35->pdn_done);
ret = wait_for_completion_timeout(&cs35l35->pdn_done,
msecs_to_jiffies(100)); if (ret == 0) {
dev_err(cs35l35->dev, "PDN_DONE did not complete\n"); return -ETIMEDOUT;
}
return 0;
}
staticint cs35l35_sdin_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event)
{ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component); int ret = 0;
switch (event) { case SND_SOC_DAPM_PRE_PMU: if (cs35l35->pdata.bst_pdn_fet_on)
regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
CS35L35_PDN_BST_MASK,
0 << CS35L35_PDN_BST_FETON_SHIFT); else
regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
CS35L35_PDN_BST_MASK,
0 << CS35L35_PDN_BST_FETOFF_SHIFT); break; case SND_SOC_DAPM_POST_PMU:
usleep_range(5000, 5100); /* If in PDM mode we must use VP for Voltage control */ if (cs35l35->pdm_mode)
regmap_update_bits(cs35l35->regmap,
CS35L35_BST_CVTR_V_CTL,
CS35L35_BST_CTL_MASK,
0 << CS35L35_BST_CTL_SHIFT);
for (i = 0; i < 2; i++)
regmap_bulk_read(cs35l35->regmap, CS35L35_INT_STATUS_1,
®, ARRAY_SIZE(reg));
break; case SND_SOC_DAPM_PRE_PMD:
regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
CS35L35_AMP_MUTE_MASK,
1 << CS35L35_AMP_MUTE_SHIFT); if (cs35l35->pdata.bst_pdn_fet_on)
regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
CS35L35_PDN_BST_MASK,
1 << CS35L35_PDN_BST_FETON_SHIFT); else
regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
CS35L35_PDN_BST_MASK,
1 << CS35L35_PDN_BST_FETOFF_SHIFT); break; case SND_SOC_DAPM_POST_PMD:
usleep_range(5000, 5100); /* * If PDM mode we should switch back to pdata value * for Voltage control when we go down
*/ if (cs35l35->pdm_mode)
regmap_update_bits(cs35l35->regmap,
CS35L35_BST_CVTR_V_CTL,
CS35L35_BST_CTL_MASK,
cs35l35->pdata.bst_vctl
<< CS35L35_BST_CTL_SHIFT);
ret = regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL2,
CS35L35_CLK_CTL2_MASK, clk_ctl); if (ret != 0) {
dev_err(component->dev, "Failed to set port config %d\n", ret); return ret;
}
/* * Rev A0 Errata * When configured for the weak-drive detection path (CH_WKFET_DIS = 0) * the Class H algorithm does not enable weak-drive operation for * nonzero values of CH_WKFET_DELAY if SP_RATE = 01 or 10
*/
errata_chk = (clk_ctl & CS35L35_SP_RATE_MASK) >> CS35L35_SP_RATE_SHIFT;
if (classh->classh_wk_fet_disable == 0x00 &&
(errata_chk == 0x01 || errata_chk == 0x02)) {
ret = regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_FET_DRIVE_CTL,
CS35L35_CH_WKFET_DEL_MASK,
0 << CS35L35_CH_WKFET_DEL_SHIFT); if (ret != 0) {
dev_err(component->dev, "Failed to set fet config %d\n",
ret); return ret;
}
}
/* * You can pull more Monitor data from the SDOUT pin than going to SDIN * Just make sure your SCLK is fast enough to fill the frame
*/ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { switch (params_width(params)) { case 8:
audin_format = CS35L35_SDIN_DEPTH_8; break; case 16:
audin_format = CS35L35_SDIN_DEPTH_16; break; case 24:
audin_format = CS35L35_SDIN_DEPTH_24; break; default:
dev_err(component->dev, "Unsupported Width %d\n",
params_width(params)); return -EINVAL;
}
regmap_update_bits(cs35l35->regmap,
CS35L35_AUDIN_DEPTH_CTL,
CS35L35_AUDIN_DEPTH_MASK,
audin_format <<
CS35L35_AUDIN_DEPTH_SHIFT); if (cs35l35->pdata.stereo) {
regmap_update_bits(cs35l35->regmap,
CS35L35_AUDIN_DEPTH_CTL,
CS35L35_ADVIN_DEPTH_MASK,
audin_format <<
CS35L35_ADVIN_DEPTH_SHIFT);
}
}
if (cs35l35->i2s_mode) { /* We have to take the SCLK to derive num sclks * to configure the CLOCK_CTL3 register correctly
*/ if ((cs35l35->sclk / srate) % 4) {
dev_err(component->dev, "Unsupported sclk/fs ratio %d:%d\n",
cs35l35->sclk, srate); return -EINVAL;
}
sp_sclks = ((cs35l35->sclk / srate) / 4) - 1;
/* Only certain ratios supported when device is a clock consumer */ if (cs35l35->clock_consumer) { switch (sp_sclks) { case CS35L35_SP_SCLKS_32FS: case CS35L35_SP_SCLKS_48FS: case CS35L35_SP_SCLKS_64FS: break; default:
dev_err(component->dev, "ratio not supported\n"); return -EINVAL;
}
} else { /* Only certain ratios supported when device is a clock provider */ switch (sp_sclks) { case CS35L35_SP_SCLKS_32FS: case CS35L35_SP_SCLKS_64FS: break; default:
dev_err(component->dev, "ratio not supported\n"); return -EINVAL;
}
}
ret = regmap_update_bits(cs35l35->regmap,
CS35L35_CLK_CTL3,
CS35L35_SP_SCLKS_MASK, sp_sclks <<
CS35L35_SP_SCLKS_SHIFT); if (ret != 0) {
dev_err(component->dev, "Failed to set fsclk %d\n", ret); return ret;
}
}
staticint cs35l35_component_set_sysclk(struct snd_soc_component *component, int clk_id, int source, unsignedint freq, int dir)
{ struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component); int clksrc; int ret = 0;
switch (clk_id) { case 0:
clksrc = CS35L35_CLK_SOURCE_MCLK; break; case 1:
clksrc = CS35L35_CLK_SOURCE_SCLK; break; case 2:
clksrc = CS35L35_CLK_SOURCE_PDM; break; default:
dev_err(component->dev, "Invalid CLK Source\n"); return -EINVAL;
}
switch (freq) { case 5644800: case 6144000: case 11289600: case 12000000: case 12288000: case 13000000: case 22579200: case 24000000: case 24576000: case 26000000:
cs35l35->sysclk = freq; break; default:
dev_err(component->dev, "Invalid CLK Frequency Input : %d\n", freq); return -EINVAL;
}
ret = regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
CS35L35_CLK_SOURCE_MASK,
clksrc << CS35L35_CLK_SOURCE_SHIFT); if (ret != 0) {
dev_err(component->dev, "Failed to set sysclk %d\n", ret); return ret;
}
/* Set Platform Data */ if (cs35l35->pdata.bst_vctl)
regmap_update_bits(cs35l35->regmap, CS35L35_BST_CVTR_V_CTL,
CS35L35_BST_CTL_MASK,
cs35l35->pdata.bst_vctl);
if (cs35l35->pdata.bst_ipk)
regmap_update_bits(cs35l35->regmap, CS35L35_BST_PEAK_I,
CS35L35_BST_IPK_MASK,
cs35l35->pdata.bst_ipk <<
CS35L35_BST_IPK_SHIFT);
ret = cs35l35_boost_inductor(cs35l35, cs35l35->pdata.boost_ind); if (ret) return ret;
if (cs35l35->pdata.gain_zc)
regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
CS35L35_AMP_GAIN_ZC_MASK,
cs35l35->pdata.gain_zc <<
CS35L35_AMP_GAIN_ZC_SHIFT);
if (cs35l35->pdata.aud_channel)
regmap_update_bits(cs35l35->regmap,
CS35L35_AUDIN_RXLOC_CTL,
CS35L35_AUD_IN_LR_MASK,
cs35l35->pdata.aud_channel <<
CS35L35_AUD_IN_LR_SHIFT);
if (cs35l35->pdata.stereo) {
regmap_update_bits(cs35l35->regmap,
CS35L35_ADVIN_RXLOC_CTL,
CS35L35_ADV_IN_LR_MASK,
cs35l35->pdata.adv_channel <<
CS35L35_ADV_IN_LR_SHIFT); if (cs35l35->pdata.shared_bst)
regmap_update_bits(cs35l35->regmap, CS35L35_CLASS_H_CTL,
CS35L35_CH_STEREO_MASK,
1 << CS35L35_CH_STEREO_SHIFT);
ret = snd_soc_add_component_controls(component, cs35l35_adv_controls,
ARRAY_SIZE(cs35l35_adv_controls)); if (ret) return ret;
}
if (cs35l35->pdata.sp_drv_str)
regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
CS35L35_SP_DRV_MASK,
cs35l35->pdata.sp_drv_str <<
CS35L35_SP_DRV_SHIFT); if (cs35l35->pdata.sp_drv_unused)
regmap_update_bits(cs35l35->regmap, CS35L35_SP_FMT_CTL3,
CS35L35_SP_I2S_DRV_MASK,
cs35l35->pdata.sp_drv_unused <<
CS35L35_SP_I2S_DRV_SHIFT);
if (classh->classh_algo_enable) { if (classh->classh_bst_override)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_CTL,
CS35L35_CH_BST_OVR_MASK,
classh->classh_bst_override <<
CS35L35_CH_BST_OVR_SHIFT); if (classh->classh_bst_max_limit)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_CTL,
CS35L35_CH_BST_LIM_MASK,
classh->classh_bst_max_limit <<
CS35L35_CH_BST_LIM_SHIFT); if (classh->classh_mem_depth)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_CTL,
CS35L35_CH_MEM_DEPTH_MASK,
classh->classh_mem_depth <<
CS35L35_CH_MEM_DEPTH_SHIFT); if (classh->classh_headroom)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_HEADRM_CTL,
CS35L35_CH_HDRM_CTL_MASK,
classh->classh_headroom <<
CS35L35_CH_HDRM_CTL_SHIFT); if (classh->classh_release_rate)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_RELEASE_RATE,
CS35L35_CH_REL_RATE_MASK,
classh->classh_release_rate <<
CS35L35_CH_REL_RATE_SHIFT); if (classh->classh_wk_fet_disable)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_FET_DRIVE_CTL,
CS35L35_CH_WKFET_DIS_MASK,
classh->classh_wk_fet_disable <<
CS35L35_CH_WKFET_DIS_SHIFT); if (classh->classh_wk_fet_delay)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_FET_DRIVE_CTL,
CS35L35_CH_WKFET_DEL_MASK,
classh->classh_wk_fet_delay <<
CS35L35_CH_WKFET_DEL_SHIFT); if (classh->classh_wk_fet_thld)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_FET_DRIVE_CTL,
CS35L35_CH_WKFET_THLD_MASK,
classh->classh_wk_fet_thld <<
CS35L35_CH_WKFET_THLD_SHIFT); if (classh->classh_vpch_auto)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_VP_CTL,
CS35L35_CH_VP_AUTO_MASK,
classh->classh_vpch_auto <<
CS35L35_CH_VP_AUTO_SHIFT); if (classh->classh_vpch_rate)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_VP_CTL,
CS35L35_CH_VP_RATE_MASK,
classh->classh_vpch_rate <<
CS35L35_CH_VP_RATE_SHIFT); if (classh->classh_vpch_man)
regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_VP_CTL,
CS35L35_CH_VP_MAN_MASK,
classh->classh_vpch_man <<
CS35L35_CH_VP_MAN_SHIFT);
}
/* Check to see if unmasked bits are active */ if (!(sticky1 & ~mask1) && !(sticky2 & ~mask2) && !(sticky3 & ~mask3)
&& !(sticky4 & ~mask4)) return IRQ_NONE;
if (sticky2 & CS35L35_PDN_DONE)
complete(&cs35l35->pdn_done);
/* read the current values */
regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_1, ¤t1);
/* handle the interrupts */ if (sticky1 & CS35L35_CAL_ERR) {
dev_crit(cs35l35->dev, "Calibration Error\n");
/* error is no longer asserted; safe to reset */ if (!(current1 & CS35L35_CAL_ERR)) {
pr_debug("%s : Cal error release\n", __func__);
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_CAL_ERR_RLS, 0);
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_CAL_ERR_RLS,
CS35L35_CAL_ERR_RLS);
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_CAL_ERR_RLS, 0);
}
}
if (sticky1 & CS35L35_AMP_SHORT) {
dev_crit(cs35l35->dev, "AMP Short Error\n"); /* error is no longer asserted; safe to reset */ if (!(current1 & CS35L35_AMP_SHORT)) {
dev_dbg(cs35l35->dev, "Amp short error release\n");
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_SHORT_RLS, 0);
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_SHORT_RLS,
CS35L35_SHORT_RLS);
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_SHORT_RLS, 0);
}
}
if (sticky1 & CS35L35_OTW) {
dev_warn(cs35l35->dev, "Over temperature warning\n");
/* error is no longer asserted; safe to reset */ if (!(current1 & CS35L35_OTW)) {
dev_dbg(cs35l35->dev, "Over temperature warn release\n");
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_OTW_RLS, 0);
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_OTW_RLS,
CS35L35_OTW_RLS);
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_OTW_RLS, 0);
}
}
if (sticky1 & CS35L35_OTE) {
dev_crit(cs35l35->dev, "Over temperature error\n"); /* error is no longer asserted; safe to reset */ if (!(current1 & CS35L35_OTE)) {
dev_dbg(cs35l35->dev, "Over temperature error release\n");
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_OTE_RLS, 0);
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_OTE_RLS,
CS35L35_OTE_RLS);
regmap_update_bits(cs35l35->regmap,
CS35L35_PROT_RELEASE_CTL,
CS35L35_OTE_RLS, 0);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.