diff options
author | Scott Peterson <speterson@nvidia.com> | 2013-04-26 13:07:32 -0700 |
---|---|---|
committer | Riham Haidar <rhaidar@nvidia.com> | 2013-05-06 12:06:23 -0700 |
commit | afebf28f22a86468f1d96e380aa86dbfb36c08a1 (patch) | |
tree | faaeb6676de53717c3abaf407bf4b295b6a1ce7d /sound | |
parent | e20a0759c2094941186aa79cd2ea61fc5f254b75 (diff) |
arm: Reduce tfa9887 speaker pops
Reduce speakers pops when enabling/disabling
the NXP speaker protection device. Add an alsa
mixer control to mute the device from the audio
HAL prior to disabling the device.
Bug 1268519
Change-Id: I2d16c0443bd833b65d07ec2fabc36102443cc8ad
Signed-off-by: Scott Peterson <speterson@nvidia.com>
Reviewed-on: http://git-master/r/224002
Reviewed-by: Vinod Subbarayalu <vsubbarayalu@nvidia.com>
GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/tegra/tegra_asoc_utils.h | 1 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_rt5640.c | 70 |
2 files changed, 62 insertions, 9 deletions
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h index cee38064ddcb..dfc60b557807 100644 --- a/sound/soc/tegra/tegra_asoc_utils.h +++ b/sound/soc/tegra/tegra_asoc_utils.h @@ -49,6 +49,7 @@ struct tegra_asoc_utils_data { int avp_device_id; unsigned int avp_dma_addr; int headset_plug_state; + int tfa9887_powerdown; }; int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index a66b4c6a1532..717ff11960a2 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c @@ -80,6 +80,8 @@ struct tegra_rt5640 { #endif enum snd_soc_bias_level bias_level; volatile int clock_enabled; + int speaker_sel; + int tfa9887_on; }; void tegra_asoc_enable_clocks(void); @@ -427,6 +429,7 @@ static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w, struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); struct tegra_asoc_platform_data *pdata = machine->pdata; + machine->speaker_sel = 1; if (machine->spk_reg) { if (SND_SOC_DAPM_EVENT_ON(event)) { regulator_enable(machine->spk_reg); @@ -435,20 +438,20 @@ static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w, regulator_disable(machine->spk_reg); } } + if(machine_is_roth()) { if (SND_SOC_DAPM_EVENT_ON(event)) { - if(i2s_tfa) { + if(i2s_tfa && !machine->tfa9887_on) { if (codec_rt) snd_soc_update_bits(codec_rt, RT5640_PWR_DIG1, 0x0001, 0x0000); tegra_asoc_enable_clocks(); Tfa9887_Powerdown(0); tegra_asoc_disable_clocks(); + machine->tfa9887_on = 1; } } - else { - Tfa9887_Powerdown(1); - } } + if (!(machine->gpio_requested & GPIO_SPKR_EN)) return 0; @@ -466,6 +469,7 @@ static int tegra_rt5640_event_hp(struct snd_soc_dapm_widget *w, struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); struct tegra_asoc_platform_data *pdata = machine->pdata; + machine->speaker_sel = 0; if (!(machine->gpio_requested & GPIO_HP_MUTE)) return 0; @@ -531,9 +535,6 @@ static const struct snd_soc_dapm_route cardhu_audio_map[] = { {"Int Spk", NULL, "SPOLP"}, {"Int Spk", NULL, "SPOLN"}, {"micbias1", NULL, "Mic Jack"}, - {"IN1P", NULL, "micbias1"}, - {"IN1N", NULL, "micbias1"}, - {"micbias1", NULL, "Int Mic"}, {"IN2P", NULL, "micbias1"}, {"DMIC L1", NULL, "Int Mic"}, {"DMIC L2", NULL, "Int Mic"}, @@ -548,6 +549,36 @@ static const struct snd_kcontrol_new cardhu_controls[] = { SOC_DAPM_PIN_SWITCH("Int Mic"), }; +static int tegra_set_tfa9887_powerdown(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = data->card; + struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); + + data->tfa9887_powerdown = ucontrol->value.integer.value[0]; + //printk("tegra_set_tfa9887_powerdown powerdown=%d ref=%d\n",data->tfa9887_powerdown,i2s_tfa->playback_ref_count); + if (i2s_tfa->playback_ref_count <= 1) { + Tfa9887_Powerdown(data->tfa9887_powerdown); + machine->tfa9887_on = !data->tfa9887_powerdown; + } + return 1; +} + +static int tegra_get_tfa9887_powerdown(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = data->tfa9887_powerdown; + + return 0; +} + +struct snd_kcontrol_new tegra_tfa9887_controls = + SOC_SINGLE_EXT("tfa9887 powerdown", 0, 0, 1, \ + 0, tegra_get_tfa9887_powerdown, tegra_set_tfa9887_powerdown); + + static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; @@ -627,6 +658,13 @@ static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd) if (ret < 0) return ret; + ret = snd_ctl_add(machine->util_data.card->snd_card, + snd_ctl_new1(&tegra_tfa9887_controls, &machine->util_data)); + if (ret < 0) { + dev_err(card->dev, "Can't add tfa9887 alsa control"); + return ret; + } + /* FIXME: Calculate automatically based on DAPM routes? */ snd_soc_dapm_nc_pin(dapm, "LOUTL"); snd_soc_dapm_nc_pin(dapm, "LOUTR"); @@ -685,7 +723,7 @@ static int tegra_rt5640_set_bias_level(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) { struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); - + //printk("tegra_rt5640_set_bias_level level =%d spkr_sel=%d\n",level,machine->speaker_sel); if (machine->bias_level == SND_SOC_BIAS_OFF && level != SND_SOC_BIAS_OFF && (!machine->clock_enabled)) { machine->clock_enabled = 1; @@ -693,6 +731,20 @@ static int tegra_rt5640_set_bias_level(struct snd_soc_card *card, machine->bias_level = level; } + if(machine_is_roth()) { + if (machine->speaker_sel && + !machine->tfa9887_on && + level > machine->bias_level) { + if(i2s_tfa) { + if (codec_rt) + snd_soc_update_bits(codec_rt, RT5640_PWR_DIG1, 0x0001, 0x0000); + tegra_asoc_enable_clocks(); + Tfa9887_Powerdown(0); + tegra_asoc_disable_clocks(); + machine->tfa9887_on = 1; + } + } + } return 0; } @@ -700,7 +752,7 @@ static int tegra_rt5640_set_bias_level_post(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) { struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); - + //printk("tegra_rt5640_set_bias_level_post level =%d\n",level); if (machine->bias_level != SND_SOC_BIAS_OFF && level == SND_SOC_BIAS_OFF && machine->clock_enabled) { machine->clock_enabled = 0; |