diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 103 |
1 files changed, 101 insertions, 2 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index f62d1d5eb7fa..e2cf02387289 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1520,9 +1520,9 @@ int snd_hda_build_pcms(struct hda_bus *bus) | |||
1520 | * | 1520 | * |
1521 | * If no entries are matching, the function returns a negative value. | 1521 | * If no entries are matching, the function returns a negative value. |
1522 | */ | 1522 | */ |
1523 | int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl) | 1523 | int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl) |
1524 | { | 1524 | { |
1525 | struct hda_board_config *c; | 1525 | const struct hda_board_config *c; |
1526 | 1526 | ||
1527 | if (codec->bus->modelname) { | 1527 | if (codec->bus->modelname) { |
1528 | for (c = tbl; c->modelname || c->pci_subvendor; c++) { | 1528 | for (c = tbl; c->modelname || c->pci_subvendor; c++) { |
@@ -1714,6 +1714,105 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o | |||
1714 | return 0; | 1714 | return 0; |
1715 | } | 1715 | } |
1716 | 1716 | ||
1717 | /* | ||
1718 | * Helper for automatic ping configuration | ||
1719 | */ | ||
1720 | /* parse all pin widgets and store the useful pin nids to cfg */ | ||
1721 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg) | ||
1722 | { | ||
1723 | hda_nid_t nid, nid_start; | ||
1724 | int i, j, nodes; | ||
1725 | short seq, sequences[4], assoc_line_out; | ||
1726 | |||
1727 | memset(cfg, 0, sizeof(*cfg)); | ||
1728 | |||
1729 | memset(sequences, 0, sizeof(sequences)); | ||
1730 | assoc_line_out = 0; | ||
1731 | |||
1732 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); | ||
1733 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | ||
1734 | unsigned int wid_caps = snd_hda_param_read(codec, nid, | ||
1735 | AC_PAR_AUDIO_WIDGET_CAP); | ||
1736 | unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
1737 | unsigned int def_conf; | ||
1738 | short assoc, loc; | ||
1739 | |||
1740 | /* read all default configuration for pin complex */ | ||
1741 | if (wid_type != AC_WID_PIN) | ||
1742 | continue; | ||
1743 | def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
1744 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | ||
1745 | continue; | ||
1746 | loc = get_defcfg_location(def_conf); | ||
1747 | switch (get_defcfg_device(def_conf)) { | ||
1748 | case AC_JACK_LINE_OUT: | ||
1749 | case AC_JACK_SPEAKER: | ||
1750 | seq = get_defcfg_sequence(def_conf); | ||
1751 | assoc = get_defcfg_association(def_conf); | ||
1752 | if (! assoc) | ||
1753 | continue; | ||
1754 | if (! assoc_line_out) | ||
1755 | assoc_line_out = assoc; | ||
1756 | else if (assoc_line_out != assoc) | ||
1757 | continue; | ||
1758 | if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) | ||
1759 | continue; | ||
1760 | cfg->line_out_pins[cfg->line_outs] = nid; | ||
1761 | sequences[cfg->line_outs] = seq; | ||
1762 | cfg->line_outs++; | ||
1763 | break; | ||
1764 | case AC_JACK_HP_OUT: | ||
1765 | cfg->hp_pin = nid; | ||
1766 | break; | ||
1767 | case AC_JACK_MIC_IN: | ||
1768 | if (loc == AC_JACK_LOC_FRONT) | ||
1769 | cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid; | ||
1770 | else | ||
1771 | cfg->input_pins[AUTO_PIN_MIC] = nid; | ||
1772 | break; | ||
1773 | case AC_JACK_LINE_IN: | ||
1774 | if (loc == AC_JACK_LOC_FRONT) | ||
1775 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; | ||
1776 | else | ||
1777 | cfg->input_pins[AUTO_PIN_LINE] = nid; | ||
1778 | break; | ||
1779 | case AC_JACK_CD: | ||
1780 | cfg->input_pins[AUTO_PIN_CD] = nid; | ||
1781 | break; | ||
1782 | case AC_JACK_AUX: | ||
1783 | cfg->input_pins[AUTO_PIN_AUX] = nid; | ||
1784 | break; | ||
1785 | case AC_JACK_SPDIF_OUT: | ||
1786 | cfg->dig_out_pin = nid; | ||
1787 | break; | ||
1788 | case AC_JACK_SPDIF_IN: | ||
1789 | cfg->dig_in_pin = nid; | ||
1790 | break; | ||
1791 | } | ||
1792 | } | ||
1793 | |||
1794 | /* sort by sequence */ | ||
1795 | for (i = 0; i < cfg->line_outs; i++) | ||
1796 | for (j = i + 1; j < cfg->line_outs; j++) | ||
1797 | if (sequences[i] > sequences[j]) { | ||
1798 | seq = sequences[i]; | ||
1799 | sequences[i] = sequences[j]; | ||
1800 | sequences[j] = seq; | ||
1801 | nid = cfg->line_out_pins[i]; | ||
1802 | cfg->line_out_pins[i] = cfg->line_out_pins[j]; | ||
1803 | cfg->line_out_pins[j] = nid; | ||
1804 | } | ||
1805 | |||
1806 | /* Swap surround and CLFE: the association order is front/CLFE/surr/back */ | ||
1807 | if (cfg->line_outs >= 3) { | ||
1808 | nid = cfg->line_out_pins[1]; | ||
1809 | cfg->line_out_pins[1] = cfg->line_out_pins[2]; | ||
1810 | cfg->line_out_pins[2] = nid; | ||
1811 | } | ||
1812 | |||
1813 | return 0; | ||
1814 | } | ||
1815 | |||
1717 | #ifdef CONFIG_PM | 1816 | #ifdef CONFIG_PM |
1718 | /* | 1817 | /* |
1719 | * power management | 1818 | * power management |