Module Name:    src
Committed By:   jmcneill
Date:           Sat Sep 26 11:51:29 UTC 2009

Modified Files:
        src/sys/dev/pci/hdaudio: hdaudio_afg.c

Log Message:
Implement and enable headphone sensing. Slightly different from the FreeBSD
implementation in that this code does not care if the headphones are seq=15.
Instead, for each association, find any HP pins with jack sense capabilities
and if at least one has the Presense Detect bit set, enable output on all
PWCs of type HP_OUT and disable output on all PWCs of type LINE_OUT, SPEAKER,
or AUX. Do the reverse if no HP pins have the Presense Detect bit set.


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/sys/dev/pci/hdaudio/hdaudio_afg.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/hdaudio/hdaudio_afg.c
diff -u src/sys/dev/pci/hdaudio/hdaudio_afg.c:1.12 src/sys/dev/pci/hdaudio/hdaudio_afg.c:1.13
--- src/sys/dev/pci/hdaudio/hdaudio_afg.c:1.12	Fri Sep 25 19:49:31 2009
+++ src/sys/dev/pci/hdaudio/hdaudio_afg.c	Sat Sep 26 11:51:29 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio_afg.c,v 1.12 2009/09/25 19:49:31 sborrill Exp $ */
+/* $NetBSD: hdaudio_afg.c,v 1.13 2009/09/26 11:51:29 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <[email protected]>
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.12 2009/09/25 19:49:31 sborrill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.13 2009/09/26 11:51:29 jmcneill Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -106,6 +106,8 @@
 
 #define	HDAUDIO_UNSOLTAG_EVENT_HP	0x00
 
+#define	HDAUDIO_HP_SENSE_PERIOD		(hz / 2)
+
 static const char *hdaudio_afg_mixer_names[] = HDAUDIO_DEVICE_NAMES;
 
 static const char *hdaudio_afg_port_connectivity[] = {
@@ -2932,96 +2934,56 @@
 	struct hdaudio_afg_softc *sc = opaque;
 	struct hdaudio_assoc *as = sc->sc_assocs;
 	struct hdaudio_widget *w;
-	struct hdaudio_control *ctl;
-	uint32_t res, v;
+	uint32_t res = 0;
 	int i, j;
 
-	for (i = 0; i < sc->sc_nassocs; i++) {
-		if (as[i].as_hpredir < 0)
-			continue;
-		w = hdaudio_afg_widget_lookup(sc, as[i].as_pins[15]);
-		if (w == NULL || w->w_enable == false)
-			continue;
-		if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
-			continue;
-
-		res = hdaudio_command(sc->sc_codec, as[i].as_pins[15],
-		    CORB_GET_PIN_SENSE, 0);
-		res = (res & COP_GET_PIN_SENSE_PRESENSE_DETECT) >> 31;
-
-		/* mute/unmute headphone pin */
-		ctl = hdaudio_afg_control_amp_get(sc, as[i].as_pins[15],
-		    HDAUDIO_PINDIR_IN, -1, 1);
-		if (ctl && ctl->ctl_mute) {
-			/* pin has muter, so use it */
-			v = (res != 0) ? 0 : 1;
-			if (v != ctl->ctl_forcemute) {
-				ctl->ctl_forcemute = v;
-				hdaudio_afg_control_amp_set(ctl,
-				    HDAUDIO_AMP_MUTE_DEFAULT,
-				    HDAUDIO_AMP_VOL_DEFAULT,
-				    HDAUDIO_AMP_VOL_DEFAULT);
-			}
-		} else {
-			/* no muter, so disable pin output */
-			w = hdaudio_afg_widget_lookup(sc, as[i].as_pins[15]);
-			if (w && w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX) {
-				if (res)
-					v = w->w_pin.ctrl | COP_PWC_OUT_ENABLE;
-				else
-					v = w->w_pin.ctrl &= ~COP_PWC_OUT_ENABLE;
-				if (v != w->w_pin.ctrl) {
-					w->w_pin.ctrl = v;
-					hdaudio_command(sc->sc_codec, w->w_nid,
-					    CORB_SET_PIN_WIDGET_CONTROL, v);
-				}
-			}
-		}
-		/* mute/unmute other pins */
-		for (j = 0; j < HDAUDIO_MAXPINS - 1; j++) {
-			int type = -1;
-			if (as[i].as_pins[j] <= 0)
-				continue;
+	for (i = 0; i < sc->sc_nassocs; i++)
+		for (j = 0; j < HDAUDIO_MAXPINS; j++) {
 			w = hdaudio_afg_widget_lookup(sc, as[i].as_pins[j]);
-			if (w && w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX)
-				type = COP_CFG_DEFAULT_DEVICE(w->w_pin.config);
-#if notyet
-			ctl = hdaudio_afg_control_amp_get(sc,
-			    as[i].as_pins[j], HDAUDIO_PINDIR_IN, -1, 1);
-			if (ctl && ctl->ctl_mute) {
-				/* pin has muter, so use it */
-				if (type == COP_DEVICE_HP_OUT)
-					v = (res != 0) ? 0 : 1;
-				else
-					v = (res != 0) ? 1 : 0;
-				if (v == ctl->ctl_forcemute)
-					continue;
-				ctl->ctl_forcemute = v;
-				hdaudio_afg_control_amp_set(ctl,
-				    HDAUDIO_AMP_MUTE_DEFAULT,
-				    HDAUDIO_AMP_VOL_DEFAULT,
-				    HDAUDIO_AMP_VOL_DEFAULT);
+			if (w == NULL || w->w_enable == false)
 				continue;
-			}
-#endif
-			/* no muter, so disable pin output */
+			if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
+				continue;
+			if (COP_CFG_DEFAULT_DEVICE(w->w_pin.config) !=
+			    COP_DEVICE_HP_OUT)
+				continue;
+			res |= hdaudio_command(sc->sc_codec, as[i].as_pins[j],
+			    CORB_GET_PIN_SENSE, 0) &
+			    COP_GET_PIN_SENSE_PRESENSE_DETECT;
+		}
+
+	for (i = 0; i < sc->sc_nassocs; i++)
+		for (j = 0; j < HDAUDIO_MAXPINS; j++) {
 			w = hdaudio_afg_widget_lookup(sc, as[i].as_pins[j]);
-			if (w && w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX) {
-				int rres = res;
-				if (type == COP_DEVICE_HP_OUT)
-					rres = !rres;
-				if (rres)
-					v = w->w_pin.ctrl &= ~COP_PWC_OUT_ENABLE;
+			if (w == NULL || w->w_enable == false)
+				continue;
+			if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
+				continue;
+			switch (COP_CFG_DEFAULT_DEVICE(w->w_pin.config)) {
+			case COP_DEVICE_HP_OUT:
+				if (res & COP_GET_PIN_SENSE_PRESENSE_DETECT)
+					w->w_pin.ctrl |= COP_PWC_OUT_ENABLE;
 				else
-					v = w->w_pin.ctrl | COP_PWC_OUT_ENABLE;
-				if (v != w->w_pin.ctrl) {
-					w->w_pin.ctrl = v;
-					hdaudio_command(sc->sc_codec, w->w_nid,
-					    CORB_SET_PIN_WIDGET_CONTROL, v);
-				}
+					w->w_pin.ctrl &= ~COP_PWC_OUT_ENABLE;
+				hdaudio_command(sc->sc_codec, w->w_nid,
+				    CORB_SET_PIN_WIDGET_CONTROL, w->w_pin.ctrl);
+				break;
+			case COP_DEVICE_LINE_OUT:
+			case COP_DEVICE_SPEAKER:
+			case COP_DEVICE_AUX:
+				if (res & COP_GET_PIN_SENSE_PRESENSE_DETECT)
+					w->w_pin.ctrl &= ~COP_PWC_OUT_ENABLE;
+				else
+					w->w_pin.ctrl |= COP_PWC_OUT_ENABLE;
+				hdaudio_command(sc->sc_codec, w->w_nid,
+				    CORB_SET_PIN_WIDGET_CONTROL, w->w_pin.ctrl);
+				break;
+			default:
+				break;
 			}
 		}
-	}
+
+	callout_schedule(&sc->sc_jack_callout, HDAUDIO_HP_SENSE_PERIOD);
 }
 
 static void
@@ -3060,12 +3022,10 @@
 		    (w->w_p.aw_cap & COP_AWCAP_UNSOL_CAPABLE) ?
 		    "unsol" : "poll");
 	}
-#if notyet
 	if (enable) {
 		hdaudio_afg_hp_switch_handler(sc);
-		callout_schedule(&sc->sc_jack_callout, hz);
+		callout_schedule(&sc->sc_jack_callout, HDAUDIO_HP_SENSE_PERIOD);
 	} else
-#endif
 		hda_trace(sc, "jack detect not enabled\n");
 }
 

Reply via email to