[alsa-devel] [RFC] hda - is_jack_detectable()

Takashi Iwai tiwai at suse.de
Wed Nov 9 08:50:07 CET 2011


At Wed, 09 Nov 2011 08:08:17 +0100,
Takashi Iwai wrote:
> 
> At Wed, 9 Nov 2011 12:06:04 +0800,
> Raymond Yau wrote:
> > 
> > 2011/11/6 Takashi Iwai <tiwai at suse.de>:
> > > At Sat, 5 Nov 2011 13:30:21 +0800,
> > > Raymond Yau wrote:
> > >>
> > >> 2011/11/2 Takashi Iwai <tiwai at suse.de>:
> > >> > At Tue, 01 Nov 2011 17:03:29 -0400,
> > >> > David Henningsson wrote:
> > >> >>
> > >> >> 2011-10-24 23:31, Raymond Yau skrev:
> > >> >> > sorry, it should be
> > >> >> >
> > >> >> > static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
> > >> >> > {
> > >> >> >          return (snd_hda_query_pin_caps(codec, nid)&  AC_PINCAP_PRES_DETECT)&&
> > >> >> > +           !(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)
> > >> >> >                     &  AC_DEFCFG_MISC_NO_PRESENCE))&&
> > >> >> >                  (get_wcaps(codec, nid)&  AC_WCAP_UNSOL_CAP);
> > >> >> > }
> > >> >> >
> > >> >> I also think it is a good idea, in fact I thought it was this way
> > >> >> already. Can we merge this patch?
> > >> >
> > >> > OK, I checked through alsa-info series and confirmed that this causes
> > >> > no harm, so I merged it now.
> > >> >
> > >> >
> > >> > thanks,
> > >> >
> > >> > Takashi
> > >> >
> > >> >
> > >>
> > >> Sorry the previous patch is wrong
> > >
> > > Ugh, so actually changing it would may bring too many changes, and
> > > most likely regressions, too.  I disabled the code for now for 3.2-rc1.
> > > Once when we cover all test cases and fix broken BIOS devices enough,
> > > we can re-enable it in near future.
> > >
> > >> attach the patch and test cases  (pins 0x11 and 0x14) front panel
> > >> green and pink jacks when set Front Audio Panel to AC97 or HD in BIOS
> > >> setup
> > >
> > > OK, thanks, we can refer to this for more tests.
> > >
> > >
> > > Takashi
> > >
> > 
> >  If bit 0 is set, it indicates that the jack has no presence detect capability
> > 
> > 
> > The Configuration Default register is defined as shown in Figure 66.
> >  31:30         29:24     23:20         19:16         15:12     11:8
> > 7:4         3:0
> >  Port          Location  Default       Connection    Color     Misc
> > Default     Sequence
> >  Connectivity            Device        Type                          Association
> >                            Figure 66. Configuration Data Structure
> > 
> > 
> > This mean that bit 0 of Misc is bit 8 of the Configuration Default register
> > 
> > 
> >              !(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid))
> >                      &  AC_DEFCFG_MISC_NO_PRESENCE)&&
> > 
> 
> Yeah, I already tried it and it still gives too many false-positives.
> Many ASUS laptops (also mobo) set this bit to all pins no matter
> whether it's an obviously detectable jack or not.  Some Toshiba
> laptops do so, too.
> 
> That being said, checking this bit alone isn't reliable because of too
> many BIOS bugs.  A bit more clever test is necessary.

It seems that a broken BIOS sets this bit on all pins in general.
So, the patch below (against the latest sound git tree or 3.2-rc1
kernel) seems working well by filtering out such a brokenness.

Let me know if this works.  If it's OK, I'll try to merge it for
3.2-rc2.


Takashi

---
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 916a186..2518299 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -4752,6 +4752,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
 	memset(sequences_hp, 0, sizeof(sequences_hp));
 	assoc_line_out = 0;
 
+	codec->ignore_misc_bit = true;
 	end_nid = codec->start_nid + codec->num_nodes;
 	for (nid = codec->start_nid; nid < end_nid; nid++) {
 		unsigned int wid_caps = get_wcaps(codec, nid);
@@ -4767,6 +4768,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
 			continue;
 
 		def_conf = snd_hda_codec_get_pincfg(codec, nid);
+		if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
+		      AC_DEFCFG_MISC_NO_PRESENCE))
+			codec->ignore_misc_bit = false;
 		conn = get_defcfg_connect(def_conf);
 		if (conn == AC_JACK_PORT_NONE)
 			continue;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 755f2b0..5644711 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -854,6 +854,7 @@ struct hda_codec {
 	unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */
 	unsigned int pins_shutup:1;	/* pins are shut up */
 	unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
+	unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	unsigned int power_on :1;	/* current (global) power-state */
 	unsigned int power_transition :1; /* power-state in transition */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index dcbea0d..6579e0f 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -510,13 +510,15 @@ int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
 
 static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
 {
-	return (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT) &&
-		/* disable MISC_NO_PRESENCE check because it may break too
-		 * many devices
-		 */
-		/*(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid) &
-		  AC_DEFCFG_MISC_NO_PRESENCE)) &&*/
-		(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP);
+	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
+		return false;
+	if (!codec->ignore_misc_bit &&
+	    (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
+	     AC_DEFCFG_MISC_NO_PRESENCE))
+		return false;
+	if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
+		return false;
+	return true;
 }
 
 /* flags for hda_nid_item */


More information about the Alsa-devel mailing list