|
@@ -904,23 +904,28 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
|
|
|
spec->pin[spec->num_pins] = pin_nid;
|
|
|
spec->num_pins++;
|
|
|
|
|
|
- /*
|
|
|
- * It is assumed that converter nodes come first in the node list and
|
|
|
- * hence have been registered and usable now.
|
|
|
- */
|
|
|
return hdmi_read_pin_conn(codec, pin_nid);
|
|
|
}
|
|
|
|
|
|
static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
|
|
|
{
|
|
|
+ int i, found_pin = 0;
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
|
|
- if (spec->num_cvts >= MAX_HDMI_CVTS) {
|
|
|
- snd_printk(KERN_WARNING
|
|
|
- "HDMI: no space for converter %d\n", nid);
|
|
|
- return -E2BIG;
|
|
|
+ for (i = 0; i < spec->num_pins; i++)
|
|
|
+ if (nid == spec->pin_cvt[i]) {
|
|
|
+ found_pin = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!found_pin) {
|
|
|
+ snd_printdd("HDMI: Skipping node %d (no connection)\n", nid);
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS))
|
|
|
+ return -E2BIG;
|
|
|
+
|
|
|
spec->cvt[spec->num_cvts] = nid;
|
|
|
spec->num_cvts++;
|
|
|
|
|
@@ -931,6 +936,8 @@ static int hdmi_parse_codec(struct hda_codec *codec)
|
|
|
{
|
|
|
hda_nid_t nid;
|
|
|
int i, nodes;
|
|
|
+ int num_tmp_cvts = 0;
|
|
|
+ hda_nid_t tmp_cvt[MAX_HDMI_CVTS];
|
|
|
|
|
|
nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
|
|
|
if (!nid || nodes < 0) {
|
|
@@ -941,6 +948,7 @@ static int hdmi_parse_codec(struct hda_codec *codec)
|
|
|
for (i = 0; i < nodes; i++, nid++) {
|
|
|
unsigned int caps;
|
|
|
unsigned int type;
|
|
|
+ unsigned int config;
|
|
|
|
|
|
caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
|
|
|
type = get_wcaps_type(caps);
|
|
@@ -950,17 +958,32 @@ static int hdmi_parse_codec(struct hda_codec *codec)
|
|
|
|
|
|
switch (type) {
|
|
|
case AC_WID_AUD_OUT:
|
|
|
- hdmi_add_cvt(codec, nid);
|
|
|
+ if (num_tmp_cvts >= MAX_HDMI_CVTS) {
|
|
|
+ snd_printk(KERN_WARNING
|
|
|
+ "HDMI: no space for converter %d\n", nid);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ tmp_cvt[num_tmp_cvts] = nid;
|
|
|
+ num_tmp_cvts++;
|
|
|
break;
|
|
|
case AC_WID_PIN:
|
|
|
caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
|
|
|
if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
|
|
|
continue;
|
|
|
+
|
|
|
+ config = snd_hda_codec_read(codec, nid, 0,
|
|
|
+ AC_VERB_GET_CONFIG_DEFAULT, 0);
|
|
|
+ if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
|
|
|
+ continue;
|
|
|
+
|
|
|
hdmi_add_pin(codec, nid);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ for (i = 0; i < num_tmp_cvts; i++)
|
|
|
+ hdmi_add_cvt(codec, tmp_cvt[i]);
|
|
|
+
|
|
|
/*
|
|
|
* G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
|
|
|
* can be lost and presence sense verb will become inaccurate if the
|