diff options
author | Ola Lilja <ola.o.lilja@stericsson.com> | 2011-06-29 10:52:10 +0200 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2011-12-06 10:59:42 +0100 |
commit | c7200962b815c957b244ea5358a7c48cd4b79055 (patch) | |
tree | 2a6efc3e2013e774b36c74dcbfb2ae54f724fd9c /sound | |
parent | 161e60e006c7c9c281adc9810db493fbc600ce7f (diff) |
Ux500 ASoC: Proper handling of vibra output driver
The Class-D amplifier used for vibra is now turned of
to same power when not needed. A new control to handle
this is introduced.
ST-Ericsson Linux next: NA
ST-Ericsson ID: 345554
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: I28d4daf28b3ff33b9cc2665e8a156c6f56175b66
Signed-off-by: Ola Lilja <ola.o.lilja@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/26046
Reviewed-by: QATEST
Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30799
Reviewed-by: Roger NILSSON1 <roger.xr.nilsson@stericsson.com>
Tested-by: Roger NILSSON1 <roger.xr.nilsson@stericsson.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/ab8500_audio.c | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/sound/soc/codecs/ab8500_audio.c b/sound/soc/codecs/ab8500_audio.c index d2de1822b82..d9668723e53 100644 --- a/sound/soc/codecs/ab8500_audio.c +++ b/sound/soc/codecs/ab8500_audio.c @@ -280,6 +280,9 @@ static inline int ab8500_codec_update_reg_audio(struct snd_soc_codec *codec, return ab8500_codec_write_reg_audio(codec, reg, new); } +static const char *enum_ena_dis[] = {"Enabled", "Disabled"}; +static const char *enum_dis_ena[] = {"Disabled", "Enabled"}; + /* Whether widget's register definitions should be inverted or not */ enum control_inversion { NORMAL = 0, @@ -316,6 +319,16 @@ static const struct snd_kcontrol_new dapm_ihfr_mute[] = { REG_DIGMULTCONF2_DATOHFREN, 1, NORMAL), }; +/* Vibra 1 switch control */ +static const struct soc_enum enum_vibra1 = SOC_ENUM_SINGLE(0, 0, 2, enum_dis_ena); +static const struct snd_kcontrol_new dapm_vibra1_mux = + SOC_DAPM_ENUM_VIRT("Vibra 1", enum_vibra1); + +/* Vibra 2 switch control */ +static const struct soc_enum enum_vibra2 = SOC_ENUM_SINGLE(0, 0, 2, enum_dis_ena); +static const struct snd_kcontrol_new dapm_vibra2_mux = + SOC_DAPM_ENUM_VIRT("Vibra 2", enum_vibra2); + /* Mic 1 mute control */ static const struct snd_kcontrol_new dapm_mic1_mute[] = { SOC_DAPM_SINGLE("Capture Switch", REG_ANACONF2, @@ -490,10 +503,8 @@ static const struct snd_kcontrol_new dapm_anc_in_select[] = { }; /* ANC enable control */ -static const char *enum_anc_dis_ena[] = {"Disabled", "Enabled"}; - static SOC_ENUM_SINGLE_DECL(dapm_enum_anc_enable, REG_ANCCONF1, - REG_ANCCONF1_ENANC, enum_anc_dis_ena); + REG_ANCCONF1_ENANC, enum_dis_ena); static const struct snd_kcontrol_new dapm_anc_enable[] = { SOC_DAPM_ENUM("ANC", dapm_enum_anc_enable), @@ -633,7 +644,8 @@ static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("DA_IN5", "ab8500_0p", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("DA_IN6", "ab8500_0p", 0, SND_SOC_NOPM, 0, 0), - + SND_SOC_DAPM_MUX("Vibra 1", SND_SOC_NOPM, 0, 0, &dapm_vibra1_mux), + SND_SOC_DAPM_MUX("Vibra 2", SND_SOC_NOPM, 0, 0, &dapm_vibra2_mux), SND_SOC_DAPM_MIXER("DA5 Channel Gain", REG_DAPATHENA, REG_DAPATHENA_ENDA5, 0, NULL, 0), SND_SOC_DAPM_MIXER("DA6 Channel Gain", REG_DAPATHENA, @@ -874,8 +886,11 @@ static const struct snd_soc_dapm_route intercon[] = { /* Vibrator path */ - {"DA5 Channel Gain", NULL, "DA_IN5"}, - {"DA6 Channel Gain", NULL, "DA_IN6"}, + {"Vibra 1", "Enabled", "DA_IN5"}, + {"Vibra 2", "Enabled", "DA_IN6"}, + + {"DA5 Channel Gain", NULL, "Vibra 1"}, + {"DA6 Channel Gain", NULL, "Vibra 2"}, {"VIB1 DAC", NULL, "DA5 Channel Gain"}, {"VIB2 DAC", NULL, "DA6 Channel Gain"}, @@ -1059,9 +1074,6 @@ static DECLARE_TLV_DB_SCALE(lin_gain_tlv, -1000, 200, 0); /* from -36 to 0 dB in 2 dB steps (mute instead of -38 dB) */ static DECLARE_TLV_DB_SCALE(lin2hs_gain_tlv, -3800, 200, 1); -static const char *enum_ena_dis[] = {"Enabled", "Disabled"}; -static const char *enum_dis_ena[] = {"Disabled", "Enabled"}; - static SOC_ENUM_SINGLE_DECL(soc_enum_hshpen, REG_ANACONF1, REG_ANACONF1_HSHPEN, enum_dis_ena); static SOC_ENUM_SINGLE_DECL(soc_enum_hslowpow, @@ -1855,7 +1867,69 @@ void ab8500_audio_power_control(bool power_on) } } -/* Extended interface for codec-driver */ +void ab8500_audio_pwm_vibra(unsigned char speed_left_pos, + unsigned char speed_left_neg, + unsigned char speed_right_pos, + unsigned char speed_right_neg) +{ + unsigned int clear_mask, set_mask; + bool vibra_on; + + if (ab8500_codec == NULL) { + pr_err("%s: ERROR: AB8500 ASoC-driver not yet probed!\n", __func__); + return; + } + + vibra_on = speed_left_pos | speed_left_neg | speed_right_pos | speed_right_neg; + if (!vibra_on) { + speed_left_pos = 0; + speed_left_neg = 0; + speed_right_pos = 0; + speed_right_neg = 0; + } + + pr_debug("%s: PWM-vibra (%d, %d, %d, %d).\n", + __func__, + speed_left_pos, + speed_left_neg, + speed_right_pos, + speed_right_neg); + + set_mask = BMASK(REG_PWMGENCONF1_PWMTOVIB1) | + BMASK(REG_PWMGENCONF1_PWMTOVIB2) | + BMASK(REG_PWMGENCONF1_PWM1CTRL) | + BMASK(REG_PWMGENCONF1_PWM2CTRL) | + BMASK(REG_PWMGENCONF1_PWM1NCTRL) | + BMASK(REG_PWMGENCONF1_PWM1PCTRL) | + BMASK(REG_PWMGENCONF1_PWM2NCTRL) | + BMASK(REG_PWMGENCONF1_PWM2PCTRL); + ab8500_codec_update_reg_audio(ab8500_codec, REG_PWMGENCONF1, 0x00, set_mask); + + if (speed_left_pos > REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX) + speed_left_pos = REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX; + ab8500_codec_update_reg_audio(ab8500_codec, REG_PWMGENCONF3, REG_MASK_ALL, speed_left_pos); + + if (speed_left_neg > REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX) + speed_left_neg = REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX; + ab8500_codec_update_reg_audio(ab8500_codec, REG_PWMGENCONF2, REG_MASK_ALL, speed_left_neg); + + if (speed_right_pos > REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX) + speed_right_pos = REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX; + ab8500_codec_update_reg_audio(ab8500_codec, REG_PWMGENCONF5, REG_MASK_ALL, speed_right_pos); + + if (speed_right_neg > REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX) + speed_right_neg = REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX; + ab8500_codec_update_reg_audio(ab8500_codec, REG_PWMGENCONF4, REG_MASK_ALL, speed_right_neg); + + if (vibra_on) { + clear_mask = 0; + set_mask = BMASK(REG_ANACONF4_ENVIB1) | BMASK(REG_ANACONF4_ENVIB2); + } else { + clear_mask = BMASK(REG_ANACONF4_ENVIB1) | BMASK(REG_ANACONF4_ENVIB2); + set_mask = 0; + }; + ab8500_codec_update_reg_audio(ab8500_codec, REG_ANACONF4, clear_mask, set_mask); +} int ab8500_audio_set_word_length(struct snd_soc_dai *dai, unsigned int wl) { |