[alsa-devel] [PATCH] ALSA: hda/ca0132 - Delay HP amp turnon.
From: Chih-Chung Chang chihchung@chromium.org
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 --- sound/pci/hda/patch_ca0132.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 0792b57..12eb21a 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -741,6 +741,9 @@ struct ca0132_spec { long voicefx_val; long cur_mic_boost;
+ struct hda_codec *codec; + struct delayed_work unsol_hp_work; + #ifdef ENABLE_TUNING_CONTROLS long cur_ctl_vals[TUNING_CTLS_COUNT]; #endif @@ -3227,6 +3230,14 @@ exit: return err < 0 ? err : 0; }
+static void ca0132_unsol_hp_delayed(struct work_struct *work) +{ + struct ca0132_spec *spec = container_of( + to_delayed_work(work), struct ca0132_spec, unsol_hp_work); + ca0132_select_out(spec->codec); + snd_hda_jack_report_sync(spec->codec); +} + static void ca0132_set_dmic(struct hda_codec *codec, int enable); static int ca0132_mic_boost_set(struct hda_codec *codec, long val); 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)
static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) { - snd_printdd(KERN_INFO "ca0132_unsol_event: 0x%x\n", res); - + struct ca0132_spec *spec = codec->spec;
if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) { ca0132_process_dsp_response(codec); @@ -4412,8 +4422,13 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
switch (res) { case UNSOL_TAG_HP: - ca0132_select_out(codec); - snd_hda_jack_report_sync(codec); + /* Delay enabling the HP amp, to let the mic-detection + * state machine run. + */ + cancel_delayed_work_sync(&spec->unsol_hp_work); + queue_delayed_work(codec->bus->workq, + &spec->unsol_hp_work, + msecs_to_jiffies(500)); break; case UNSOL_TAG_AMIC1: ca0132_select_mic(codec); @@ -4588,6 +4603,7 @@ static void ca0132_free(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec;
+ cancel_delayed_work_sync(&spec->unsol_hp_work); snd_hda_power_up(codec); snd_hda_sequence_write(codec, spec->base_exit_verbs); ca0132_exit_chip(codec); @@ -4653,6 +4669,7 @@ static int patch_ca0132(struct hda_codec *codec) if (!spec) return -ENOMEM; codec->spec = spec; + spec->codec = codec;
spec->num_mixers = 1; spec->mixers[0] = ca0132_mixer; @@ -4663,6 +4680,8 @@ static int patch_ca0132(struct hda_codec *codec) spec->init_verbs[1] = ca0132_init_verbs1; spec->num_init_verbs = 2;
+ INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed); + ca0132_init_chip(codec);
ca0132_config(codec);
At Mon, 25 Mar 2013 10:39:23 -0700, Dylan Reid wrote:
From: Chih-Chung Chang chihchung@chromium.org
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
Thanks, applied.
Takashi
sound/pci/hda/patch_ca0132.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 0792b57..12eb21a 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -741,6 +741,9 @@ struct ca0132_spec { long voicefx_val; long cur_mic_boost;
- struct hda_codec *codec;
- struct delayed_work unsol_hp_work;
#ifdef ENABLE_TUNING_CONTROLS long cur_ctl_vals[TUNING_CTLS_COUNT]; #endif @@ -3227,6 +3230,14 @@ exit: return err < 0 ? err : 0; }
+static void ca0132_unsol_hp_delayed(struct work_struct *work) +{
- struct ca0132_spec *spec = container_of(
to_delayed_work(work), struct ca0132_spec, unsol_hp_work);
- ca0132_select_out(spec->codec);
- snd_hda_jack_report_sync(spec->codec);
+}
static void ca0132_set_dmic(struct hda_codec *codec, int enable); static int ca0132_mic_boost_set(struct hda_codec *codec, long val); 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)
static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) {
- snd_printdd(KERN_INFO "ca0132_unsol_event: 0x%x\n", res);
struct ca0132_spec *spec = codec->spec;
if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) { ca0132_process_dsp_response(codec);
@@ -4412,8 +4422,13 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
switch (res) { case UNSOL_TAG_HP:
ca0132_select_out(codec);
snd_hda_jack_report_sync(codec);
/* Delay enabling the HP amp, to let the mic-detection
* state machine run.
*/
cancel_delayed_work_sync(&spec->unsol_hp_work);
queue_delayed_work(codec->bus->workq,
&spec->unsol_hp_work,
case UNSOL_TAG_AMIC1: ca0132_select_mic(codec);msecs_to_jiffies(500)); break;
@@ -4588,6 +4603,7 @@ static void ca0132_free(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec;
- cancel_delayed_work_sync(&spec->unsol_hp_work); snd_hda_power_up(codec); snd_hda_sequence_write(codec, spec->base_exit_verbs); ca0132_exit_chip(codec);
@@ -4653,6 +4669,7 @@ static int patch_ca0132(struct hda_codec *codec) if (!spec) return -ENOMEM; codec->spec = spec;
spec->codec = codec;
spec->num_mixers = 1; spec->mixers[0] = ca0132_mixer;
@@ -4663,6 +4680,8 @@ static int patch_ca0132(struct hda_codec *codec) spec->init_verbs[1] = ca0132_init_verbs1; spec->num_init_verbs = 2;
INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed);
ca0132_init_chip(codec);
ca0132_config(codec);
-- 1.8.1.3.605.g02339dd
participants (2)
-
Dylan Reid
-
Takashi Iwai