int adau17x1_add_widgets(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct adau *adau = snd_soc_codec_get_drvdata(codec); int ret; ret = snd_soc_add_codec_controls(codec, adau17x1_controls, ARRAY_SIZE(adau17x1_controls)); if (ret) return ret; ret = snd_soc_dapm_new_controls(dapm, adau17x1_dapm_widgets, ARRAY_SIZE(adau17x1_dapm_widgets)); if (ret) return ret; if (adau17x1_has_dsp(adau)) { ret = snd_soc_dapm_new_controls(dapm, adau17x1_dsp_dapm_widgets, ARRAY_SIZE(adau17x1_dsp_dapm_widgets)); if (ret) return ret; if (!adau->sigmadsp) return 0; ret = sigmadsp_attach(adau->sigmadsp, &codec->component); if (ret) { dev_err(codec->dev, "Failed to attach firmware: %d\n", ret); return ret; } } return 0; }
static int aic31xx_add_widgets(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); int ret = 0; if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) { ret = snd_soc_dapm_new_controls( dapm, aic311x_dapm_widgets, ARRAY_SIZE(aic311x_dapm_widgets)); if (ret) return ret; ret = snd_soc_dapm_add_routes(dapm, aic311x_audio_map, ARRAY_SIZE(aic311x_audio_map)); if (ret) return ret; } else { ret = snd_soc_dapm_new_controls( dapm, aic310x_dapm_widgets, ARRAY_SIZE(aic310x_dapm_widgets)); if (ret) return ret; ret = snd_soc_dapm_add_routes(dapm, aic310x_audio_map, ARRAY_SIZE(aic310x_audio_map)); if (ret) return ret; } return 0; }
static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dai->codec); struct adau *adau = snd_soc_codec_get_drvdata(dai->codec); switch (clk_id) { case ADAU17X1_CLK_SRC_MCLK: case ADAU17X1_CLK_SRC_PLL: break; default: return -EINVAL; } adau->sysclk = freq; if (adau->clk_src != clk_id) { if (clk_id == ADAU17X1_CLK_SRC_PLL) { snd_soc_dapm_add_routes(dapm, &adau17x1_dapm_pll_route, 1); } else { snd_soc_dapm_del_routes(dapm, &adau17x1_dapm_pll_route, 1); } } adau->clk_src = clk_id; return 0; }
static int txsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val = ucontrol->value.enumerated.item[0] << e->shift_l; unsigned int mask = 1 << e->shift_l; unsigned int txpwr; if (val != 0 && val != mask) return -EINVAL; snd_soc_dapm_mutex_lock(dapm); if (snd_soc_test_bits(codec, e->reg, mask, val)) { /* save the current power state of the transmitter */ txpwr = snd_soc_read(codec, WM8804_PWRDN) & 0x4; /* power down the transmitter */ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x4); /* set the tx source */ snd_soc_update_bits(codec, e->reg, mask, val); /* restore the transmitter's configuration */ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, txpwr); } snd_soc_dapm_mutex_unlock(dapm); return 0; }
static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct adau *adau = snd_soc_codec_get_drvdata(codec); struct adau1761_platform_data *pdata = codec->dev->platform_data; enum adau1761_output_mode mode; int ret; if (pdata) mode = pdata->headphone_mode; else mode = ADAU1761_OUTPUT_MODE_HEADPHONE; switch (mode) { case ADAU1761_OUTPUT_MODE_LINE: break; case ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS: regmap_update_bits(adau->regmap, ADAU1761_PLAY_MONO_OUTPUT_VOL, ADAU1761_PLAY_MONO_OUTPUT_VOL_MODE_HP | ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE, ADAU1761_PLAY_MONO_OUTPUT_VOL_MODE_HP | ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE); /* fallthrough */ case ADAU1761_OUTPUT_MODE_HEADPHONE: regmap_update_bits(adau->regmap, ADAU1761_PLAY_HP_RIGHT_VOL, ADAU1761_PLAY_HP_RIGHT_VOL_MODE_HP, ADAU1761_PLAY_HP_RIGHT_VOL_MODE_HP); break; default: return -EINVAL; } if (mode == ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS) { ret = snd_soc_dapm_new_controls(dapm, adau1761_capless_dapm_widgets, ARRAY_SIZE(adau1761_capless_dapm_widgets)); if (ret) return ret; ret = snd_soc_dapm_add_routes(dapm, adau1761_capless_dapm_routes, ARRAY_SIZE(adau1761_capless_dapm_routes)); } else { ret = snd_soc_add_codec_controls(codec, adau1761_mono_controls, ARRAY_SIZE(adau1761_mono_controls)); if (ret) return ret; ret = snd_soc_dapm_new_controls(dapm, adau1761_mono_dapm_widgets, ARRAY_SIZE(adau1761_mono_dapm_widgets)); if (ret) return ret; ret = snd_soc_dapm_add_routes(dapm, adau1761_mono_dapm_routes, ARRAY_SIZE(adau1761_mono_dapm_routes)); } return ret; }
static int ad193x_codec_probe(struct snd_soc_codec *codec) { struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); int num, ret; /* default setting for ad193x */ /* unmute dac channels */ regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0); /* de-emphasis: 48kHz, powedown dac */ regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A); /* dac in tdm mode */ regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x40); /* adc only */ if (ad193x_has_adc(ad193x)) { /* high-pass filter enable */ regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3); /* sata delay=1, adc aux mode */ regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43); } /* pll input: mclki/xi */ regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); /* adc only */ if (ad193x_has_adc(ad193x)) { /* add adc controls */ num = ARRAY_SIZE(ad193x_adc_snd_controls); ret = snd_soc_add_codec_controls(codec, ad193x_adc_snd_controls, num); if (ret) return ret; /* add adc widgets */ num = ARRAY_SIZE(ad193x_adc_widgets); ret = snd_soc_dapm_new_controls(dapm, ad193x_adc_widgets, num); if (ret) return ret; /* add adc routes */ num = ARRAY_SIZE(ad193x_adc_audio_paths); ret = snd_soc_dapm_add_routes(dapm, ad193x_adc_audio_paths, num); if (ret) return ret; } return 0; }
static int ssm2604_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); int ret; ret = snd_soc_dapm_new_controls(dapm, ssm2604_dapm_widgets, ARRAY_SIZE(ssm2604_dapm_widgets)); if (ret) return ret; return snd_soc_dapm_add_routes(dapm, ssm2604_routes, ARRAY_SIZE(ssm2604_routes)); }
static int wm8997_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); arizona_init_spk(codec); snd_soc_dapm_disable_pin(dapm, "HAPTICS"); priv->core.arizona->dapm = dapm; return 0; }
static int cs53l30_codec_probe(struct snd_soc_codec *codec) { struct cs53l30_private *priv = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); if (priv->use_sdout2) snd_soc_dapm_add_routes(dapm, cs53l30_dapm_routes_sdout2, ARRAY_SIZE(cs53l30_dapm_routes_sdout2)); else snd_soc_dapm_add_routes(dapm, cs53l30_dapm_routes_sdout1, ARRAY_SIZE(cs53l30_dapm_routes_sdout1)); return 0; }
static int cs35l33_set_hg_data(struct snd_soc_codec *codec, struct cs35l33_pdata *pdata) { struct cs35l33_hg *hg_config = &pdata->hg_config; struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); if (hg_config->enable_hg_algo) { regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL, CS35L33_MEM_DEPTH_MASK, hg_config->mem_depth << CS35L33_MEM_DEPTH_SHIFT); regmap_write(priv->regmap, CS35L33_HG_REL_RATE, hg_config->release_rate); regmap_update_bits(priv->regmap, CS35L33_HG_HEAD, CS35L33_HD_RM_MASK, hg_config->hd_rm << CS35L33_HD_RM_SHIFT); regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL, CS35L33_LDO_THLD_MASK, hg_config->ldo_thld << CS35L33_LDO_THLD_SHIFT); regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL, CS35L33_LDO_DISABLE_MASK, hg_config->ldo_path_disable << CS35L33_LDO_DISABLE_SHIFT); regmap_update_bits(priv->regmap, CS35L33_LDO_DEL, CS35L33_LDO_ENTRY_DELAY_MASK, hg_config->ldo_entry_delay << CS35L33_LDO_ENTRY_DELAY_SHIFT); if (hg_config->vp_hg_auto) { regmap_update_bits(priv->regmap, CS35L33_HG_EN, CS35L33_VP_HG_AUTO_MASK, CS35L33_VP_HG_AUTO_MASK); snd_soc_dapm_add_routes(dapm, cs35l33_vphg_auto_route, ARRAY_SIZE(cs35l33_vphg_auto_route)); } regmap_update_bits(priv->regmap, CS35L33_HG_EN, CS35L33_VP_HG_MASK, hg_config->vp_hg << CS35L33_VP_HG_SHIFT); regmap_update_bits(priv->regmap, CS35L33_LDO_DEL, CS35L33_VP_HG_RATE_MASK, hg_config->vp_hg_rate << CS35L33_VP_HG_RATE_SHIFT); regmap_update_bits(priv->regmap, CS35L33_LDO_DEL, CS35L33_VP_HG_VA_MASK, hg_config->vp_hg_va << CS35L33_VP_HG_VA_SHIFT); regmap_update_bits(priv->regmap, CS35L33_HG_EN, CS35L33_CLASS_HG_EN_MASK, CS35L33_CLASS_HG_EN_MASK); } return 0; }
/* * The MUX register for the Capture and Playback MUXs selects either DSP as * source/destination or one of the TDM slots. The TDM slot is selected via * snd_soc_dai_set_tdm_slot(), so we only expose whether to go to the DSP or * directly to the DAI interface with this control. */ static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct adau *adau = snd_soc_codec_get_drvdata(codec); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct snd_soc_dapm_update update; unsigned int stream = e->shift_l; unsigned int val, change; int reg; if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; switch (ucontrol->value.enumerated.item[0]) { case 0: val = 0; adau->dsp_bypass[stream] = false; break; default: val = (adau->tdm_slot[stream] * 2) + 1; adau->dsp_bypass[stream] = true; break; } if (stream == SNDRV_PCM_STREAM_PLAYBACK) reg = ADAU17X1_SERIAL_INPUT_ROUTE; else reg = ADAU17X1_SERIAL_OUTPUT_ROUTE; change = snd_soc_test_bits(codec, reg, 0xff, val); if (change) { update.kcontrol = kcontrol; update.mask = 0xff; update.reg = reg; update.val = val; snd_soc_dapm_mux_update_power(dapm, kcontrol, ucontrol->value.enumerated.item[0], e, &update); } return change; }
int adau17x1_add_routes(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct adau *adau = snd_soc_codec_get_drvdata(codec); int ret; ret = snd_soc_dapm_add_routes(dapm, adau17x1_dapm_routes, ARRAY_SIZE(adau17x1_dapm_routes)); if (ret) return ret; if (adau17x1_has_dsp(adau)) { ret = snd_soc_dapm_add_routes(dapm, adau17x1_dsp_dapm_routes, ARRAY_SIZE(adau17x1_dsp_dapm_routes)); } else { ret = snd_soc_dapm_add_routes(dapm, adau17x1_no_dsp_dapm_routes, ARRAY_SIZE(adau17x1_no_dsp_dapm_routes)); } return ret; }
static int adau1977_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); int ret; switch (adau1977->type) { case ADAU1977: ret = snd_soc_dapm_new_controls(dapm, adau1977_micbias_dapm_widgets, ARRAY_SIZE(adau1977_micbias_dapm_widgets)); if (ret < 0) return ret; break; default: break; } return 0; }
static int ssm2602_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); int ret; regmap_update_bits(ssm2602->regmap, SSM2602_LOUT1V, LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH); regmap_update_bits(ssm2602->regmap, SSM2602_ROUT1V, ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH); ret = snd_soc_add_codec_controls(codec, ssm2602_snd_controls, ARRAY_SIZE(ssm2602_snd_controls)); if (ret) return ret; ret = snd_soc_dapm_new_controls(dapm, ssm2602_dapm_widgets, ARRAY_SIZE(ssm2602_dapm_widgets)); if (ret) return ret; return snd_soc_dapm_add_routes(dapm, ssm2602_routes, ARRAY_SIZE(ssm2602_routes)); }
static int cs35l33_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { struct snd_soc_codec *codec = dai->codec; struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec); unsigned int reg, bit_pos, i; int slot, slot_num; if (slot_width != 8) return -EINVAL; /* scan rx_mask for aud slot */ slot = ffs(rx_mask) - 1; if (slot >= 0) { regmap_update_bits(priv->regmap, CS35L33_RX_AUD, CS35L33_X_LOC, slot); dev_dbg(codec->dev, "Audio starts from slots %d", slot); } /* * scan tx_mask: vmon(2 slots); imon (2 slots); * vpmon (1 slot) vbstmon (1 slot) */ slot = ffs(tx_mask) - 1; slot_num = 0; for (i = 0; i < 2 ; i++) { /* disable vpmon/vbstmon: enable later if set in tx_mask */ regmap_update_bits(priv->regmap, CS35L33_TX_VPMON + i, CS35L33_X_STATE | CS35L33_X_LOC, CS35L33_X_STATE | CS35L33_X_LOC); } /* disconnect {vp,vbst}_mon routes: eanble later if set in tx_mask*/ snd_soc_dapm_del_routes(dapm, cs35l33_vp_vbst_mon_route, ARRAY_SIZE(cs35l33_vp_vbst_mon_route)); while (slot >= 0) { /* configure VMON_TX_LOC */ if (slot_num == 0) { regmap_update_bits(priv->regmap, CS35L33_TX_VMON, CS35L33_X_STATE | CS35L33_X_LOC, slot); dev_dbg(codec->dev, "VMON enabled in slots %d-%d", slot, slot + 1); } /* configure IMON_TX_LOC */ if (slot_num == 3) { regmap_update_bits(priv->regmap, CS35L33_TX_IMON, CS35L33_X_STATE | CS35L33_X_LOC, slot); dev_dbg(codec->dev, "IMON enabled in slots %d-%d", slot, slot + 1); } /* configure VPMON_TX_LOC */ if (slot_num == 4) { regmap_update_bits(priv->regmap, CS35L33_TX_VPMON, CS35L33_X_STATE | CS35L33_X_LOC, slot); snd_soc_dapm_add_routes(dapm, &cs35l33_vp_vbst_mon_route[0], 2); dev_dbg(codec->dev, "VPMON enabled in slots %d", slot); } /* configure VBSTMON_TX_LOC */ if (slot_num == 5) { regmap_update_bits(priv->regmap, CS35L33_TX_VBSTMON, CS35L33_X_STATE | CS35L33_X_LOC, slot); snd_soc_dapm_add_routes(dapm, &cs35l33_vp_vbst_mon_route[2], 2); dev_dbg(codec->dev, "VBSTMON enabled in slots %d", slot); } /* Enable the relevant tx slot */ reg = CS35L33_TX_EN4 - (slot/8); bit_pos = slot - ((slot / 8) * (8)); regmap_update_bits(priv->regmap, reg, 1 << bit_pos, 1 << bit_pos); tx_mask &= ~(1 << slot); slot = ffs(tx_mask) - 1; slot_num++; } return 0; }
static int uda134x_soc_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); struct uda134x_platform_data *pd = uda134x->pd; const struct snd_soc_dapm_widget *widgets; unsigned num_widgets; int ret; printk(KERN_INFO "UDA134X SoC Audio Codec\n"); switch (pd->model) { case UDA134X_UDA1340: case UDA134X_UDA1341: case UDA134X_UDA1344: case UDA134X_UDA1345: break; default: printk(KERN_ERR "UDA134X SoC codec: " "unsupported model %d\n", pd->model); return -EINVAL; } if (pd->power) pd->power(1); uda134x_reset(codec); if (pd->model == UDA134X_UDA1341) { widgets = uda1341_dapm_widgets; num_widgets = ARRAY_SIZE(uda1341_dapm_widgets); } else { widgets = uda1340_dapm_widgets; num_widgets = ARRAY_SIZE(uda1340_dapm_widgets); } ret = snd_soc_dapm_new_controls(dapm, widgets, num_widgets); if (ret) { printk(KERN_ERR "%s failed to register dapm controls: %d", __func__, ret); return ret; } switch (pd->model) { case UDA134X_UDA1340: case UDA134X_UDA1344: ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls, ARRAY_SIZE(uda1340_snd_controls)); break; case UDA134X_UDA1341: ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls, ARRAY_SIZE(uda1341_snd_controls)); break; case UDA134X_UDA1345: ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls, ARRAY_SIZE(uda1345_snd_controls)); break; default: printk(KERN_ERR "%s unknown codec type: %d", __func__, pd->model); return -EINVAL; } if (ret < 0) { printk(KERN_ERR "UDA134X: failed to register controls\n"); return ret; } return 0; }
static int ad1836_probe(struct snd_soc_codec *codec) { struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); int num_dacs, num_adcs; int ret = 0; int i; num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2; /* default setting for ad1836 */ /* de-emphasis: 48kHz, power-on dac */ regmap_write(ad1836->regmap, AD1836_DAC_CTRL1, 0x300); /* unmute dac channels */ regmap_write(ad1836->regmap, AD1836_DAC_CTRL2, 0x0); /* high-pass filter enable, power-on adc */ regmap_write(ad1836->regmap, AD1836_ADC_CTRL1, 0x100); /* unmute adc channles, adc aux mode */ regmap_write(ad1836->regmap, AD1836_ADC_CTRL2, 0x180); /* volume */ for (i = 1; i <= num_dacs; ++i) { regmap_write(ad1836->regmap, AD1836_DAC_L_VOL(i), 0x3FF); regmap_write(ad1836->regmap, AD1836_DAC_R_VOL(i), 0x3FF); } if (ad1836->type == AD1836) { /* left/right diff:PGA/MUX */ regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x3A); ret = snd_soc_add_codec_controls(codec, ad1836_controls, ARRAY_SIZE(ad1836_controls)); if (ret) return ret; } else { regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x00); } ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2); if (ret) return ret; ret = snd_soc_add_codec_controls(codec, ad183x_adc_controls, num_adcs); if (ret) return ret; ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs); if (ret) return ret; ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs); if (ret) return ret; ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs); if (ret) return ret; ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs); if (ret) return ret; return ret; }
static int cs53l30_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct cs53l30_private *priv = snd_soc_codec_get_drvdata(codec); unsigned int reg; int i, inter_max_check, ret; switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: if (dapm->bias_level == SND_SOC_BIAS_STANDBY) regmap_update_bits(priv->regmap, CS53L30_PWRCTL, CS53L30_PDN_LP_MASK, 0); break; case SND_SOC_BIAS_STANDBY: if (dapm->bias_level == SND_SOC_BIAS_OFF) { ret = clk_prepare_enable(priv->mclk); if (ret) { dev_err(codec->dev, "failed to enable MCLK: %d\n", ret); return ret; } regmap_update_bits(priv->regmap, CS53L30_MCLKCTL, CS53L30_MCLK_DIS_MASK, 0); regmap_update_bits(priv->regmap, CS53L30_PWRCTL, CS53L30_PDN_ULP_MASK, 0); msleep(50); } else { regmap_update_bits(priv->regmap, CS53L30_PWRCTL, CS53L30_PDN_ULP_MASK, CS53L30_PDN_ULP); } break; case SND_SOC_BIAS_OFF: regmap_update_bits(priv->regmap, CS53L30_INT_MASK, CS53L30_PDN_DONE, 0); /* * If digital softramp is set, the amount of time required * for power down increases and depends on the digital * volume setting. */ /* Set the max possible time if digsft is set */ regmap_read(priv->regmap, CS53L30_SFT_RAMP, ®); if (reg & CS53L30_DIGSFT_MASK) inter_max_check = CS53L30_PDN_POLL_MAX; else inter_max_check = 10; regmap_update_bits(priv->regmap, CS53L30_PWRCTL, CS53L30_PDN_ULP_MASK, CS53L30_PDN_ULP); /* PDN_DONE will take a min of 20ms to be set.*/ msleep(20); /* Clr status */ regmap_read(priv->regmap, CS53L30_IS, ®); for (i = 0; i < inter_max_check; i++) { if (inter_max_check < 10) { usleep_range(1000, 1100); regmap_read(priv->regmap, CS53L30_IS, ®); if (reg & CS53L30_PDN_DONE) break; } else { usleep_range(10000, 10100); regmap_read(priv->regmap, CS53L30_IS, ®); if (reg & CS53L30_PDN_DONE) break; } } /* PDN_DONE is set. We now can disable the MCLK */ regmap_update_bits(priv->regmap, CS53L30_INT_MASK, CS53L30_PDN_DONE, CS53L30_PDN_DONE); regmap_update_bits(priv->regmap, CS53L30_MCLKCTL, CS53L30_MCLK_DIS_MASK, CS53L30_MCLK_DIS); clk_disable_unprepare(priv->mclk); break; } return 0; }
static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct adau1761_platform_data *pdata = codec->dev->platform_data; struct adau *adau = snd_soc_codec_get_drvdata(codec); enum adau1761_digmic_jackdet_pin_mode mode; unsigned int val = 0; int ret; if (pdata) mode = pdata->digmic_jackdetect_pin_mode; else mode = ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE; switch (mode) { case ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT: switch (pdata->jackdetect_debounce_time) { case ADAU1761_JACKDETECT_DEBOUNCE_5MS: case ADAU1761_JACKDETECT_DEBOUNCE_10MS: case ADAU1761_JACKDETECT_DEBOUNCE_20MS: case ADAU1761_JACKDETECT_DEBOUNCE_40MS: val |= pdata->jackdetect_debounce_time << 6; break; default: return -EINVAL; } if (pdata->jackdetect_active_low) val |= ADAU1761_DIGMIC_JACKDETECT_ACTIVE_LOW; ret = snd_soc_add_codec_controls(codec, adau1761_jack_detect_controls, ARRAY_SIZE(adau1761_jack_detect_controls)); if (ret) return ret; case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: /* fallthrough */ ret = snd_soc_dapm_add_routes(dapm, adau1761_no_dmic_routes, ARRAY_SIZE(adau1761_no_dmic_routes)); if (ret) return ret; break; case ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC: ret = snd_soc_dapm_new_controls(dapm, adau1761_dmic_widgets, ARRAY_SIZE(adau1761_dmic_widgets)); if (ret) return ret; ret = snd_soc_dapm_add_routes(dapm, adau1761_dmic_routes, ARRAY_SIZE(adau1761_dmic_routes)); if (ret) return ret; val |= ADAU1761_DIGMIC_JACKDETECT_DIGMIC; break; default: return -EINVAL; } regmap_write(adau->regmap, ADAU1761_DIGMIC_JACKDETECT, val); return 0; }
static int adau1761_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct adau1761_platform_data *pdata = codec->dev->platform_data; struct adau *adau = snd_soc_codec_get_drvdata(codec); int ret; ret = adau17x1_add_widgets(codec); if (ret < 0) return ret; if (pdata && pdata->input_differential) { regmap_update_bits(adau->regmap, ADAU1761_LEFT_DIFF_INPUT_VOL, ADAU1761_DIFF_INPUT_VOL_LDEN, ADAU1761_DIFF_INPUT_VOL_LDEN); regmap_update_bits(adau->regmap, ADAU1761_RIGHT_DIFF_INPUT_VOL, ADAU1761_DIFF_INPUT_VOL_LDEN, ADAU1761_DIFF_INPUT_VOL_LDEN); ret = snd_soc_add_codec_controls(codec, adau1761_differential_mode_controls, ARRAY_SIZE(adau1761_differential_mode_controls)); if (ret) return ret; } else { ret = snd_soc_add_codec_controls(codec, adau1761_single_mode_controls, ARRAY_SIZE(adau1761_single_mode_controls)); if (ret) return ret; } switch (adau1761_get_lineout_mode(codec)) { case ADAU1761_OUTPUT_MODE_LINE: break; case ADAU1761_OUTPUT_MODE_HEADPHONE: regmap_update_bits(adau->regmap, ADAU1761_PLAY_LINE_LEFT_VOL, ADAU1761_PLAY_LINE_LEFT_VOL_MODE_HP, ADAU1761_PLAY_LINE_LEFT_VOL_MODE_HP); regmap_update_bits(adau->regmap, ADAU1761_PLAY_LINE_RIGHT_VOL, ADAU1761_PLAY_LINE_RIGHT_VOL_MODE_HP, ADAU1761_PLAY_LINE_RIGHT_VOL_MODE_HP); break; default: return -EINVAL; } ret = adau1761_setup_headphone_mode(codec); if (ret) return ret; ret = adau1761_setup_digmic_jackdetect(codec); if (ret) return ret; if (adau->type == ADAU1761) { ret = snd_soc_dapm_new_controls(dapm, adau1761_dapm_widgets, ARRAY_SIZE(adau1761_dapm_widgets)); if (ret) return ret; ret = snd_soc_dapm_add_routes(dapm, adau1761_dapm_routes, ARRAY_SIZE(adau1761_dapm_routes)); if (ret) return ret; } ret = adau17x1_add_routes(codec); if (ret < 0) return ret; return 0; }