[alsa-devel] [PATCH RFC v2 0/7] Allow multiple callbacks for hda_jack
Hi,
here is a v2 patchset for allowing multiple callbacks for hda_jack. The difference from the previous patchset is typo fixes, more comments on the return value from snd_hda_jack_detect_enable_callback(), and the missing check of jack->jack_detect flag.
Takashi
The action value assigned to each hda_jack_tbl entry is mostly superfluous. The actually used values are either the widget NID or a value specific to the callback.
The former case can be simply replaced by a reference to widget NID itself. The only place doing the latter is STAC/IDT codec driver for the powermap handling. But, the code doesn't need to check the action field at all -- the function jack_update_power() is called either with a specific pin or with NULL. So the check of jack->action can be removed completely there, too.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/hda_generic.c | 4 +--- sound/pci/hda/hda_generic.h | 6 ------ sound/pci/hda/hda_jack.c | 10 +++------- sound/pci/hda/hda_jack.h | 22 +--------------------- sound/pci/hda/patch_ca0132.c | 16 +++++++++------- sound/pci/hda/patch_cirrus.c | 3 --- sound/pci/hda/patch_hdmi.c | 4 ++-- sound/pci/hda/patch_realtek.c | 9 +++------ sound/pci/hda/patch_sigmatel.c | 18 ++++-------------- sound/pci/hda/patch_via.c | 4 ---- 10 files changed, 23 insertions(+), 73 deletions(-)
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 95121e818b4d..4d605e4ac41c 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -4180,7 +4180,7 @@ static int check_auto_mute_availability(struct hda_codec *codec) if (!is_jack_detectable(codec, nid)) continue; codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid); - snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT, + snd_hda_jack_detect_enable_callback(codec, nid, call_hp_automute); spec->detect_hp = 1; } @@ -4193,7 +4193,6 @@ static int check_auto_mute_availability(struct hda_codec *codec) continue; codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid); snd_hda_jack_detect_enable_callback(codec, nid, - HDA_GEN_FRONT_EVENT, call_line_automute); spec->detect_lo = 1; } @@ -4235,7 +4234,6 @@ static bool auto_mic_check_imux(struct hda_codec *codec) for (i = 1; i < spec->am_num_entries; i++) snd_hda_jack_detect_enable_callback(codec, spec->am_entry[i].pin, - HDA_GEN_MIC_EVENT, call_mic_autoswitch); return true; } diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 3f95f1d3f1f8..72f5624125fb 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -12,12 +12,6 @@ #ifndef __SOUND_HDA_GENERIC_H #define __SOUND_HDA_GENERIC_H
-/* unsol event tags */ -enum { - HDA_GEN_HP_EVENT = 1, HDA_GEN_FRONT_EVENT, HDA_GEN_MIC_EVENT, - HDA_GEN_LAST_EVENT = HDA_GEN_MIC_EVENT -}; - /* table entry for multi-io paths */ struct hda_multi_io { hda_nid_t pin; /* multi-io widget pin NID */ diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 9746d73cec52..9c8f24f2d56b 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -217,7 +217,6 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state); * snd_hda_jack_detect_enable - enable the jack-detection */ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, - unsigned char action, hda_jack_callback cb) { struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); @@ -226,8 +225,6 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, if (jack->jack_detect) return 0; /* already registered */ jack->jack_detect = 1; - if (action) - jack->action = action; if (cb) jack->callback = cb; if (codec->jackpoll_interval > 0) @@ -238,10 +235,9 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, } EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback);
-int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, - unsigned char action) +int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid) { - return snd_hda_jack_detect_enable_callback(codec, nid, action, NULL); + return snd_hda_jack_detect_enable_callback(codec, nid, NULL); } EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable);
@@ -431,7 +427,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, return err;
if (!phantom_jack) - return snd_hda_jack_detect_enable(codec, nid, 0); + return snd_hda_jack_detect_enable(codec, nid); return 0; }
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index 46e1ea83ce3c..c1abc7324d68 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h @@ -19,7 +19,6 @@ typedef void (*hda_jack_callback) (struct hda_codec *, struct hda_jack_tbl *);
struct hda_jack_tbl { hda_nid_t nid; - unsigned char action; /* event action (0 = none) */ unsigned char tag; /* unsol event tag */ unsigned int private_data; /* arbitrary data */ hda_jack_callback callback; @@ -47,29 +46,10 @@ struct hda_jack_tbl * snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid); void snd_hda_jack_tbl_clear(struct hda_codec *codec);
-/** - * snd_hda_jack_get_action - get jack-tbl entry for the tag - * - * Call this from the unsol event handler to get the assigned action for the - * event. This will mark the dirty flag for the later reporting, too. - */ -static inline unsigned char -snd_hda_jack_get_action(struct hda_codec *codec, unsigned int tag) -{ - struct hda_jack_tbl *jack = snd_hda_jack_tbl_get_from_tag(codec, tag); - if (jack) { - jack->jack_dirty = 1; - return jack->action; - } - return 0; -} - void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
-int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, - unsigned char action); +int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid); int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, - unsigned char action, hda_jack_callback cb);
int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 5d8455e2dacd..39fae52258f0 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -4116,8 +4116,8 @@ static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
static void ca0132_init_unsol(struct hda_codec *codec) { - snd_hda_jack_detect_enable(codec, UNSOL_TAG_HP, UNSOL_TAG_HP); - snd_hda_jack_detect_enable(codec, UNSOL_TAG_AMIC1, UNSOL_TAG_AMIC1); + snd_hda_jack_detect_enable(codec, UNSOL_TAG_HP); + snd_hda_jack_detect_enable(codec, UNSOL_TAG_AMIC1); }
static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir) @@ -4406,16 +4406,18 @@ static void ca0132_process_dsp_response(struct hda_codec *codec) static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) { struct ca0132_spec *spec = codec->spec; + unsigned int tag = (res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f;
- if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) { + if (tag == UNSOL_TAG_DSP) { ca0132_process_dsp_response(codec); } else { - res = snd_hda_jack_get_action(codec, - (res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f); + struct hda_jack_tbl *jack;
codec_dbg(codec, "snd_hda_jack_get_action: 0x%x\n", res); - - switch (res) { + jack = snd_hda_jack_tbl_get_from_tag(codec, tag); + if (!jack) + return; + switch (jack->nid) { case UNSOL_TAG_HP: /* Delay enabling the HP amp, to let the mic-detection * state machine run. diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 3db724eaa53c..69b0ffc55a51 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -135,8 +135,6 @@ enum { #define CS421X_IDX_DAC_CFG 0x03 #define CS421X_IDX_SPK_CTL 0x04
-#define SPDIF_EVENT 0x04 - /* Cirrus Logic CS4213 is like CS4210 but does not have SPDIF input/output */ #define CS4213_VENDOR_NID 0x09
@@ -1019,7 +1017,6 @@ static void parse_cs421x_digital(struct hda_codec *codec) if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { spec->spdif_detect = 1; snd_hda_jack_detect_enable_callback(codec, nid, - SPDIF_EVENT, cs4210_spdif_automute); } } diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 99d7d7fecaad..8f94527f1890 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2165,7 +2165,7 @@ static int generic_hdmi_init(struct hda_codec *codec) hda_nid_t pin_nid = per_pin->pin_nid;
hdmi_init_pin(codec, pin_nid); - snd_hda_jack_detect_enable_callback(codec, pin_nid, pin_nid, + snd_hda_jack_detect_enable_callback(codec, pin_nid, codec->jackpoll_interval > 0 ? jack_callback : NULL); } return 0; @@ -2428,7 +2428,7 @@ static int simple_playback_init(struct hda_codec *codec) if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - snd_hda_jack_detect_enable(codec, pin, pin); + snd_hda_jack_detect_enable(codec, pin); return 0; }
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6b1a5de07e35..ac00420e59ff 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -40,9 +40,6 @@ /* keep halting ALC5505 DSP, for power saving */ #define HALT_REALTEK_ALC5505
-/* unsol event tags */ -#define ALC_DCVOL_EVENT 0x08 - /* for GPIO Poll */ #define GPIO_MASK 0x03
@@ -1130,7 +1127,8 @@ static void alc880_fixup_vol_knob(struct hda_codec *codec, const struct hda_fixup *fix, int action) { if (action == HDA_FIXUP_ACT_PROBE) - snd_hda_jack_detect_enable_callback(codec, 0x21, ALC_DCVOL_EVENT, alc_update_knob_master); + snd_hda_jack_detect_enable_callback(codec, 0x21, + alc_update_knob_master); }
static const struct hda_fixup alc880_fixups[] = { @@ -1593,7 +1591,7 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, spec->gen.detect_hp = 1; spec->gen.automute_speaker = 1; spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ - snd_hda_jack_detect_enable_callback(codec, 0x0f, HDA_GEN_HP_EVENT, + snd_hda_jack_detect_enable_callback(codec, 0x0f, snd_hda_gen_hp_automute); snd_hda_add_verbs(codec, alc_gpio1_init_verbs); } @@ -4254,7 +4252,6 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, spec->gen.auto_mute_via_amp = 1; spec->gen.automute_hook = asus_tx300_automute; snd_hda_jack_detect_enable_callback(codec, 0x1b, - HDA_GEN_HP_EVENT, snd_hda_gen_hp_automute); break; case HDA_FIXUP_ACT_BUILD: diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 60aebd0f5e56..bc371cfb5d84 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -40,11 +40,6 @@ #include "hda_generic.h"
enum { - STAC_VREF_EVENT = 8, - STAC_PWR_EVENT, -}; - -enum { STAC_REF, STAC_9200_OQO, STAC_9200_DELL_D21, @@ -505,13 +500,11 @@ static void jack_update_power(struct hda_codec *codec, for (i = 0; i < spec->num_pwrs; i++) { hda_nid_t nid = spec->pwr_nids[i]; jack = snd_hda_jack_tbl_get(codec, nid); - if (!jack || !jack->action) + if (!jack) continue; - if (jack->action == STAC_PWR_EVENT || - jack->action <= HDA_GEN_LAST_EVENT) - stac_toggle_power_map(codec, nid, - snd_hda_jack_detect(codec, nid), - false); + stac_toggle_power_map(codec, nid, + snd_hda_jack_detect(codec, nid), + false); }
snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_IDT_SET_POWER_MAP, @@ -568,7 +561,6 @@ static void stac_init_power_map(struct hda_codec *codec) spec->vref_mute_led_nid != nid && is_jack_detectable(codec, nid)) { snd_hda_jack_detect_enable_callback(codec, nid, - STAC_PWR_EVENT, jack_update_power); } else { if (def_conf == AC_JACK_PORT_NONE) @@ -3028,7 +3020,6 @@ static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec, snd_hda_codec_write_cache(codec, codec->afg, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); snd_hda_jack_detect_enable_callback(codec, codec->afg, - STAC_VREF_EVENT, stac_vref_event); jack = snd_hda_jack_tbl_get(codec, codec->afg); if (jack) @@ -4052,7 +4043,6 @@ static void stac9205_fixup_dell_m43(struct hda_codec *codec, snd_hda_codec_write_cache(codec, codec->afg, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); snd_hda_jack_detect_enable_callback(codec, codec->afg, - STAC_VREF_EVENT, stac_vref_event); jack = snd_hda_jack_tbl_get(codec, codec->afg); if (jack) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 778166259b3e..2a8be5a5da15 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -592,8 +592,6 @@ static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_t set_widgets_power_state(codec); }
-#define VIA_JACK_EVENT (HDA_GEN_LAST_EVENT + 1) - static void via_set_jack_unsol_events(struct hda_codec *codec) { struct via_spec *spec = codec->spec; @@ -610,7 +608,6 @@ static void via_set_jack_unsol_events(struct hda_codec *codec) if (pin && !snd_hda_jack_tbl_get(codec, pin) && is_jack_detectable(codec, pin)) snd_hda_jack_detect_enable_callback(codec, pin, - VIA_JACK_EVENT, via_jack_powerstate_event); }
@@ -619,7 +616,6 @@ static void via_set_jack_unsol_events(struct hda_codec *codec) if (pin && !snd_hda_jack_tbl_get(codec, pin) && is_jack_detectable(codec, pin)) snd_hda_jack_detect_enable_callback(codec, pin, - VIA_JACK_EVENT, via_jack_powerstate_event); } }
It's called only in hda_jack.c, so make it local.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/hda_jack.c | 3 +-- sound/pci/hda/hda_jack.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 9c8f24f2d56b..7f332794993f 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -94,7 +94,7 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_from_tag); /** * snd_hda_jack_tbl_new - create a jack-table entry for the given NID */ -struct hda_jack_tbl * +static struct hda_jack_tbl * snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) { struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); @@ -108,7 +108,6 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) jack->tag = codec->jacktbl.used; return jack; } -EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_new);
void snd_hda_jack_tbl_clear(struct hda_codec *codec) { diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index c1abc7324d68..67f42db9c89c 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h @@ -42,8 +42,6 @@ snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); struct hda_jack_tbl * snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag);
-struct hda_jack_tbl * -snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid); void snd_hda_jack_tbl_clear(struct hda_codec *codec);
void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
STAC/IDT driver calls snd_hda_jack_tbl_get() again after calling snd_hda_jack_detect_enable_callback(). For simplifying this, let's make snd_hda_jack_detect_enable_callback() returning the pointer while handling the error with the standard IS_ERR() & co.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/hda_jack.c | 24 +++++++++++++++++------- sound/pci/hda/hda_jack.h | 5 +++-- sound/pci/hda/patch_sigmatel.c | 14 ++++++-------- 3 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 7f332794993f..a5fe1b428015 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -214,29 +214,39 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state);
/** * snd_hda_jack_detect_enable - enable the jack-detection + * + * In the case of error, the return value will be a pointer embedded with + * errno. Check and handle the return value appropriately with standard + * macros such as @IS_ERR() and @PTR_ERR(). */ -int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, - hda_jack_callback cb) +struct hda_jack_tbl * +snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, + hda_jack_callback cb) { struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); + int err; + if (!jack) - return -ENOMEM; + return ERR_PTR(-ENOMEM); if (jack->jack_detect) - return 0; /* already registered */ + return jack; /* already registered */ jack->jack_detect = 1; if (cb) jack->callback = cb; if (codec->jackpoll_interval > 0) - return 0; /* No unsol if we're polling instead */ - return snd_hda_codec_write_cache(codec, nid, 0, + return jack; /* No unsol if we're polling instead */ + err = snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | jack->tag); + if (err < 0) + return ERR_PTR(err); + return jack; } EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback);
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid) { - return snd_hda_jack_detect_enable_callback(codec, nid, NULL); + return PTR_ERR_OR_ZERO(snd_hda_jack_detect_enable_callback(codec, nid, NULL)); } EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable);
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index 67f42db9c89c..668669ce3e52 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h @@ -47,8 +47,9 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec); void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid); -int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, - hda_jack_callback cb); +struct hda_jack_tbl * +snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, + hda_jack_callback cb);
int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, hda_nid_t gating_nid); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index bc371cfb5d84..4b338beb9449 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -3019,10 +3019,9 @@ static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec, /* Enable VREF power saving on GPIO1 detect */ snd_hda_codec_write_cache(codec, codec->afg, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); - snd_hda_jack_detect_enable_callback(codec, codec->afg, - stac_vref_event); - jack = snd_hda_jack_tbl_get(codec, codec->afg); - if (jack) + jack = snd_hda_jack_detect_enable_callback(codec, codec->afg, + stac_vref_event); + if (!IS_ERR(jack)) jack->private_data = 0x02;
spec->gpio_mask |= 0x02; @@ -4042,10 +4041,9 @@ static void stac9205_fixup_dell_m43(struct hda_codec *codec, /* Enable unsol response for GPIO4/Dock HP connection */ snd_hda_codec_write_cache(codec, codec->afg, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); - snd_hda_jack_detect_enable_callback(codec, codec->afg, - stac_vref_event); - jack = snd_hda_jack_tbl_get(codec, codec->afg); - if (jack) + jack = snd_hda_jack_detect_enable_callback(codec, codec->afg, + stac_vref_event); + if (!IS_ERR(jack)) jack->private_data = 0x01;
spec->gpio_dir = 0x0b;
So far, hda_jack infrastructure allows only one callback per jack, and this makes things slightly complicated when a driver wants to assign multiple tasks to a jack, e.g. the standard auto-mute with a power up/down sequence. This can be simplified if the hda_jack accepts multiple callbacks.
This patch is such an extension: the callback-specific part (the function and private_data) is split to another struct from hda_jack_tbl, and multiple such objects can be assigned to a single hda_jack_tbl entry.
The new struct hda_jack_callback is passed to each callback function now, thus the patch became bigger than expected. But these changes are mostly trivial.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/hda_generic.c | 19 ++++++++++++------- sound/pci/hda/hda_generic.h | 12 ++++++------ sound/pci/hda/hda_jack.c | 43 ++++++++++++++++++++++++++++++------------ sound/pci/hda/hda_jack.h | 17 ++++++++++++----- sound/pci/hda/patch_cirrus.c | 2 +- sound/pci/hda/patch_conexant.c | 3 ++- sound/pci/hda/patch_hdmi.c | 14 ++++++++++---- sound/pci/hda/patch_realtek.c | 12 +++++++----- sound/pci/hda/patch_sigmatel.c | 24 +++++++++++------------ sound/pci/hda/patch_via.c | 11 +++++++---- 10 files changed, 100 insertions(+), 57 deletions(-)
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 4d605e4ac41c..32a85f9cac4b 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -2032,7 +2032,8 @@ static int create_speaker_out_ctls(struct hda_codec *codec) * independent HP controls */
-static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack); +static void call_hp_automute(struct hda_codec *codec, + struct hda_jack_callback *jack); static int indep_hp_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -3948,7 +3949,8 @@ static void call_update_outputs(struct hda_codec *codec) }
/* standard HP-automute helper */ -void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) +void snd_hda_gen_hp_automute(struct hda_codec *codec, + struct hda_jack_callback *jack) { struct hda_gen_spec *spec = codec->spec; hda_nid_t *pins = spec->autocfg.hp_pins; @@ -3968,7 +3970,8 @@ void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
/* standard line-out-automute helper */ -void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) +void snd_hda_gen_line_automute(struct hda_codec *codec, + struct hda_jack_callback *jack) { struct hda_gen_spec *spec = codec->spec;
@@ -3988,7 +3991,8 @@ void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jac EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
/* standard mic auto-switch helper */ -void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack) +void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, + struct hda_jack_callback *jack) { struct hda_gen_spec *spec = codec->spec; int i; @@ -4011,7 +4015,8 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *ja EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
/* call appropriate hooks */ -static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) +static void call_hp_automute(struct hda_codec *codec, + struct hda_jack_callback *jack) { struct hda_gen_spec *spec = codec->spec; if (spec->hp_automute_hook) @@ -4021,7 +4026,7 @@ static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) }
static void call_line_automute(struct hda_codec *codec, - struct hda_jack_tbl *jack) + struct hda_jack_callback *jack) { struct hda_gen_spec *spec = codec->spec; if (spec->line_automute_hook) @@ -4031,7 +4036,7 @@ static void call_line_automute(struct hda_codec *codec, }
static void call_mic_autoswitch(struct hda_codec *codec, - struct hda_jack_tbl *jack) + struct hda_jack_callback *jack) { struct hda_gen_spec *spec = codec->spec; if (spec->mic_autoswitch_hook) diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 72f5624125fb..61dd5153f512 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -284,11 +284,11 @@ struct hda_gen_spec {
/* automute / autoswitch hooks */ void (*hp_automute_hook)(struct hda_codec *codec, - struct hda_jack_tbl *tbl); + struct hda_jack_callback *cb); void (*line_automute_hook)(struct hda_codec *codec, - struct hda_jack_tbl *tbl); + struct hda_jack_callback *cb); void (*mic_autoswitch_hook)(struct hda_codec *codec, - struct hda_jack_tbl *tbl); + struct hda_jack_callback *cb); };
int snd_hda_gen_spec_init(struct hda_gen_spec *spec); @@ -320,11 +320,11 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec);
/* standard jack event callbacks */ void snd_hda_gen_hp_automute(struct hda_codec *codec, - struct hda_jack_tbl *jack); + struct hda_jack_callback *jack); void snd_hda_gen_line_automute(struct hda_codec *codec, - struct hda_jack_tbl *jack); + struct hda_jack_callback *jack); void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, - struct hda_jack_tbl *jack); + struct hda_jack_callback *jack); void snd_hda_gen_update_outputs(struct hda_codec *codec);
#ifdef CONFIG_PM diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index a5fe1b428015..6a8dc0100434 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -117,8 +117,13 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) struct hda_jack_tbl *jack = codec->jacktbl.list; int i; for (i = 0; i < codec->jacktbl.used; i++, jack++) { + struct hda_jack_callback *cb, *next; if (jack->jack) snd_device_free(codec->bus->card, jack->jack); + for (cb = jack->callback; cb; cb = next) { + next = cb->next; + kfree(cb); + } } } #endif @@ -219,28 +224,38 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state); * errno. Check and handle the return value appropriately with standard * macros such as @IS_ERR() and @PTR_ERR(). */ -struct hda_jack_tbl * +struct hda_jack_callback * snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, - hda_jack_callback cb) + hda_jack_callback_fn func) { - struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); + struct hda_jack_tbl *jack; + struct hda_jack_callback *callback = NULL; int err;
+ jack = snd_hda_jack_tbl_new(codec, nid); if (!jack) return ERR_PTR(-ENOMEM); + if (func) { + callback = kzalloc(sizeof(*callback), GFP_KERNEL); + if (!callback) + return ERR_PTR(-ENOMEM); + callback->func = func; + callback->tbl = jack; + callback->next = jack->callback; + jack->callback = callback; + } + if (jack->jack_detect) - return jack; /* already registered */ + return callback; /* already registered */ jack->jack_detect = 1; - if (cb) - jack->callback = cb; if (codec->jackpoll_interval > 0) - return jack; /* No unsol if we're polling instead */ + return callback; /* No unsol if we're polling instead */ err = snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | jack->tag); if (err < 0) return ERR_PTR(err); - return jack; + return callback; } EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback);
@@ -503,13 +518,17 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctls); static void call_jack_callback(struct hda_codec *codec, struct hda_jack_tbl *jack) { - if (jack->callback) - jack->callback(codec, jack); + struct hda_jack_callback *cb; + + for (cb = jack->callback; cb; cb = cb->next) + cb->func(codec, cb); if (jack->gated_jack) { struct hda_jack_tbl *gated = snd_hda_jack_tbl_get(codec, jack->gated_jack); - if (gated && gated->callback) - gated->callback(codec, gated); + if (gated) { + for (cb = gated->callback; cb; cb = cb->next) + cb->func(codec, cb); + } } }
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index 668669ce3e52..b41e0a3ea1fb 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h @@ -14,14 +14,21 @@
struct auto_pin_cfg; struct hda_jack_tbl; +struct hda_jack_callback;
-typedef void (*hda_jack_callback) (struct hda_codec *, struct hda_jack_tbl *); +typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *); + +struct hda_jack_callback { + struct hda_jack_tbl *tbl; + hda_jack_callback_fn func; + unsigned int private_data; /* arbitrary data */ + struct hda_jack_callback *next; +};
struct hda_jack_tbl { hda_nid_t nid; unsigned char tag; /* unsol event tag */ - unsigned int private_data; /* arbitrary data */ - hda_jack_callback callback; + struct hda_jack_callback *callback; /* jack-detection stuff */ unsigned int pin_sense; /* cached pin-sense value */ unsigned int jack_detect:1; /* capable of jack-detection? */ @@ -47,9 +54,9 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec); void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid); -struct hda_jack_tbl * +struct hda_jack_callback * snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, - hda_jack_callback cb); + hda_jack_callback_fn cb);
int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, hda_nid_t gating_nid); diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 69b0ffc55a51..1589c9bcce3e 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -982,7 +982,7 @@ static void cs4210_pinmux_init(struct hda_codec *codec) }
static void cs4210_spdif_automute(struct hda_codec *codec, - struct hda_jack_tbl *tbl) + struct hda_jack_callback *tbl) { struct cs_spec *spec = codec->spec; bool spdif_present = false; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index e0c5bc1d671b..d5b0582daaf0 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -393,7 +393,8 @@ static void olpc_xo_update_mic_pins(struct hda_codec *codec) }
/* mic_autoswitch hook */ -static void olpc_xo_automic(struct hda_codec *codec, struct hda_jack_tbl *jack) +static void olpc_xo_automic(struct hda_codec *codec, + struct hda_jack_callback *jack) { struct conexant_spec *spec = codec->spec; int saved_cached_write = codec->cached_write; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8f94527f1890..39862e98551c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1163,17 +1163,23 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
-static void jack_callback(struct hda_codec *codec, struct hda_jack_tbl *jack) +static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid) { struct hdmi_spec *spec = codec->spec; - int pin_idx = pin_nid_to_pin_index(codec, jack->nid); + int pin_idx = pin_nid_to_pin_index(codec, nid); + if (pin_idx < 0) return; - if (hdmi_present_sense(get_pin(spec, pin_idx), 1)) snd_hda_jack_report_sync(codec); }
+static void jack_callback(struct hda_codec *codec, + struct hda_jack_callback *jack) +{ + check_presence_and_report(codec, jack->tbl->nid); +} + static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) { int tag = res >> AC_UNSOL_RES_TAG_SHIFT; @@ -1190,7 +1196,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA), !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV));
- jack_callback(codec, jack); + check_presence_and_report(codec, jack->nid); }
static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ac00420e59ff..a109fdb085f9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -264,7 +264,8 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, }
/* update the master volume per volume-knob's unsol event */ -static void alc_update_knob_master(struct hda_codec *codec, struct hda_jack_tbl *jack) +static void alc_update_knob_master(struct hda_codec *codec, + struct hda_jack_callback *jack) { unsigned int val; struct snd_kcontrol *kctl; @@ -276,7 +277,7 @@ static void alc_update_knob_master(struct hda_codec *codec, struct hda_jack_tbl uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (!uctl) return; - val = snd_hda_codec_read(codec, jack->nid, 0, + val = snd_hda_codec_read(codec, jack->tbl->nid, 0, AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); val &= HDA_AMP_VOLMASK; uctl->value.integer.value[0] = val; @@ -3272,7 +3273,7 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec, }
static void alc269_x101_hp_automute_hook(struct hda_codec *codec, - struct hda_jack_tbl *jack) + struct hda_jack_callback *jack) { struct alc_spec *spec = codec->spec; int vref; @@ -3926,7 +3927,8 @@ static void alc_update_headset_mode_hook(struct hda_codec *codec, alc_update_headset_mode(codec); }
-static void alc_update_headset_jack_cb(struct hda_codec *codec, struct hda_jack_tbl *jack) +static void alc_update_headset_jack_cb(struct hda_codec *codec, + struct hda_jack_callback *jack) { struct alc_spec *spec = codec->spec; spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN; @@ -4166,7 +4168,7 @@ static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec, }
static void alc283_hp_automute_hook(struct hda_codec *codec, - struct hda_jack_tbl *jack) + struct hda_jack_callback *jack) { struct alc_spec *spec = codec->spec; int vref; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 4b338beb9449..3193529607f2 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -481,7 +481,7 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
/* update power bit per jack plug/unplug */ static void jack_update_power(struct hda_codec *codec, - struct hda_jack_tbl *jack) + struct hda_jack_callback *jack) { struct sigmatel_spec *spec = codec->spec; int i; @@ -489,9 +489,9 @@ static void jack_update_power(struct hda_codec *codec, if (!spec->num_pwrs) return;
- if (jack && jack->nid) { - stac_toggle_power_map(codec, jack->nid, - snd_hda_jack_detect(codec, jack->nid), + if (jack && jack->tbl->nid) { + stac_toggle_power_map(codec, jack->tbl->nid, + snd_hda_jack_detect(codec, jack->tbl->nid), true); return; } @@ -499,8 +499,7 @@ static void jack_update_power(struct hda_codec *codec, /* update all jacks */ for (i = 0; i < spec->num_pwrs; i++) { hda_nid_t nid = spec->pwr_nids[i]; - jack = snd_hda_jack_tbl_get(codec, nid); - if (!jack) + if (!snd_hda_jack_tbl_get(codec, nid)) continue; stac_toggle_power_map(codec, nid, snd_hda_jack_detect(codec, nid), @@ -512,27 +511,28 @@ static void jack_update_power(struct hda_codec *codec, }
static void stac_hp_automute(struct hda_codec *codec, - struct hda_jack_tbl *jack) + struct hda_jack_callback *jack) { snd_hda_gen_hp_automute(codec, jack); jack_update_power(codec, jack); }
static void stac_line_automute(struct hda_codec *codec, - struct hda_jack_tbl *jack) + struct hda_jack_callback *jack) { snd_hda_gen_line_automute(codec, jack); jack_update_power(codec, jack); }
static void stac_mic_autoswitch(struct hda_codec *codec, - struct hda_jack_tbl *jack) + struct hda_jack_callback *jack) { snd_hda_gen_mic_autoswitch(codec, jack); jack_update_power(codec, jack); }
-static void stac_vref_event(struct hda_codec *codec, struct hda_jack_tbl *event) +static void stac_vref_event(struct hda_codec *codec, + struct hda_jack_callback *event) { unsigned int data;
@@ -3011,7 +3011,7 @@ static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct sigmatel_spec *spec = codec->spec; - struct hda_jack_tbl *jack; + struct hda_jack_callback *jack;
if (action != HDA_FIXUP_ACT_PRE_PROBE) return; @@ -4033,7 +4033,7 @@ static void stac9205_fixup_dell_m43(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct sigmatel_spec *spec = codec->spec; - struct hda_jack_tbl *jack; + struct hda_jack_callback *jack;
if (action == HDA_FIXUP_ACT_PRE_PROBE) { snd_hda_apply_pincfgs(codec, dell_9205_m43_pin_configs); diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 2a8be5a5da15..8d234ab9f06b 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -118,7 +118,7 @@ static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream, int action); -static void via_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl); +static void via_hp_automute(struct hda_codec *codec, struct hda_jack_callback *tbl);
static struct via_spec *via_new_spec(struct hda_codec *codec) { @@ -575,19 +575,22 @@ static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = { {} /* terminator */ };
-static void via_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl) +static void via_hp_automute(struct hda_codec *codec, + struct hda_jack_callback *tbl) { set_widgets_power_state(codec); snd_hda_gen_hp_automute(codec, tbl); }
-static void via_line_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl) +static void via_line_automute(struct hda_codec *codec, + struct hda_jack_callback *tbl) { set_widgets_power_state(codec); snd_hda_gen_line_automute(codec, tbl); }
-static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_tbl *tbl) +static void via_jack_powerstate_event(struct hda_codec *codec, + struct hda_jack_callback *tbl) { set_widgets_power_state(codec); }
Now we can register multiple callbacks to each jack, most of hooks used in STAC/IDT codecs can be removed by enabling the powermap update callback for all relevant pins. Along with this, the call of stac_init_power_map() can be moved back to stac_parse_auto_config() and the own build_controls callback can be removed, too.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_sigmatel.c | 38 ++------------------------------------ 1 file changed, 2 insertions(+), 36 deletions(-)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3193529607f2..4f6413e01c13 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -510,27 +510,6 @@ static void jack_update_power(struct hda_codec *codec, spec->power_map_bits); }
-static void stac_hp_automute(struct hda_codec *codec, - struct hda_jack_callback *jack) -{ - snd_hda_gen_hp_automute(codec, jack); - jack_update_power(codec, jack); -} - -static void stac_line_automute(struct hda_codec *codec, - struct hda_jack_callback *jack) -{ - snd_hda_gen_line_automute(codec, jack); - jack_update_power(codec, jack); -} - -static void stac_mic_autoswitch(struct hda_codec *codec, - struct hda_jack_callback *jack) -{ - snd_hda_gen_mic_autoswitch(codec, jack); - jack_update_power(codec, jack); -} - static void stac_vref_event(struct hda_codec *codec, struct hda_jack_callback *event) { @@ -555,8 +534,6 @@ static void stac_init_power_map(struct hda_codec *codec) hda_nid_t nid = spec->pwr_nids[i]; unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); def_conf = get_defcfg_connect(def_conf); - if (snd_hda_jack_tbl_get(codec, nid)) - continue; if (def_conf == AC_JACK_PORT_COMPLEX && spec->vref_mute_led_nid != nid && is_jack_detectable(codec, nid)) { @@ -4206,9 +4183,6 @@ static int stac_parse_auto_config(struct hda_codec *codec) spec->gen.pcm_capture_hook = stac_capture_pcm_hook;
spec->gen.automute_hook = stac_update_outputs; - spec->gen.hp_automute_hook = stac_hp_automute; - spec->gen.line_automute_hook = stac_line_automute; - spec->gen.mic_autoswitch_hook = stac_mic_autoswitch;
err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); if (err < 0) @@ -4260,16 +4234,8 @@ static int stac_parse_auto_config(struct hda_codec *codec) return err; }
- return 0; -} - -static int stac_build_controls(struct hda_codec *codec) -{ - int err = snd_hda_gen_build_controls(codec); - - if (err < 0) - return err; stac_init_power_map(codec); + return 0; }
@@ -4383,7 +4349,7 @@ static int stac_suspend(struct hda_codec *codec) #endif /* CONFIG_PM */
static const struct hda_codec_ops stac_patch_ops = { - .build_controls = stac_build_controls, + .build_controls = snd_hda_gen_build_controls, .build_pcms = snd_hda_gen_build_pcms, .init = stac_init, .free = stac_free,
Like the previous fix for STAC/IDT codecs, the automute hooks in VIA driver can be also removed by enabling the power control callback for all pins.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_via.c | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-)
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 8d234ab9f06b..6c206b6c8d65 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -118,7 +118,6 @@ static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream, int action); -static void via_hp_automute(struct hda_codec *codec, struct hda_jack_callback *tbl);
static struct via_spec *via_new_spec(struct hda_codec *codec) { @@ -575,20 +574,6 @@ static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = { {} /* terminator */ };
-static void via_hp_automute(struct hda_codec *codec, - struct hda_jack_callback *tbl) -{ - set_widgets_power_state(codec); - snd_hda_gen_hp_automute(codec, tbl); -} - -static void via_line_automute(struct hda_codec *codec, - struct hda_jack_callback *tbl) -{ - set_widgets_power_state(codec); - snd_hda_gen_line_automute(codec, tbl); -} - static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_callback *tbl) { @@ -602,22 +587,16 @@ static void via_set_jack_unsol_events(struct hda_codec *codec) hda_nid_t pin; int i;
- spec->gen.hp_automute_hook = via_hp_automute; - if (cfg->speaker_pins[0]) - spec->gen.line_automute_hook = via_line_automute; - for (i = 0; i < cfg->line_outs; i++) { pin = cfg->line_out_pins[i]; - if (pin && !snd_hda_jack_tbl_get(codec, pin) && - is_jack_detectable(codec, pin)) + if (pin && is_jack_detectable(codec, pin)) snd_hda_jack_detect_enable_callback(codec, pin, via_jack_powerstate_event); }
for (i = 0; i < cfg->num_inputs; i++) { pin = cfg->line_out_pins[i]; - if (pin && !snd_hda_jack_tbl_get(codec, pin) && - is_jack_detectable(codec, pin)) + if (pin && is_jack_detectable(codec, pin)) snd_hda_jack_detect_enable_callback(codec, pin, via_jack_powerstate_event); }
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 --- sound/pci/hda/patch_ca0132.c | 76 ++++++++++++++++++++------------------------ 1 file 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) { struct ca0132_spec *spec = container_of( to_delayed_work(work), struct ca0132_spec, unsol_hp_work); + struct hda_jack_tbl *jack; + ca0132_select_out(spec->codec); - snd_hda_jack_report_sync(spec->codec); + jack = snd_hda_jack_tbl_get(spec->codec, UNSOL_TAG_HP); + if (jack) { + jack->block_report = 0; + snd_hda_jack_report_sync(spec->codec); + } }
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) } }
-static void ca0132_init_unsol(struct hda_codec *codec) -{ - snd_hda_jack_detect_enable(codec, UNSOL_TAG_HP); - snd_hda_jack_detect_enable(codec, UNSOL_TAG_AMIC1); -} - static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir) { unsigned int caps; @@ -4390,7 +4390,8 @@ static void ca0132_download_dsp(struct hda_codec *codec) ca0132_set_dsp_msr(codec, true); }
-static void ca0132_process_dsp_response(struct hda_codec *codec) +static void ca0132_process_dsp_response(struct hda_codec *codec, + struct hda_jack_callback *callback) { struct ca0132_spec *spec = codec->spec;
@@ -4403,38 +4404,31 @@ static void ca0132_process_dsp_response(struct hda_codec *codec) dspio_clear_response_queue(codec); }
-static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) +static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb) { struct ca0132_spec *spec = codec->spec; - unsigned int tag = (res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f;
- if (tag == UNSOL_TAG_DSP) { - ca0132_process_dsp_response(codec); - } else { - struct hda_jack_tbl *jack; - - codec_dbg(codec, "snd_hda_jack_get_action: 0x%x\n", res); - jack = snd_hda_jack_tbl_get_from_tag(codec, tag); - if (!jack) - return; - switch (jack->nid) { - case UNSOL_TAG_HP: - /* 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); - snd_hda_jack_report_sync(codec); - break; - default: - break; - } - } + /* 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)); + cb->tbl->block_report = 1; +} + +static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb) +{ + ca0132_select_mic(codec); +} + +static void ca0132_init_unsol(struct hda_codec *codec) +{ + snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_HP, hp_callback); + snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_AMIC1, + amic_callback); + snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, + ca0132_process_dsp_response); }
/* @@ -4445,8 +4439,6 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) static struct hda_verb ca0132_base_init_verbs[] = { /*enable ct extension*/ {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1}, - /*enable DSP node unsol, needed for DSP download*/ - {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | UNSOL_TAG_DSP}, {} };
@@ -4563,6 +4555,8 @@ static int ca0132_init(struct hda_codec *codec)
snd_hda_power_up(codec);
+ ca0132_init_unsol(codec); + ca0132_init_params(codec); ca0132_init_flags(codec); snd_hda_sequence_write(codec, spec->base_init_verbs); @@ -4585,8 +4579,6 @@ static int ca0132_init(struct hda_codec *codec) for (i = 0; i < spec->num_init_verbs; i++) snd_hda_sequence_write(codec, spec->init_verbs[i]);
- ca0132_init_unsol(codec); - ca0132_select_out(codec); ca0132_select_mic(codec);
@@ -4614,7 +4606,7 @@ static struct hda_codec_ops ca0132_patch_ops = { .build_pcms = ca0132_build_pcms, .init = ca0132_init, .free = ca0132_free, - .unsol_event = ca0132_unsol_event, + .unsol_event = snd_hda_jack_unsol_event, };
static void ca0132_config(struct hda_codec *codec)
participants (1)
-
Takashi Iwai