diff options
author | Chih-Chung Chang <chihchung@chromium.org> | 2013-03-25 13:39:23 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-04-02 05:28:39 -0400 |
commit | 993884f6a26c6547fa3875f9d3fabdc4250d8da6 (patch) | |
tree | 8852dd8068a9dd332fe435fedee1891f60dca17d /sound/pci/hda | |
parent | b8e63df919d75ef4ecafd66b5123a798b18cc0e7 (diff) |
ALSA: hda/ca0132 - Delay HP amp turnon.
Turing on the headphone amp interferes with the impedance measurement
used to detect a TRRS style headset microphone. Delay the HP turn on
until 500ms after the jack is detected, allowing the mic detection
state machine to run to completion.
Signed-off-by: Chih-Chung Chang <chihchung@chromium.org>
Signed-off-by: Dylan Reid <dgreid@chromium.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 0792b5725f9c..12eb21aff557 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -741,6 +741,9 @@ struct ca0132_spec { | |||
741 | long voicefx_val; | 741 | long voicefx_val; |
742 | long cur_mic_boost; | 742 | long cur_mic_boost; |
743 | 743 | ||
744 | struct hda_codec *codec; | ||
745 | struct delayed_work unsol_hp_work; | ||
746 | |||
744 | #ifdef ENABLE_TUNING_CONTROLS | 747 | #ifdef ENABLE_TUNING_CONTROLS |
745 | long cur_ctl_vals[TUNING_CTLS_COUNT]; | 748 | long cur_ctl_vals[TUNING_CTLS_COUNT]; |
746 | #endif | 749 | #endif |
@@ -3227,6 +3230,14 @@ exit: | |||
3227 | return err < 0 ? err : 0; | 3230 | return err < 0 ? err : 0; |
3228 | } | 3231 | } |
3229 | 3232 | ||
3233 | static void ca0132_unsol_hp_delayed(struct work_struct *work) | ||
3234 | { | ||
3235 | struct ca0132_spec *spec = container_of( | ||
3236 | to_delayed_work(work), struct ca0132_spec, unsol_hp_work); | ||
3237 | ca0132_select_out(spec->codec); | ||
3238 | snd_hda_jack_report_sync(spec->codec); | ||
3239 | } | ||
3240 | |||
3230 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); | 3241 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); |
3231 | static int ca0132_mic_boost_set(struct hda_codec *codec, long val); | 3242 | static int ca0132_mic_boost_set(struct hda_codec *codec, long val); |
3232 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val); | 3243 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val); |
@@ -4399,8 +4410,7 @@ static void ca0132_process_dsp_response(struct hda_codec *codec) | |||
4399 | 4410 | ||
4400 | static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) | 4411 | static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) |
4401 | { | 4412 | { |
4402 | snd_printdd(KERN_INFO "ca0132_unsol_event: 0x%x\n", res); | 4413 | struct ca0132_spec *spec = codec->spec; |
4403 | |||
4404 | 4414 | ||
4405 | if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) { | 4415 | if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) { |
4406 | ca0132_process_dsp_response(codec); | 4416 | ca0132_process_dsp_response(codec); |
@@ -4412,8 +4422,13 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4412 | 4422 | ||
4413 | switch (res) { | 4423 | switch (res) { |
4414 | case UNSOL_TAG_HP: | 4424 | case UNSOL_TAG_HP: |
4415 | ca0132_select_out(codec); | 4425 | /* Delay enabling the HP amp, to let the mic-detection |
4416 | snd_hda_jack_report_sync(codec); | 4426 | * state machine run. |
4427 | */ | ||
4428 | cancel_delayed_work_sync(&spec->unsol_hp_work); | ||
4429 | queue_delayed_work(codec->bus->workq, | ||
4430 | &spec->unsol_hp_work, | ||
4431 | msecs_to_jiffies(500)); | ||
4417 | break; | 4432 | break; |
4418 | case UNSOL_TAG_AMIC1: | 4433 | case UNSOL_TAG_AMIC1: |
4419 | ca0132_select_mic(codec); | 4434 | ca0132_select_mic(codec); |
@@ -4588,6 +4603,7 @@ static void ca0132_free(struct hda_codec *codec) | |||
4588 | { | 4603 | { |
4589 | struct ca0132_spec *spec = codec->spec; | 4604 | struct ca0132_spec *spec = codec->spec; |
4590 | 4605 | ||
4606 | cancel_delayed_work_sync(&spec->unsol_hp_work); | ||
4591 | snd_hda_power_up(codec); | 4607 | snd_hda_power_up(codec); |
4592 | snd_hda_sequence_write(codec, spec->base_exit_verbs); | 4608 | snd_hda_sequence_write(codec, spec->base_exit_verbs); |
4593 | ca0132_exit_chip(codec); | 4609 | ca0132_exit_chip(codec); |
@@ -4653,6 +4669,7 @@ static int patch_ca0132(struct hda_codec *codec) | |||
4653 | if (!spec) | 4669 | if (!spec) |
4654 | return -ENOMEM; | 4670 | return -ENOMEM; |
4655 | codec->spec = spec; | 4671 | codec->spec = spec; |
4672 | spec->codec = codec; | ||
4656 | 4673 | ||
4657 | spec->num_mixers = 1; | 4674 | spec->num_mixers = 1; |
4658 | spec->mixers[0] = ca0132_mixer; | 4675 | spec->mixers[0] = ca0132_mixer; |
@@ -4663,6 +4680,8 @@ static int patch_ca0132(struct hda_codec *codec) | |||
4663 | spec->init_verbs[1] = ca0132_init_verbs1; | 4680 | spec->init_verbs[1] = ca0132_init_verbs1; |
4664 | spec->num_init_verbs = 2; | 4681 | spec->num_init_verbs = 2; |
4665 | 4682 | ||
4683 | INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed); | ||
4684 | |||
4666 | ca0132_init_chip(codec); | 4685 | ca0132_init_chip(codec); |
4667 | 4686 | ||
4668 | ca0132_config(codec); | 4687 | ca0132_config(codec); |