Loading sound/pci/hda/patch_intelhdmi.c +119 −1 Original line number Diff line number Diff line Loading @@ -213,6 +213,10 @@ static struct cea_channel_speaker_allocation channel_allocations[] = { }; /* * HDA/HDMI auto parsing */ static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) { int i; Loading @@ -225,6 +229,113 @@ static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) return -EINVAL; } static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) { struct intel_hdmi_spec *spec = codec->spec; hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; int conn_len, curr; int index; if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { snd_printk(KERN_WARNING "HDMI: pin %d wcaps %#x " "does not support connection list\n", pin_nid, get_wcaps(codec, pin_nid)); return -EINVAL; } conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, HDA_MAX_CONNECTIONS); if (conn_len > 1) curr = snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_CONNECT_SEL, 0); else curr = 0; index = hda_node_index(spec->pin, pin_nid); if (index < 0) return -EINVAL; spec->pin_cvt[index] = conn_list[curr]; return 0; } static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) { struct intel_hdmi_spec *spec = codec->spec; if (spec->num_pins >= INTEL_HDMI_PINS) { snd_printk(KERN_WARNING "HDMI: no space for pin %d \n", pin_nid); return -EINVAL; } 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 intel_hdmi_read_pin_conn(codec, pin_nid); } static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) { struct intel_hdmi_spec *spec = codec->spec; if (spec->num_cvts >= INTEL_HDMI_CVTS) { snd_printk(KERN_WARNING "HDMI: no space for converter %d \n", nid); return -EINVAL; } spec->cvt[spec->num_cvts] = nid; spec->num_cvts++; return 0; } static int intel_hdmi_parse_codec(struct hda_codec *codec) { hda_nid_t nid; int i, nodes; nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); if (!nid || nodes < 0) { snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); return -EINVAL; } for (i = 0; i < nodes; i++, nid++) { unsigned int caps; unsigned int type; caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); type = get_wcaps_type(caps); if (!(caps & AC_WCAP_DIGITAL)) continue; switch (type) { case AC_WID_AUD_OUT: if (intel_hdmi_add_cvt(codec, nid) < 0) return -EINVAL; break; case AC_WID_PIN: caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); if (!(caps & AC_PINCAP_HDMI)) continue; if (intel_hdmi_add_pin(codec, nid) < 0) return -EINVAL; break; } } return 0; } /* * HDMI routines */ Loading Loading @@ -756,8 +867,15 @@ static int do_patch_intel_hdmi(struct hda_codec *codec, int spec_id) if (spec == NULL) return -ENOMEM; *spec = static_specs[spec_id]; codec->spec = spec; if (intel_hdmi_parse_codec(codec) < 0) { codec->spec = NULL; kfree(spec); return -EINVAL; } if (memcmp(spec, static_specs + spec_id, sizeof(*spec))) snd_printk(KERN_WARNING "HDMI: auto parse disagree with known config\n"); codec->patch_ops = intel_hdmi_patch_ops; for (i = 0; i < spec->num_pins; i++) Loading Loading
sound/pci/hda/patch_intelhdmi.c +119 −1 Original line number Diff line number Diff line Loading @@ -213,6 +213,10 @@ static struct cea_channel_speaker_allocation channel_allocations[] = { }; /* * HDA/HDMI auto parsing */ static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) { int i; Loading @@ -225,6 +229,113 @@ static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) return -EINVAL; } static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) { struct intel_hdmi_spec *spec = codec->spec; hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; int conn_len, curr; int index; if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { snd_printk(KERN_WARNING "HDMI: pin %d wcaps %#x " "does not support connection list\n", pin_nid, get_wcaps(codec, pin_nid)); return -EINVAL; } conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, HDA_MAX_CONNECTIONS); if (conn_len > 1) curr = snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_CONNECT_SEL, 0); else curr = 0; index = hda_node_index(spec->pin, pin_nid); if (index < 0) return -EINVAL; spec->pin_cvt[index] = conn_list[curr]; return 0; } static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) { struct intel_hdmi_spec *spec = codec->spec; if (spec->num_pins >= INTEL_HDMI_PINS) { snd_printk(KERN_WARNING "HDMI: no space for pin %d \n", pin_nid); return -EINVAL; } 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 intel_hdmi_read_pin_conn(codec, pin_nid); } static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) { struct intel_hdmi_spec *spec = codec->spec; if (spec->num_cvts >= INTEL_HDMI_CVTS) { snd_printk(KERN_WARNING "HDMI: no space for converter %d \n", nid); return -EINVAL; } spec->cvt[spec->num_cvts] = nid; spec->num_cvts++; return 0; } static int intel_hdmi_parse_codec(struct hda_codec *codec) { hda_nid_t nid; int i, nodes; nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); if (!nid || nodes < 0) { snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); return -EINVAL; } for (i = 0; i < nodes; i++, nid++) { unsigned int caps; unsigned int type; caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); type = get_wcaps_type(caps); if (!(caps & AC_WCAP_DIGITAL)) continue; switch (type) { case AC_WID_AUD_OUT: if (intel_hdmi_add_cvt(codec, nid) < 0) return -EINVAL; break; case AC_WID_PIN: caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); if (!(caps & AC_PINCAP_HDMI)) continue; if (intel_hdmi_add_pin(codec, nid) < 0) return -EINVAL; break; } } return 0; } /* * HDMI routines */ Loading Loading @@ -756,8 +867,15 @@ static int do_patch_intel_hdmi(struct hda_codec *codec, int spec_id) if (spec == NULL) return -ENOMEM; *spec = static_specs[spec_id]; codec->spec = spec; if (intel_hdmi_parse_codec(codec) < 0) { codec->spec = NULL; kfree(spec); return -EINVAL; } if (memcmp(spec, static_specs + spec_id, sizeof(*spec))) snd_printk(KERN_WARNING "HDMI: auto parse disagree with known config\n"); codec->patch_ops = intel_hdmi_patch_ops; for (i = 0; i < spec->num_pins; i++) Loading