summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorScott Peterson <speterson@nvidia.com>2013-04-26 13:07:32 -0700
committerRiham Haidar <rhaidar@nvidia.com>2013-05-06 12:06:23 -0700
commitafebf28f22a86468f1d96e380aa86dbfb36c08a1 (patch)
treefaaeb6676de53717c3abaf407bf4b295b6a1ce7d /sound
parente20a0759c2094941186aa79cd2ea61fc5f254b75 (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.h1
-rw-r--r--sound/soc/tegra/tegra_rt5640.c70
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;