[alsa-devel] [PATCH] hda-emu: Add sanify check of initial pinctl

David Henningsson david.henningsson at canonical.com
Thu Feb 7 14:24:12 CET 2013


The pinctl in alsa-info is not the initial
pinctl but the current, so sanify the current pinctl before
accepting it as the initial pinctl. (The initial pinctl is used
during pm test.)

Several false positives in the test tool is removed
with this improvement.

Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---
 hda-int.c           |   64 +++++++++++++++++++++++++++++++++++----------------
 hda-parse.c         |    2 ++
 include/hda-types.h |    4 ++++
 3 files changed, 50 insertions(+), 20 deletions(-)

diff --git a/hda-int.c b/hda-int.c
index c25af56..fbd3cee 100644
--- a/hda-int.c
+++ b/hda-int.c
@@ -400,29 +400,37 @@ static int get_channel_streamid(struct xhda_codec *codec,
 	return node->streamid;
 }
 
-static int set_pin_ctl(struct xhda_codec *codec, struct xhda_node *node,
-		       unsigned int cmd)
+void hda_verify_pin_ctl(struct xhda_node *node, int log,
+			unsigned int *sanified_pinctl)
 {
-	if (!node)
-		return 0;
-	node->pinctl = cmd & 0xff;
+	int pinctl = node->pinctl;
 
 	/* sanity checks */
 	if ((node->pinctl & AC_PINCTL_OUT_EN) &&
-	    !(node->pincap & AC_PINCAP_OUT))
-		hda_log(HDA_LOG_ERR,
-			"setting OUT_EN to pin 0x%x without caps\n",
-			node->nid);
+	    !(node->pincap & AC_PINCAP_OUT)) {
+		if (log)
+			hda_log(HDA_LOG_ERR,
+				"setting OUT_EN to pin 0x%x without caps\n",
+				node->nid);
+		pinctl &= ~AC_PINCTL_OUT_EN;
+	}
 	if ((node->pinctl & AC_PINCTL_HP_EN) &&
-	    !(node->pincap & AC_PINCAP_HP_DRV))
-		hda_log(HDA_LOG_ERR,
-			"setting HP_EN to pin 0x%x without caps\n",
-			node->nid);
+	    !(node->pincap & AC_PINCAP_HP_DRV)) {
+		if (log)
+			hda_log(HDA_LOG_ERR,
+				"setting HP_EN to pin 0x%x without caps\n",
+				node->nid);
+		pinctl &= ~AC_PINCTL_HP_EN;
+	}
 	if ((node->pinctl & AC_PINCTL_IN_EN) &&
-	    !(node->pincap & AC_PINCAP_IN))
-		hda_log(HDA_LOG_ERR,
-			"setting IN_EN to pin 0x%x without caps\n",
-			node->nid);
+	    !(node->pincap & AC_PINCAP_IN)) {
+		if (log)
+			hda_log(HDA_LOG_ERR,
+				"setting IN_EN to pin 0x%x without caps\n",
+				node->nid);
+		pinctl &= ~AC_PINCTL_IN_EN;
+	}
+
 	if (node->pinctl & AC_PINCTL_IN_EN) {
 		unsigned int cap_set, cap_check;
 		const char *vref;
@@ -455,11 +463,27 @@ static int set_pin_ctl(struct xhda_codec *codec, struct xhda_node *node,
 		if (!cap_set)
 			cap_set = AC_PINCAP_VREF_HIZ;
 		if (cap_check && !(cap_set & cap_check)) {
-			hda_log(HDA_LOG_ERR,
-				"setting VREF %s to pin 0x%x without caps 0x%x\n",
-				vref, node->nid, node->pincap);
+			if (log)
+				hda_log(HDA_LOG_ERR,
+					"setting VREF %s to pin 0x%x without caps 0x%x\n",
+					vref, node->nid, node->pincap);
+			pinctl &= ~AC_PINCTL_VREFEN;
 		}
 	}
+
+	if (sanified_pinctl)
+		*sanified_pinctl = pinctl;
+}
+
+static int set_pin_ctl(struct xhda_codec *codec, struct xhda_node *node,
+		       unsigned int cmd)
+{
+	if (!node)
+		return 0;
+	node->pinctl = cmd & 0xff;
+
+	hda_verify_pin_ctl(node, 1, NULL);
+
 	return 0;
 }
 
diff --git a/hda-parse.c b/hda-parse.c
index c75b03b..d38bc04 100644
--- a/hda-parse.c
+++ b/hda-parse.c
@@ -240,6 +240,8 @@ static int parse_node_items(const char *buf)
 				      &node->orig_amp_out_vals);
 	} else if ((p = strmatch(head, "Pin-ctls: "))) {
 		node->pinctl = strtoul(p, NULL, 0);
+		if (node->pincap)
+			hda_verify_pin_ctl(node, 0, &node->pinctl);
 		node->orig_pinctl = node->pinctl;
 	} else if ((p = strmatch(head, "Pincap "))) {
 		const char *end;
diff --git a/include/hda-types.h b/include/hda-types.h
index 3754bca..68cfaa8 100644
--- a/include/hda-types.h
+++ b/include/hda-types.h
@@ -146,6 +146,10 @@ void hda_free_route_lists(struct xhda_route_list *list);
 
 void hda_show_routes(int nid, unsigned int flags);
 
+void hda_verify_pin_ctl(struct xhda_node *node, int log,
+		        unsigned int *sanified_pinctl);
+
+
 void *xalloc(size_t size);
 
 #endif /* __HDA_TYPES_H */
-- 
1.7.9.5



More information about the Alsa-devel mailing list