Commit 3a93897e authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Manage unsol tags in hda_jack.c

Manage the tags assigned for unsolicited events dynamically together
with the jack-detection routines.  Basically this is almost same as what
we've done in patch_sigmatel.c.  Assign the new tag number for each new
unsol event, associate with the given NID and the action type, etc.

With this change, now all pins looked over in snd_hda_jack_add_kctls()
are actually enabled for detection now even if the pins aren't used for
jack-retasking by the driver.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 01a61e12
...@@ -50,6 +50,24 @@ snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid) ...@@ -50,6 +50,24 @@ snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
} }
EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get); EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get);
/**
* snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag
*/
struct hda_jack_tbl *
snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag)
{
struct hda_jack_tbl *jack = codec->jacktbl.list;
int i;
if (!tag || !jack)
return NULL;
for (i = 0; i < codec->jacktbl.used; i++, jack++)
if (jack->tag == tag)
return jack;
return NULL;
}
EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag);
/** /**
* snd_hda_jack_tbl_new - create a jack-table entry for the given NID * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
*/ */
...@@ -65,6 +83,7 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) ...@@ -65,6 +83,7 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
return NULL; return NULL;
jack->nid = nid; jack->nid = nid;
jack->jack_dirty = 1; jack->jack_dirty = 1;
jack->tag = codec->jacktbl.used;
return jack; return jack;
} }
...@@ -77,7 +96,7 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) ...@@ -77,7 +96,7 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec)
static void jack_detect_update(struct hda_codec *codec, static void jack_detect_update(struct hda_codec *codec,
struct hda_jack_tbl *jack) struct hda_jack_tbl *jack)
{ {
if (jack->jack_dirty || !jack->jack_cachable) { if (jack->jack_dirty || !jack->jack_detect) {
unsigned int val = read_pin_sense(codec, jack->nid); unsigned int val = read_pin_sense(codec, jack->nid);
jack->jack_dirty = 0; jack->jack_dirty = 0;
if (val != jack->pin_sense) { if (val != jack->pin_sense) {
...@@ -141,17 +160,19 @@ EXPORT_SYMBOL_HDA(snd_hda_jack_detect); ...@@ -141,17 +160,19 @@ EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
* snd_hda_jack_detect_enable - enable the jack-detection * snd_hda_jack_detect_enable - enable the jack-detection
*/ */
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
unsigned int tag) unsigned char action)
{ {
struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
if (!jack) if (!jack)
return -ENOMEM; return -ENOMEM;
if (jack->jack_cachable) if (jack->jack_detect)
return 0; /* already registered */ return 0; /* already registered */
jack->jack_cachable = 1; jack->jack_detect = 1;
if (action)
jack->action = action;
return snd_hda_codec_write_cache(codec, nid, 0, return snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE, AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | tag); AC_USRSP_EN | jack->tag);
} }
EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
...@@ -167,18 +188,6 @@ static void jack_detect_report(struct hda_codec *codec, ...@@ -167,18 +188,6 @@ static void jack_detect_report(struct hda_codec *codec,
} }
} }
/**
* snd_hda_jack_report - notify kctl when the jack state was changed
*/
void snd_hda_jack_report(struct hda_codec *codec, hda_nid_t nid)
{
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
if (jack)
jack_detect_report(codec, jack);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_report);
/** /**
* snd_hda_jack_report_sync - sync the states of all jacks and report if changed * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
*/ */
...@@ -231,7 +240,7 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, ...@@ -231,7 +240,7 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
struct hda_jack_tbl *jack; struct hda_jack_tbl *jack;
struct snd_kcontrol *kctl; struct snd_kcontrol *kctl;
jack = snd_hda_jack_tbl_get(codec, nid); jack = snd_hda_jack_tbl_new(codec, nid);
if (!jack) if (!jack)
return 0; return 0;
if (jack->kctl) if (jack->kctl)
...@@ -251,20 +260,28 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, ...@@ -251,20 +260,28 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx, static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx,
const struct auto_pin_cfg *cfg) const struct auto_pin_cfg *cfg)
{ {
unsigned int def_conf, conn;
int err;
if (!nid) if (!nid)
return 0; return 0;
if (!is_jack_detectable(codec, nid)) if (!is_jack_detectable(codec, nid))
return 0; return 0;
return snd_hda_jack_add_kctl(codec, nid, def_conf = snd_hda_codec_get_pincfg(codec, nid);
conn = get_defcfg_connect(def_conf);
if (conn != AC_JACK_PORT_COMPLEX)
return 0;
err = snd_hda_jack_add_kctl(codec, nid,
snd_hda_get_pin_label(codec, nid, cfg), snd_hda_get_pin_label(codec, nid, cfg),
idx); idx);
if (err < 0)
return err;
return snd_hda_jack_detect_enable(codec, nid, 0);
} }
/** /**
* snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg
*
* As of now, it assigns only to the pins that enabled the detection.
* Usually this is called at the end of build_controls callback.
*/ */
int snd_hda_jack_add_kctls(struct hda_codec *codec, int snd_hda_jack_add_kctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg) const struct auto_pin_cfg *cfg)
......
...@@ -14,8 +14,12 @@ ...@@ -14,8 +14,12 @@
struct hda_jack_tbl { struct hda_jack_tbl {
hda_nid_t nid; hda_nid_t nid;
unsigned char action; /* event action (0 = none) */
unsigned char tag; /* unsol event tag */
unsigned int private_data; /* arbitrary data */
/* jack-detection stuff */
unsigned int pin_sense; /* cached pin-sense value */ unsigned int pin_sense; /* cached pin-sense value */
unsigned int jack_cachable:1; /* can be updated via unsol events */ unsigned int jack_detect:1; /* capable of jack-detection? */
unsigned int jack_dirty:1; /* needs to update? */ unsigned int jack_dirty:1; /* needs to update? */
unsigned int need_notify:1; /* to be notified? */ unsigned int need_notify:1; /* to be notified? */
struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */
...@@ -23,29 +27,34 @@ struct hda_jack_tbl { ...@@ -23,29 +27,34 @@ struct hda_jack_tbl {
struct hda_jack_tbl * struct hda_jack_tbl *
snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); 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 * struct hda_jack_tbl *
snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid); 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_tbl_clear(struct hda_codec *codec);
/** /**
* snd_hda_jack_set_dirty - set the dirty flag for the given jack-entry * snd_hda_jack_get_action - get jack-tbl entry for the tag
* *
* Call this function when a pin-state may change, e.g. when the hardware * Call this from the unsol event handler to get the assigned action for the
* notifies via an unsolicited event. * event. This will mark the dirty flag for the later reporting, too.
*/ */
static inline void snd_hda_jack_set_dirty(struct hda_codec *codec, static inline unsigned char
hda_nid_t nid) snd_hda_jack_get_action(struct hda_codec *codec, unsigned int tag)
{ {
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); struct hda_jack_tbl *jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
if (jack) if (jack) {
jack->jack_dirty = 1; jack->jack_dirty = 1;
return jack->action;
}
return 0;
} }
void snd_hda_jack_set_dirty_all(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(struct hda_codec *codec, hda_nid_t nid,
unsigned int tag); unsigned char action);
u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
...@@ -68,7 +77,6 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, ...@@ -68,7 +77,6 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
int snd_hda_jack_add_kctls(struct hda_codec *codec, int snd_hda_jack_add_kctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg); const struct auto_pin_cfg *cfg);
void snd_hda_jack_report(struct hda_codec *codec, hda_nid_t nid);
void snd_hda_jack_report_sync(struct hda_codec *codec); void snd_hda_jack_report_sync(struct hda_codec *codec);
......
...@@ -1235,9 +1235,7 @@ static void cs_free(struct hda_codec *codec) ...@@ -1235,9 +1235,7 @@ static void cs_free(struct hda_codec *codec)
static void cs_unsol_event(struct hda_codec *codec, unsigned int res) static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
{ {
snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */ switch (snd_hda_jack_get_action(codec, res >> 26)) {
switch ((res >> 26) & 0x7f) {
case HP_EVENT: case HP_EVENT:
cs_automute(codec); cs_automute(codec);
break; break;
...@@ -1824,9 +1822,7 @@ static int cs421x_build_controls(struct hda_codec *codec) ...@@ -1824,9 +1822,7 @@ static int cs421x_build_controls(struct hda_codec *codec)
static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
{ {
snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */ switch (snd_hda_jack_get_action(codec, res >> 26)) {
switch ((res >> 26) & 0x3f) {
case HP_EVENT: case HP_EVENT:
case SPDIF_EVENT: case SPDIF_EVENT:
cs_automute(codec); cs_automute(codec);
......
...@@ -3757,8 +3757,8 @@ static void cx_auto_automic(struct hda_codec *codec) ...@@ -3757,8 +3757,8 @@ static void cx_auto_automic(struct hda_codec *codec)
static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
{ {
int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20; int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
snd_hda_jack_set_dirty(codec, nid);
switch (res >> 26) { switch (snd_hda_jack_get_action(codec, res >> 26)) {
case CONEXANT_HP_EVENT: case CONEXANT_HP_EVENT:
cx_auto_hp_automute(codec); cx_auto_hp_automute(codec);
break; break;
...@@ -3982,11 +3982,11 @@ static void mute_outputs(struct hda_codec *codec, int num_nids, ...@@ -3982,11 +3982,11 @@ static void mute_outputs(struct hda_codec *codec, int num_nids,
} }
static void enable_unsol_pins(struct hda_codec *codec, int num_pins, static void enable_unsol_pins(struct hda_codec *codec, int num_pins,
hda_nid_t *pins, unsigned int tag) hda_nid_t *pins, unsigned int action)
{ {
int i; int i;
for (i = 0; i < num_pins; i++) for (i = 0; i < num_pins; i++)
snd_hda_jack_detect_enable(codec, pins[i], tag); snd_hda_jack_detect_enable(codec, pins[i], action);
} }
static void cx_auto_init_output(struct hda_codec *codec) static void cx_auto_init_output(struct hda_codec *codec)
......
...@@ -754,10 +754,18 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry); ...@@ -754,10 +754,18 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry);
static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
{ {
struct hdmi_spec *spec = codec->spec; struct hdmi_spec *spec = codec->spec;
int pin_nid = res >> AC_UNSOL_RES_TAG_SHIFT; int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
int pin_nid;
int pd = !!(res & AC_UNSOL_RES_PD); int pd = !!(res & AC_UNSOL_RES_PD);
int eldv = !!(res & AC_UNSOL_RES_ELDV); int eldv = !!(res & AC_UNSOL_RES_ELDV);
int pin_idx; int pin_idx;
struct hda_jack_tbl *jack;
jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
if (!jack)
return;
pin_nid = jack->nid;
jack->jack_dirty = 1;
printk(KERN_INFO printk(KERN_INFO
"HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
...@@ -767,7 +775,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) ...@@ -767,7 +775,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
if (pin_idx < 0) if (pin_idx < 0)
return; return;
snd_hda_jack_set_dirty(codec, pin_nid);
hdmi_present_sense(&spec->pins[pin_idx], true); hdmi_present_sense(&spec->pins[pin_idx], true);
snd_hda_jack_report_sync(codec); snd_hda_jack_report_sync(codec);
} }
...@@ -801,7 +808,7 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) ...@@ -801,7 +808,7 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
int tag = res >> AC_UNSOL_RES_TAG_SHIFT; int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
if (pin_nid_to_pin_index(spec, tag) < 0) { if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) {
snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
return; return;
} }
......
...@@ -185,6 +185,7 @@ struct alc_spec { ...@@ -185,6 +185,7 @@ struct alc_spec {
unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
unsigned int use_jack_tbl:1; /* 1 for model=auto */
/* auto-mute control */ /* auto-mute control */
int automute_mode; int automute_mode;
...@@ -661,11 +662,13 @@ static void alc_mic_automute(struct hda_codec *codec) ...@@ -661,11 +662,13 @@ static void alc_mic_automute(struct hda_codec *codec)
/* unsolicited event for HP jack sensing */ /* unsolicited event for HP jack sensing */
static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
{ {
struct alc_spec *spec = codec->spec;
if (codec->vendor_id == 0x10ec0880) if (codec->vendor_id == 0x10ec0880)
res >>= 28; res >>= 28;
else else
res >>= 26; res >>= 26;
snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */ if (spec->use_jack_tbl)
res = snd_hda_jack_get_action(codec, res);
switch (res) { switch (res) {
case ALC_HP_EVENT: case ALC_HP_EVENT:
alc_hp_automute(codec); alc_hp_automute(codec);
...@@ -3896,6 +3899,7 @@ static void set_capture_mixer(struct hda_codec *codec) ...@@ -3896,6 +3899,7 @@ static void set_capture_mixer(struct hda_codec *codec)
static void alc_auto_init_std(struct hda_codec *codec) static void alc_auto_init_std(struct hda_codec *codec)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
spec->use_jack_tbl = 1;
alc_auto_init_multi_out(codec); alc_auto_init_multi_out(codec);
alc_auto_init_extra_out(codec); alc_auto_init_extra_out(codec);
alc_auto_init_analog_input(codec); alc_auto_init_analog_input(codec);
......
...@@ -177,13 +177,6 @@ enum { ...@@ -177,13 +177,6 @@ enum {
STAC_9872_MODELS STAC_9872_MODELS
}; };
struct sigmatel_event {
hda_nid_t nid;
unsigned char type;
unsigned char tag;
int data;
};
struct sigmatel_mic_route { struct sigmatel_mic_route {
hda_nid_t pin; hda_nid_t pin;
signed char mux_idx; signed char mux_idx;
...@@ -231,9 +224,6 @@ struct sigmatel_spec { ...@@ -231,9 +224,6 @@ struct sigmatel_spec {
const hda_nid_t *pwr_nids; const hda_nid_t *pwr_nids;
const hda_nid_t *dac_list; const hda_nid_t *dac_list;
/* events */
struct snd_array events;
/* playback */ /* playback */
struct hda_input_mux *mono_mux; struct hda_input_mux *mono_mux;
unsigned int cur_mmux; unsigned int cur_mmux;
...@@ -4182,49 +4172,18 @@ static int stac92xx_add_jack(struct hda_codec *codec, ...@@ -4182,49 +4172,18 @@ static int stac92xx_add_jack(struct hda_codec *codec,
#endif /* CONFIG_SND_HDA_INPUT_JACK */ #endif /* CONFIG_SND_HDA_INPUT_JACK */
} }
static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid, static int stac_add_event(struct hda_codec *codec, hda_nid_t nid,
unsigned char type, int data) unsigned char type, int data)
{ {
struct sigmatel_event *event; struct hda_jack_tbl *event;
snd_array_init(&spec->events, sizeof(*event), 32); event = snd_hda_jack_tbl_new(codec, nid);
event = snd_array_new(&spec->events);
if (!event) if (!event)
return -ENOMEM; return -ENOMEM;
event->nid = nid; event->action = type;
event->type = type; event->private_data = data;
event->tag = spec->events.used;
event->data = data;
return event->tag;
}
static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
hda_nid_t nid)
{
struct sigmatel_spec *spec = codec->spec;
struct sigmatel_event *event = spec->events.list;
int i;
for (i = 0; i < spec->events.used; i++, event++) {
if (event->nid == nid)
return event;
}
return NULL;
}
static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec, return 0;
unsigned char tag)
{
struct sigmatel_spec *spec = codec->spec;
struct sigmatel_event *event = spec->events.list;
int i;
for (i = 0; i < spec->events.used; i++, event++) {
if (event->tag == tag)
return event;
}
return NULL;
} }
/* check if given nid is a valid pin and no other events are assigned /* check if given nid is a valid pin and no other events are assigned
...@@ -4234,22 +4193,17 @@ static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec, ...@@ -4234,22 +4193,17 @@ static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
unsigned int type) unsigned int type)
{ {
struct sigmatel_event *event; struct hda_jack_tbl *event;
int tag;
if (!is_jack_detectable(codec, nid)) if (!is_jack_detectable(codec, nid))
return 0; return 0;
event = stac_get_event(codec, nid); event = snd_hda_jack_tbl_new(codec, nid);
if (event) { if (!event)
if (event->type != type) return -ENOMEM;
return 0; if (event->action && event->action != type)
tag = event->tag; return 0;
} else { event->action = type;
tag = stac_add_event(codec->spec, nid, type, 0); snd_hda_jack_detect_enable(codec, nid, 0);
if (tag < 0)
return 0;
}
snd_hda_jack_detect_enable(codec, nid, tag);
return 1; return 1;
} }
...@@ -4536,7 +4490,6 @@ static void stac92xx_free(struct hda_codec *codec) ...@@ -4536,7 +4490,6 @@ static void stac92xx_free(struct hda_codec *codec)
stac92xx_shutup(codec); stac92xx_shutup(codec);
snd_hda_input_jack_free(codec); snd_hda_input_jack_free(codec);
snd_array_free(&spec->events);
kfree(spec); kfree(spec);
snd_hda_detach_beep_device(codec); snd_hda_detach_beep_device(codec);
...@@ -4801,12 +4754,12 @@ static void stac92xx_mic_detect(struct hda_codec *codec) ...@@ -4801,12 +4754,12 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
} }
static void handle_unsol_event(struct hda_codec *codec, static void handle_unsol_event(struct hda_codec *codec,
struct sigmatel_event *event) struct hda_jack_tbl *event)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
int data; int data;
switch (event->type) { switch (event->action) {
case STAC_HP_EVENT: case STAC_HP_EVENT:
case STAC_LO_EVENT: case STAC_LO_EVENT:
stac92xx_hp_detect(codec); stac92xx_hp_detect(codec);
...@@ -4816,7 +4769,7 @@ static void handle_unsol_event(struct hda_codec *codec, ...@@ -4816,7 +4769,7 @@ static void handle_unsol_event(struct hda_codec *codec,
break; break;
} }
switch (event->type) { switch (event->action) {
case STAC_HP_EVENT: case STAC_HP_EVENT:
case STAC_LO_EVENT: case STAC_LO_EVENT:
case STAC_MIC_EVENT: case STAC_MIC_EVENT:
...@@ -4849,14 +4802,14 @@ static void handle_unsol_event(struct hda_codec *codec, ...@@ -4849,14 +4802,14 @@ static void handle_unsol_event(struct hda_codec *codec,
AC_VERB_GET_GPIO_DATA, 0); AC_VERB_GET_GPIO_DATA, 0);
/* toggle VREF state based on GPIOx status */ /* toggle VREF state based on GPIOx status */
snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, snd_hda_codec_write(codec, codec->afg, 0, 0x7e0,
!!(data & (1 << event->data))); !!(data & (1 << event->private_data)));
break; break;
} }
} }
static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid)
{ {
struct sigmatel_event *event = stac_get_event(codec, nid); struct hda_jack_tbl *event = snd_hda_jack_tbl_get(codec, nid);
if (!event) if (!event)
return; return;
handle_unsol_event(codec, event); handle_unsol_event(codec, event);
...@@ -4864,15 +4817,14 @@ static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) ...@@ -4864,15 +4817,14 @@ static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid)
static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
{ {
struct sigmatel_spec *spec = codec->spec; struct hda_jack_tbl *event;
struct sigmatel_event *event;
int tag; int tag;
tag = (res >> 26) & 0x7f; tag = (res >> 26) & 0x7f;
event = stac_get_event_from_tag(codec, tag); event = snd_hda_jack_tbl_get_from_tag(codec, tag);
if (!event) if (!event)
return; return;
snd_hda_jack_set_dirty(codec, event->nid); event->jack_dirty = 1;
handle_unsol_event(codec, event); handle_unsol_event(codec, event);
snd_hda_jack_report_sync(codec); snd_hda_jack_report_sync(codec);
} }
...@@ -5857,15 +5809,13 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) ...@@ -5857,15 +5809,13 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
switch (spec->board_config) { switch (spec->board_config) {
case STAC_HP_M4: case STAC_HP_M4:
/* Enable VREF power saving on GPIO1 detect */ /* Enable VREF power saving on GPIO1 detect */
err = stac_add_event(spec, codec->afg, err = stac_add_event(codec, codec->afg,
STAC_VREF_EVENT, 0x02); STAC_VREF_EVENT, 0x02);
if (err < 0) if (err < 0)
return err; return err;
snd_hda_codec_write_cache(codec, codec->afg, 0, snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
snd_hda_codec_write_cache(codec, codec->afg, 0, snd_hda_jack_detect_enable(codec, codec->afg, 0);
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | err);
spec->gpio_mask |= 0x02; spec->gpio_mask |= 0x02;
break; break;
} }
...@@ -6338,14 +6288,12 @@ static int patch_stac9205(struct hda_codec *codec) ...@@ -6338,14 +6288,12 @@ static int patch_stac9205(struct hda_codec *codec)
snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030); snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030);
/* Enable unsol response for GPIO4/Dock HP connection */ /* Enable unsol response for GPIO4/Dock HP connection */
err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01); err = stac_add_event(codec, codec->afg, STAC_VREF_EVENT, 0x01);
if (err < 0) if (err < 0)
return err; return err;
snd_hda_codec_write_cache(codec, codec->afg, 0, snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
snd_hda_codec_write_cache(codec, codec->afg, 0, snd_hda_jack_detect_enable(codec, codec->afg, 0);
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | err);
spec->gpio_dir = 0x0b; spec->gpio_dir = 0x0b;
spec->eapd_mask = 0x01; spec->eapd_mask = 0x01;
......
...@@ -1714,9 +1714,8 @@ static void via_gpio_control(struct hda_codec *codec) ...@@ -1714,9 +1714,8 @@ static void via_gpio_control(struct hda_codec *codec)
static void via_unsol_event(struct hda_codec *codec, static void via_unsol_event(struct hda_codec *codec,
unsigned int res) unsigned int res)
{ {
snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */
res >>= 26; res >>= 26;
res = snd_hda_jack_get_action(codec, res);
if (res & VIA_JACK_EVENT) if (res & VIA_JACK_EVENT)
set_widgets_power_state(codec); set_widgets_power_state(codec);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment