diff options
Diffstat (limited to 'sound/soc/codecs/wm8993.c')
| -rw-r--r-- | sound/soc/codecs/wm8993.c | 186 |
1 files changed, 45 insertions, 141 deletions
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index d256a934064..f825dc04ebe 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1,7 +1,7 @@ /* * wm8993.c -- WM8993 ALSA SoC audio driver * - * Copyright 2009, 2010 Wolfson Microelectronics plc + * Copyright 2009-12 Wolfson Microelectronics plc * * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> * @@ -218,7 +218,6 @@ struct wm8993_priv { unsigned int sysclk_rate; unsigned int fs; unsigned int bclk; - int class_w_users; unsigned int fll_fref; unsigned int fll_fout; int fll_src; @@ -647,8 +646,8 @@ static const char *dac_deemph_text[] = { "48kHz", }; -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text); +static SOC_ENUM_SINGLE_DECL(dac_deemph, + WM8993_DAC_CTRL, 4, dac_deemph_text); static const char *adc_hpf_text[] = { "Hi-Fi", @@ -657,16 +656,16 @@ static const char *adc_hpf_text[] = { "Voice 3", }; -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text); +static SOC_ENUM_SINGLE_DECL(adc_hpf, + WM8993_ADC_CTRL, 5, adc_hpf_text); static const char *drc_path_text[] = { "ADC", "DAC" }; -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text); +static SOC_ENUM_SINGLE_DECL(drc_path, + WM8993_DRC_CONTROL_1, 14, drc_path_text); static const char *drc_r0_text[] = { "1", @@ -677,8 +676,8 @@ static const char *drc_r0_text[] = { "0", }; -static const struct soc_enum drc_r0 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text); +static SOC_ENUM_SINGLE_DECL(drc_r0, + WM8993_DRC_CONTROL_3, 8, drc_r0_text); static const char *drc_r1_text[] = { "1", @@ -688,8 +687,8 @@ static const char *drc_r1_text[] = { "0", }; -static const struct soc_enum drc_r1 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text); +static SOC_ENUM_SINGLE_DECL(drc_r1, + WM8993_DRC_CONTROL_4, 13, drc_r1_text); static const char *drc_attack_text[] = { "Reserved", @@ -706,8 +705,8 @@ static const char *drc_attack_text[] = { "185.6ms", }; -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text); +static SOC_ENUM_SINGLE_DECL(drc_attack, + WM8993_DRC_CONTROL_2, 12, drc_attack_text); static const char *drc_decay_text[] = { "186ms", @@ -721,16 +720,16 @@ static const char *drc_decay_text[] = { "47.56ms", }; -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_decay, + WM8993_DRC_CONTROL_2, 8, drc_decay_text); static const char *drc_ff_text[] = { "5 samples", "9 samples", }; -static const struct soc_enum drc_ff = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text); +static SOC_ENUM_SINGLE_DECL(drc_ff, + WM8993_DRC_CONTROL_3, 7, drc_ff_text); static const char *drc_qr_rate_text[] = { "0.725ms", @@ -738,8 +737,8 @@ static const char *drc_qr_rate_text[] = { "5.8ms", }; -static const struct soc_enum drc_qr_rate = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_rate, + WM8993_DRC_CONTROL_3, 0, drc_qr_rate_text); static const char *drc_smooth_text[] = { "Low", @@ -747,8 +746,8 @@ static const char *drc_smooth_text[] = { "High", }; -static const struct soc_enum drc_smooth = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text); +static SOC_ENUM_SINGLE_DECL(drc_smooth, + WM8993_DRC_CONTROL_1, 4, drc_smooth_text); static const struct snd_kcontrol_new wm8993_snd_controls[] = { SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE, @@ -824,84 +823,6 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, return 0; } -/* - * When used with DAC outputs only the WM8993 charge pump supports - * operation in class W mode, providing very low power consumption - * when used with digital sources. Enable and disable this mode - * automatically depending on the mixer configuration. - * - * Currently the only supported paths are the direct DAC->headphone - * paths (which provide minimum power consumption anyway). - */ -static int class_w_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - int ret; - - /* Turn it off if we're using the main output mixer */ - if (ucontrol->value.integer.value[0] == 0) { - if (wm8993->class_w_users == 0) { - dev_dbg(codec->dev, "Disabling Class W\n"); - snd_soc_update_bits(codec, WM8993_CLASS_W_0, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V, - 0); - } - wm8993->class_w_users++; - wm8993->hubs_data.class_w = true; - } - - /* Implement the change */ - ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); - - /* Enable it if we're using the direct DAC path */ - if (ucontrol->value.integer.value[0] == 1) { - if (wm8993->class_w_users == 1) { - dev_dbg(codec->dev, "Enabling Class W\n"); - snd_soc_update_bits(codec, WM8993_CLASS_W_0, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V); - } - wm8993->class_w_users--; - wm8993->hubs_data.class_w = false; - } - - dev_dbg(codec->dev, "Indirect DAC use count now %d\n", - wm8993->class_w_users); - - return ret; -} - -#define SOC_DAPM_ENUM_W(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_enum_double, \ - .put = class_w_put, \ - .private_value = (unsigned long)&xenum } - -static const char *hp_mux_text[] = { - "Mixer", - "DAC", -}; - -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text); - -static const struct snd_kcontrol_new hpl_mux = - SOC_DAPM_ENUM_W("Left Headphone Mux", hpl_enum); - -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text); - -static const struct snd_kcontrol_new hpr_mux = - SOC_DAPM_ENUM_W("Right Headphone Mux", hpr_enum); - static const struct snd_kcontrol_new left_speaker_mixer[] = { SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 7, 1, 0), SOC_DAPM_SINGLE("IN1LP Switch", WM8993_SPEAKER_MIXER, 5, 1, 0), @@ -920,26 +841,26 @@ static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum aifoutl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutl_enum, + WM8993_AUDIO_INTERFACE_1, 15, aif_text); static const struct snd_kcontrol_new aifoutl_mux = SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); -static const struct soc_enum aifoutr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutr_enum, + WM8993_AUDIO_INTERFACE_1, 14, aif_text); static const struct snd_kcontrol_new aifoutr_mux = SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); -static const struct soc_enum aifinl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinl_enum, + WM8993_AUDIO_INTERFACE_2, 15, aif_text); static const struct snd_kcontrol_new aifinl_mux = SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); -static const struct soc_enum aifinr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinr_enum, + WM8993_AUDIO_INTERFACE_2, 14, aif_text); static const struct snd_kcontrol_new aifinr_mux = SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); @@ -948,14 +869,14 @@ static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum sidetonel_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetonel_enum, + WM8993_DIGITAL_SIDE_TONE, 2, sidetone_text); static const struct snd_kcontrol_new sidetonel_mux = SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum); -static const struct soc_enum sidetoner_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetoner_enum, + WM8993_DIGITAL_SIDE_TONE, 0, sidetone_text); static const struct snd_kcontrol_new sidetoner_mux = SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum); @@ -988,8 +909,8 @@ SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &sidetoner_mux), SND_SOC_DAPM_DAC("DACL", NULL, WM8993_POWER_MANAGEMENT_3, 1, 0), SND_SOC_DAPM_DAC("DACR", NULL, WM8993_POWER_MANAGEMENT_3, 0, 0), -SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), -SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), +SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpl_mux), +SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpr_mux), SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0, left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), @@ -1572,16 +1493,6 @@ static int wm8993_probe(struct snd_soc_codec *codec) wm8993->hubs_data.dcs_codes_r = -2; wm8993->hubs_data.series_startup = 1; - codec->control_data = wm8993->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* By default we're using the output mixers */ - wm8993->class_w_users = 2; - /* Latch volume update bits and default ZC on */ snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, WM8993_DAC_VU, WM8993_DAC_VU); @@ -1602,6 +1513,8 @@ static int wm8993_probe(struct snd_soc_codec *codec) wm8993->pdata.lineout2fb, wm8993->pdata.jd_scthr, wm8993->pdata.jd_thr, + wm8993->pdata.micbias1_delay, + wm8993->pdata.micbias2_delay, wm8993->pdata.micbias1_lvl, wm8993->pdata.micbias2_lvl); @@ -1639,10 +1552,7 @@ static int wm8993_probe(struct snd_soc_codec *codec) static int wm8993_remove(struct snd_soc_codec *codec) { - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); return 0; } @@ -1725,8 +1635,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8993 = { .set_bias_level = wm8993_set_bias_level, }; -static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int wm8993_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { struct wm8993_priv *wm8993; unsigned int reg; @@ -1740,7 +1650,7 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, wm8993->dev = &i2c->dev; init_completion(&wm8993->fll_lock); - wm8993->regmap = regmap_init_i2c(i2c, &wm8993_regmap); + wm8993->regmap = devm_regmap_init_i2c(i2c, &wm8993_regmap); if (IS_ERR(wm8993->regmap)) { ret = PTR_ERR(wm8993->regmap); dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); @@ -1752,18 +1662,18 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) wm8993->supplies[i].supply = wm8993_supply_names[i]; - ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies), + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies), wm8993->supplies); if (ret != 0) { dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); - goto err; + return ret; } ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); if (ret != 0) { dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; + return ret; } ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, ®); @@ -1822,23 +1732,17 @@ err_irq: free_irq(i2c->irq, wm8993); err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); -err: - regmap_exit(wm8993->regmap); return ret; } -static __devexit int wm8993_i2c_remove(struct i2c_client *i2c) +static int wm8993_i2c_remove(struct i2c_client *i2c) { struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c); snd_soc_unregister_codec(&i2c->dev); if (i2c->irq) free_irq(i2c->irq, wm8993); - regmap_exit(wm8993->regmap); regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); return 0; } @@ -1855,7 +1759,7 @@ static struct i2c_driver wm8993_i2c_driver = { .owner = THIS_MODULE, }, .probe = wm8993_i2c_probe, - .remove = __devexit_p(wm8993_i2c_remove), + .remove = wm8993_i2c_remove, .id_table = wm8993_i2c_id, }; |
