diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-09-11 09:53:26 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-09-16 11:25:02 -0400 |
commit | f8fb117034847634bff8f02632151f7535981fa1 (patch) | |
tree | 286e991990ab7c832825a0d6cea9e72d63b1e132 | |
parent | 7c3008c47b405420bf2b24fb5a21af3df5b5c323 (diff) |
ALSA: hda - Use standard hda_jack infrastructure for CA0132 driver
For its headphone, mic and DSP responses, we can use the standard
hda_jack infrastructure in CA0132 driver, too. The only point to
handle carefully is the delayed headphone jack handling. It tries to
react after a certain delay. Here we use the existing block_report
flag in hda_jack_tbl (that was implemented for HDMI).
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 76 |
1 files changed, 34 insertions, 42 deletions
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 39fae52258f0..4f7ffa8c4a0d 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -3224,8 +3224,14 @@ static void ca0132_unsol_hp_delayed(struct work_struct *work) | |||
3224 | { | 3224 | { |
3225 | struct ca0132_spec *spec = container_of( | 3225 | struct ca0132_spec *spec = container_of( |
3226 | to_delayed_work(work), struct ca0132_spec, unsol_hp_work); | 3226 | to_delayed_work(work), struct ca0132_spec, unsol_hp_work); |
3227 | struct hda_jack_tbl *jack; | ||
3228 | |||
3227 | ca0132_select_out(spec->codec); | 3229 | ca0132_select_out(spec->codec); |
3228 | snd_hda_jack_report_sync(spec->codec); | 3230 | jack = snd_hda_jack_tbl_get(spec->codec, UNSOL_TAG_HP); |
3231 | if (jack) { | ||
3232 | jack->block_report = 0; | ||
3233 | snd_hda_jack_report_sync(spec->codec); | ||
3234 | } | ||
3229 | } | 3235 | } |
3230 | 3236 | ||
3231 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); | 3237 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); |
@@ -4114,12 +4120,6 @@ static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc) | |||
4114 | } | 4120 | } |
4115 | } | 4121 | } |
4116 | 4122 | ||
4117 | static void ca0132_init_unsol(struct hda_codec *codec) | ||
4118 | { | ||
4119 | snd_hda_jack_detect_enable(codec, UNSOL_TAG_HP); | ||
4120 | snd_hda_jack_detect_enable(codec, UNSOL_TAG_AMIC1); | ||
4121 | } | ||
4122 | |||
4123 | static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir) | 4123 | static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir) |
4124 | { | 4124 | { |
4125 | unsigned int caps; | 4125 | unsigned int caps; |
@@ -4390,7 +4390,8 @@ static void ca0132_download_dsp(struct hda_codec *codec) | |||
4390 | ca0132_set_dsp_msr(codec, true); | 4390 | ca0132_set_dsp_msr(codec, true); |
4391 | } | 4391 | } |
4392 | 4392 | ||
4393 | static void ca0132_process_dsp_response(struct hda_codec *codec) | 4393 | static void ca0132_process_dsp_response(struct hda_codec *codec, |
4394 | struct hda_jack_callback *callback) | ||
4394 | { | 4395 | { |
4395 | struct ca0132_spec *spec = codec->spec; | 4396 | struct ca0132_spec *spec = codec->spec; |
4396 | 4397 | ||
@@ -4403,38 +4404,31 @@ static void ca0132_process_dsp_response(struct hda_codec *codec) | |||
4403 | dspio_clear_response_queue(codec); | 4404 | dspio_clear_response_queue(codec); |
4404 | } | 4405 | } |
4405 | 4406 | ||
4406 | static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) | 4407 | static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb) |
4407 | { | 4408 | { |
4408 | struct ca0132_spec *spec = codec->spec; | 4409 | struct ca0132_spec *spec = codec->spec; |
4409 | unsigned int tag = (res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f; | ||
4410 | 4410 | ||
4411 | if (tag == UNSOL_TAG_DSP) { | 4411 | /* Delay enabling the HP amp, to let the mic-detection |
4412 | ca0132_process_dsp_response(codec); | 4412 | * state machine run. |
4413 | } else { | 4413 | */ |
4414 | struct hda_jack_tbl *jack; | 4414 | cancel_delayed_work_sync(&spec->unsol_hp_work); |
4415 | 4415 | queue_delayed_work(codec->bus->workq, &spec->unsol_hp_work, | |
4416 | codec_dbg(codec, "snd_hda_jack_get_action: 0x%x\n", res); | 4416 | msecs_to_jiffies(500)); |
4417 | jack = snd_hda_jack_tbl_get_from_tag(codec, tag); | 4417 | cb->tbl->block_report = 1; |
4418 | if (!jack) | 4418 | } |
4419 | return; | 4419 | |
4420 | switch (jack->nid) { | 4420 | static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb) |
4421 | case UNSOL_TAG_HP: | 4421 | { |
4422 | /* Delay enabling the HP amp, to let the mic-detection | 4422 | ca0132_select_mic(codec); |
4423 | * state machine run. | 4423 | } |
4424 | */ | 4424 | |
4425 | cancel_delayed_work_sync(&spec->unsol_hp_work); | 4425 | static void ca0132_init_unsol(struct hda_codec *codec) |
4426 | queue_delayed_work(codec->bus->workq, | 4426 | { |
4427 | &spec->unsol_hp_work, | 4427 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_HP, hp_callback); |
4428 | msecs_to_jiffies(500)); | 4428 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_AMIC1, |
4429 | break; | 4429 | amic_callback); |
4430 | case UNSOL_TAG_AMIC1: | 4430 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, |
4431 | ca0132_select_mic(codec); | 4431 | ca0132_process_dsp_response); |
4432 | snd_hda_jack_report_sync(codec); | ||
4433 | break; | ||
4434 | default: | ||
4435 | break; | ||
4436 | } | ||
4437 | } | ||
4438 | } | 4432 | } |
4439 | 4433 | ||
4440 | /* | 4434 | /* |
@@ -4445,8 +4439,6 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4445 | static struct hda_verb ca0132_base_init_verbs[] = { | 4439 | static struct hda_verb ca0132_base_init_verbs[] = { |
4446 | /*enable ct extension*/ | 4440 | /*enable ct extension*/ |
4447 | {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1}, | 4441 | {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1}, |
4448 | /*enable DSP node unsol, needed for DSP download*/ | ||
4449 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | UNSOL_TAG_DSP}, | ||
4450 | {} | 4442 | {} |
4451 | }; | 4443 | }; |
4452 | 4444 | ||
@@ -4563,6 +4555,8 @@ static int ca0132_init(struct hda_codec *codec) | |||
4563 | 4555 | ||
4564 | snd_hda_power_up(codec); | 4556 | snd_hda_power_up(codec); |
4565 | 4557 | ||
4558 | ca0132_init_unsol(codec); | ||
4559 | |||
4566 | ca0132_init_params(codec); | 4560 | ca0132_init_params(codec); |
4567 | ca0132_init_flags(codec); | 4561 | ca0132_init_flags(codec); |
4568 | snd_hda_sequence_write(codec, spec->base_init_verbs); | 4562 | snd_hda_sequence_write(codec, spec->base_init_verbs); |
@@ -4585,8 +4579,6 @@ static int ca0132_init(struct hda_codec *codec) | |||
4585 | for (i = 0; i < spec->num_init_verbs; i++) | 4579 | for (i = 0; i < spec->num_init_verbs; i++) |
4586 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | 4580 | snd_hda_sequence_write(codec, spec->init_verbs[i]); |
4587 | 4581 | ||
4588 | ca0132_init_unsol(codec); | ||
4589 | |||
4590 | ca0132_select_out(codec); | 4582 | ca0132_select_out(codec); |
4591 | ca0132_select_mic(codec); | 4583 | ca0132_select_mic(codec); |
4592 | 4584 | ||
@@ -4614,7 +4606,7 @@ static struct hda_codec_ops ca0132_patch_ops = { | |||
4614 | .build_pcms = ca0132_build_pcms, | 4606 | .build_pcms = ca0132_build_pcms, |
4615 | .init = ca0132_init, | 4607 | .init = ca0132_init, |
4616 | .free = ca0132_free, | 4608 | .free = ca0132_free, |
4617 | .unsol_event = ca0132_unsol_event, | 4609 | .unsol_event = snd_hda_jack_unsol_event, |
4618 | }; | 4610 | }; |
4619 | 4611 | ||
4620 | static void ca0132_config(struct hda_codec *codec) | 4612 | static void ca0132_config(struct hda_codec *codec) |