aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2013-02-07 14:24:12 +0100
committerTakashi Iwai <tiwai@suse.de>2013-02-07 14:44:58 +0100
commit0c8e2268ade578290564982edd168cf8a3657095 (patch)
tree4493055215d4b25f4657046f602845a4639502f4
parentb55f6928ed0559485f03775f9204c507e29e876e (diff)
downloadhda-emu-0c8e2268ade578290564982edd168cf8a3657095.tar.gz
hda-emu: Add sanify check of initial pinctl
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@canonical.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--hda-int.c64
-rw-r--r--hda-parse.c2
-rw-r--r--include/hda-types.h4
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 9c49a31..8b24179 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 0db0839..fac5084 100644
--- a/include/hda-types.h
+++ b/include/hda-types.h
@@ -158,6 +158,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 */