aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c103
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 */
1523int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl) 1523int 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 */
1721int 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