aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_cirrus.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_cirrus.c')
-rw-r--r--sound/pci/hda/patch_cirrus.c187
1 files changed, 118 insertions, 69 deletions
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 70a7abda7e2..0e99357e822 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -26,6 +26,7 @@
26#include <sound/core.h> 26#include <sound/core.h>
27#include "hda_codec.h" 27#include "hda_codec.h"
28#include "hda_local.h" 28#include "hda_local.h"
29#include "hda_jack.h"
29#include <sound/tlv.h> 30#include <sound/tlv.h>
30 31
31/* 32/*
@@ -78,6 +79,7 @@ enum {
78 CS420X_MBP53, 79 CS420X_MBP53,
79 CS420X_MBP55, 80 CS420X_MBP55,
80 CS420X_IMAC27, 81 CS420X_IMAC27,
82 CS420X_IMAC27_122,
81 CS420X_APPLE, 83 CS420X_APPLE,
82 CS420X_AUTO, 84 CS420X_AUTO,
83 CS420X_MODELS 85 CS420X_MODELS
@@ -137,7 +139,7 @@ enum {
137*/ 139*/
138#define CS4210_DAC_NID 0x02 140#define CS4210_DAC_NID 0x02
139#define CS4210_ADC_NID 0x03 141#define CS4210_ADC_NID 0x03
140#define CS421X_VENDOR_NID 0x0B 142#define CS4210_VENDOR_NID 0x0B
141#define CS421X_DMIC_PIN_NID 0x09 /* Port E */ 143#define CS421X_DMIC_PIN_NID 0x09 /* Port E */
142#define CS421X_SPDIF_PIN_NID 0x0A /* Port H */ 144#define CS421X_SPDIF_PIN_NID 0x0A /* Port H */
143 145
@@ -148,6 +150,10 @@ enum {
148 150
149#define SPDIF_EVENT 0x04 151#define SPDIF_EVENT 0x04
150 152
153/* Cirrus Logic CS4213 is like CS4210 but does not have SPDIF input/output */
154#define CS4213_VENDOR_NID 0x09
155
156
151static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx) 157static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
152{ 158{
153 struct cs_spec *spec = codec->spec; 159 struct cs_spec *spec = codec->spec;
@@ -721,8 +727,9 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol,
721 if (uinfo->value.enumerated.item >= spec->num_inputs) 727 if (uinfo->value.enumerated.item >= spec->num_inputs)
722 uinfo->value.enumerated.item = spec->num_inputs - 1; 728 uinfo->value.enumerated.item = spec->num_inputs - 1;
723 idx = spec->input_idx[uinfo->value.enumerated.item]; 729 idx = spec->input_idx[uinfo->value.enumerated.item];
724 strcpy(uinfo->value.enumerated.name, 730 snd_hda_get_pin_label(codec, cfg->inputs[idx].pin, cfg,
725 hda_get_input_pin_label(codec, cfg->inputs[idx].pin, 1)); 731 uinfo->value.enumerated.name,
732 sizeof(uinfo->value.enumerated.name), NULL);
726 return 0; 733 return 0;
727} 734}
728 735
@@ -920,16 +927,14 @@ static void cs_automute(struct hda_codec *codec)
920 927
921 /* mute speakers if spdif or hp jack is plugged in */ 928 /* mute speakers if spdif or hp jack is plugged in */
922 for (i = 0; i < cfg->speaker_outs; i++) { 929 for (i = 0; i < cfg->speaker_outs; i++) {
930 int pin_ctl = hp_present ? 0 : PIN_OUT;
931 /* detect on spdif is specific to CS4210 */
932 if (spdif_present && (spec->vendor_nid == CS4210_VENDOR_NID))
933 pin_ctl = 0;
934
923 nid = cfg->speaker_pins[i]; 935 nid = cfg->speaker_pins[i];
924 snd_hda_codec_write(codec, nid, 0, 936 snd_hda_codec_write(codec, nid, 0,
925 AC_VERB_SET_PIN_WIDGET_CONTROL, 937 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_ctl);
926 hp_present ? 0 : PIN_OUT);
927 /* detect on spdif is specific to CS421x */
928 if (spec->vendor_nid == CS421X_VENDOR_NID) {
929 snd_hda_codec_write(codec, nid, 0,
930 AC_VERB_SET_PIN_WIDGET_CONTROL,
931 spdif_present ? 0 : PIN_OUT);
932 }
933 } 938 }
934 if (spec->gpio_eapd_hp) { 939 if (spec->gpio_eapd_hp) {
935 unsigned int gpio = hp_present ? 940 unsigned int gpio = hp_present ?
@@ -938,8 +943,8 @@ static void cs_automute(struct hda_codec *codec)
938 AC_VERB_SET_GPIO_DATA, gpio); 943 AC_VERB_SET_GPIO_DATA, gpio);
939 } 944 }
940 945
941 /* specific to CS421x */ 946 /* specific to CS4210 */
942 if (spec->vendor_nid == CS421X_VENDOR_NID) { 947 if (spec->vendor_nid == CS4210_VENDOR_NID) {
943 /* mute HPs if spdif jack (SENSE_B) is present */ 948 /* mute HPs if spdif jack (SENSE_B) is present */
944 for (i = 0; i < cfg->hp_outs; i++) { 949 for (i = 0; i < cfg->hp_outs; i++) {
945 nid = cfg->hp_pins[i]; 950 nid = cfg->hp_pins[i];
@@ -976,7 +981,12 @@ static void cs_automic(struct hda_codec *codec)
976 present = snd_hda_jack_detect(codec, nid); 981 present = snd_hda_jack_detect(codec, nid);
977 982
978 /* specific to CS421x, single ADC */ 983 /* specific to CS421x, single ADC */
979 if (spec->vendor_nid == CS421X_VENDOR_NID) { 984 if (spec->vendor_nid == CS420X_VENDOR_NID) {
985 if (present)
986 change_cur_input(codec, spec->automic_idx, 0);
987 else
988 change_cur_input(codec, !spec->automic_idx, 0);
989 } else {
980 if (present) { 990 if (present) {
981 spec->last_input = spec->cur_input; 991 spec->last_input = spec->cur_input;
982 spec->cur_input = spec->automic_idx; 992 spec->cur_input = spec->automic_idx;
@@ -984,11 +994,6 @@ static void cs_automic(struct hda_codec *codec)
984 spec->cur_input = spec->last_input; 994 spec->cur_input = spec->last_input;
985 } 995 }
986 cs_update_input_select(codec); 996 cs_update_input_select(codec);
987 } else {
988 if (present)
989 change_cur_input(codec, spec->automic_idx, 0);
990 else
991 change_cur_input(codec, !spec->automic_idx, 0);
992 } 997 }
993} 998}
994 999
@@ -1027,9 +1032,7 @@ static void init_output(struct hda_codec *codec)
1027 if (!cfg->speaker_outs) 1032 if (!cfg->speaker_outs)
1028 continue; 1033 continue;
1029 if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { 1034 if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
1030 snd_hda_codec_write(codec, nid, 0, 1035 snd_hda_jack_detect_enable(codec, nid, HP_EVENT);
1031 AC_VERB_SET_UNSOLICITED_ENABLE,
1032 AC_USRSP_EN | HP_EVENT);
1033 spec->hp_detect = 1; 1036 spec->hp_detect = 1;
1034 } 1037 }
1035 } 1038 }
@@ -1070,19 +1073,10 @@ static void init_input(struct hda_codec *codec)
1070 AC_VERB_SET_AMP_GAIN_MUTE, 1073 AC_VERB_SET_AMP_GAIN_MUTE,
1071 AMP_IN_MUTE(spec->adc_idx[i])); 1074 AMP_IN_MUTE(spec->adc_idx[i]));
1072 if (spec->mic_detect && spec->automic_idx == i) 1075 if (spec->mic_detect && spec->automic_idx == i)
1073 snd_hda_codec_write(codec, pin, 0, 1076 snd_hda_jack_detect_enable(codec, pin, MIC_EVENT);
1074 AC_VERB_SET_UNSOLICITED_ENABLE,
1075 AC_USRSP_EN | MIC_EVENT);
1076 } 1077 }
1077 /* specific to CS421x */ 1078 /* CS420x has multiple ADC, CS421x has single ADC */
1078 if (spec->vendor_nid == CS421X_VENDOR_NID) { 1079 if (spec->vendor_nid == CS420X_VENDOR_NID) {
1079 if (spec->mic_detect)
1080 cs_automic(codec);
1081 else {
1082 spec->cur_adc = spec->adc_nid[spec->cur_input];
1083 cs_update_input_select(codec);
1084 }
1085 } else {
1086 change_cur_input(codec, spec->cur_input, 1); 1080 change_cur_input(codec, spec->cur_input, 1);
1087 if (spec->mic_detect) 1081 if (spec->mic_detect)
1088 cs_automic(codec); 1082 cs_automic(codec);
@@ -1096,6 +1090,13 @@ static void init_input(struct hda_codec *codec)
1096 * selected in IDX_SPDIF_CTL. 1090 * selected in IDX_SPDIF_CTL.
1097 */ 1091 */
1098 cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); 1092 cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
1093 } else {
1094 if (spec->mic_detect)
1095 cs_automic(codec);
1096 else {
1097 spec->cur_adc = spec->adc_nid[spec->cur_input];
1098 cs_update_input_select(codec);
1099 }
1099 } 1100 }
1100} 1101}
1101 1102
@@ -1200,11 +1201,14 @@ static int cs_init(struct hda_codec *codec)
1200 init_output(codec); 1201 init_output(codec);
1201 init_input(codec); 1202 init_input(codec);
1202 init_digital(codec); 1203 init_digital(codec);
1204 snd_hda_jack_report_sync(codec);
1205
1203 return 0; 1206 return 0;
1204} 1207}
1205 1208
1206static int cs_build_controls(struct hda_codec *codec) 1209static int cs_build_controls(struct hda_codec *codec)
1207{ 1210{
1211 struct cs_spec *spec = codec->spec;
1208 int err; 1212 int err;
1209 1213
1210 err = build_output(codec); 1214 err = build_output(codec);
@@ -1219,7 +1223,15 @@ static int cs_build_controls(struct hda_codec *codec)
1219 err = build_digital_input(codec); 1223 err = build_digital_input(codec);
1220 if (err < 0) 1224 if (err < 0)
1221 return err; 1225 return err;
1222 return cs_init(codec); 1226 err = cs_init(codec);
1227 if (err < 0)
1228 return err;
1229
1230 err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
1231 if (err < 0)
1232 return err;
1233
1234 return 0;
1223} 1235}
1224 1236
1225static void cs_free(struct hda_codec *codec) 1237static void cs_free(struct hda_codec *codec)
@@ -1232,7 +1244,7 @@ static void cs_free(struct hda_codec *codec)
1232 1244
1233static void cs_unsol_event(struct hda_codec *codec, unsigned int res) 1245static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
1234{ 1246{
1235 switch ((res >> 26) & 0x7f) { 1247 switch (snd_hda_jack_get_action(codec, res >> 26)) {
1236 case HP_EVENT: 1248 case HP_EVENT:
1237 cs_automute(codec); 1249 cs_automute(codec);
1238 break; 1250 break;
@@ -1240,6 +1252,7 @@ static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
1240 cs_automic(codec); 1252 cs_automic(codec);
1241 break; 1253 break;
1242 } 1254 }
1255 snd_hda_jack_report_sync(codec);
1243} 1256}
1244 1257
1245static const struct hda_codec_ops cs_patch_ops = { 1258static const struct hda_codec_ops cs_patch_ops = {
@@ -1278,6 +1291,7 @@ static const char * const cs420x_models[CS420X_MODELS] = {
1278 [CS420X_MBP53] = "mbp53", 1291 [CS420X_MBP53] = "mbp53",
1279 [CS420X_MBP55] = "mbp55", 1292 [CS420X_MBP55] = "mbp55",
1280 [CS420X_IMAC27] = "imac27", 1293 [CS420X_IMAC27] = "imac27",
1294 [CS420X_IMAC27_122] = "imac27_122",
1281 [CS420X_APPLE] = "apple", 1295 [CS420X_APPLE] = "apple",
1282 [CS420X_AUTO] = "auto", 1296 [CS420X_AUTO] = "auto",
1283}; 1297};
@@ -1294,6 +1308,7 @@ static const struct snd_pci_quirk cs420x_cfg_tbl[] = {
1294}; 1308};
1295 1309
1296static const struct snd_pci_quirk cs420x_codec_cfg_tbl[] = { 1310static const struct snd_pci_quirk cs420x_codec_cfg_tbl[] = {
1311 SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122),
1297 SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), 1312 SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
1298 {} /* terminator */ 1313 {} /* terminator */
1299}; 1314};
@@ -1393,6 +1408,12 @@ static int patch_cs420x(struct hda_codec *codec)
1393 spec->gpio_mask = spec->gpio_dir = 1408 spec->gpio_mask = spec->gpio_dir =
1394 spec->gpio_eapd_hp | spec->gpio_eapd_speaker; 1409 spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
1395 break; 1410 break;
1411 case CS420X_IMAC27_122:
1412 spec->gpio_eapd_hp = 4; /* GPIO2 = headphones */
1413 spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */
1414 spec->gpio_mask = spec->gpio_dir =
1415 spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
1416 break;
1396 } 1417 }
1397 1418
1398 err = cs_parse_auto_config(codec); 1419 err = cs_parse_auto_config(codec);
@@ -1557,7 +1578,7 @@ static const struct snd_kcontrol_new cs421x_speaker_bost_ctl = {
1557 .tlv = { .p = cs421x_speaker_boost_db_scale }, 1578 .tlv = { .p = cs421x_speaker_boost_db_scale },
1558}; 1579};
1559 1580
1560static void cs421x_pinmux_init(struct hda_codec *codec) 1581static void cs4210_pinmux_init(struct hda_codec *codec)
1561{ 1582{
1562 struct cs_spec *spec = codec->spec; 1583 struct cs_spec *spec = codec->spec;
1563 unsigned int def_conf, coef; 1584 unsigned int def_conf, coef;
@@ -1602,10 +1623,7 @@ static void init_cs421x_digital(struct hda_codec *codec)
1602 if (!cfg->speaker_outs) 1623 if (!cfg->speaker_outs)
1603 continue; 1624 continue;
1604 if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { 1625 if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
1605 1626 snd_hda_jack_detect_enable(codec, nid, SPDIF_EVENT);
1606 snd_hda_codec_write(codec, nid, 0,
1607 AC_VERB_SET_UNSOLICITED_ENABLE,
1608 AC_USRSP_EN | SPDIF_EVENT);
1609 spec->spdif_detect = 1; 1627 spec->spdif_detect = 1;
1610 } 1628 }
1611 } 1629 }
@@ -1615,10 +1633,11 @@ static int cs421x_init(struct hda_codec *codec)
1615{ 1633{
1616 struct cs_spec *spec = codec->spec; 1634 struct cs_spec *spec = codec->spec;
1617 1635
1618 snd_hda_sequence_write(codec, cs421x_coef_init_verbs); 1636 if (spec->vendor_nid == CS4210_VENDOR_NID) {
1619 snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes); 1637 snd_hda_sequence_write(codec, cs421x_coef_init_verbs);
1620 1638 snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes);
1621 cs421x_pinmux_init(codec); 1639 cs4210_pinmux_init(codec);
1640 }
1622 1641
1623 if (spec->gpio_mask) { 1642 if (spec->gpio_mask) {
1624 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK, 1643 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
@@ -1632,6 +1651,7 @@ static int cs421x_init(struct hda_codec *codec)
1632 init_output(codec); 1651 init_output(codec);
1633 init_input(codec); 1652 init_input(codec);
1634 init_cs421x_digital(codec); 1653 init_cs421x_digital(codec);
1654 snd_hda_jack_report_sync(codec);
1635 1655
1636 return 0; 1656 return 0;
1637} 1657}
@@ -1771,32 +1791,21 @@ static int build_cs421x_output(struct hda_codec *codec)
1771 struct auto_pin_cfg *cfg = &spec->autocfg; 1791 struct auto_pin_cfg *cfg = &spec->autocfg;
1772 struct snd_kcontrol *kctl; 1792 struct snd_kcontrol *kctl;
1773 int err; 1793 int err;
1774 char *name = "HP/Speakers"; 1794 char *name = "Master";
1775 1795
1776 fix_volume_caps(codec, dac); 1796 fix_volume_caps(codec, dac);
1777 if (!spec->vmaster_sw) {
1778 err = add_vmaster(codec, dac);
1779 if (err < 0)
1780 return err;
1781 }
1782 1797
1783 err = add_mute(codec, name, 0, 1798 err = add_mute(codec, name, 0,
1784 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl); 1799 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl);
1785 if (err < 0) 1800 if (err < 0)
1786 return err; 1801 return err;
1787 err = snd_ctl_add_slave(spec->vmaster_sw, kctl);
1788 if (err < 0)
1789 return err;
1790 1802
1791 err = add_volume(codec, name, 0, 1803 err = add_volume(codec, name, 0,
1792 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl); 1804 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl);
1793 if (err < 0) 1805 if (err < 0)
1794 return err; 1806 return err;
1795 err = snd_ctl_add_slave(spec->vmaster_vol, kctl);
1796 if (err < 0)
1797 return err;
1798 1807
1799 if (cfg->speaker_outs) { 1808 if (cfg->speaker_outs && (spec->vendor_nid == CS4210_VENDOR_NID)) {
1800 err = snd_hda_ctl_add(codec, 0, 1809 err = snd_hda_ctl_add(codec, 0,
1801 snd_ctl_new1(&cs421x_speaker_bost_ctl, codec)); 1810 snd_ctl_new1(&cs421x_speaker_bost_ctl, codec));
1802 if (err < 0) 1811 if (err < 0)
@@ -1807,6 +1816,7 @@ static int build_cs421x_output(struct hda_codec *codec)
1807 1816
1808static int cs421x_build_controls(struct hda_codec *codec) 1817static int cs421x_build_controls(struct hda_codec *codec)
1809{ 1818{
1819 struct cs_spec *spec = codec->spec;
1810 int err; 1820 int err;
1811 1821
1812 err = build_cs421x_output(codec); 1822 err = build_cs421x_output(codec);
@@ -1818,12 +1828,20 @@ static int cs421x_build_controls(struct hda_codec *codec)
1818 err = build_digital_output(codec); 1828 err = build_digital_output(codec);
1819 if (err < 0) 1829 if (err < 0)
1820 return err; 1830 return err;
1821 return cs421x_init(codec); 1831 err = cs421x_init(codec);
1832 if (err < 0)
1833 return err;
1834
1835 err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
1836 if (err < 0)
1837 return err;
1838
1839 return 0;
1822} 1840}
1823 1841
1824static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) 1842static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
1825{ 1843{
1826 switch ((res >> 26) & 0x3f) { 1844 switch (snd_hda_jack_get_action(codec, res >> 26)) {
1827 case HP_EVENT: 1845 case HP_EVENT:
1828 case SPDIF_EVENT: 1846 case SPDIF_EVENT:
1829 cs_automute(codec); 1847 cs_automute(codec);
@@ -1833,6 +1851,7 @@ static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
1833 cs_automic(codec); 1851 cs_automic(codec);
1834 break; 1852 break;
1835 } 1853 }
1854 snd_hda_jack_report_sync(codec);
1836} 1855}
1837 1856
1838static int parse_cs421x_input(struct hda_codec *codec) 1857static int parse_cs421x_input(struct hda_codec *codec)
@@ -1883,6 +1902,7 @@ static int cs421x_parse_auto_config(struct hda_codec *codec)
1883*/ 1902*/
1884static int cs421x_suspend(struct hda_codec *codec, pm_message_t state) 1903static int cs421x_suspend(struct hda_codec *codec, pm_message_t state)
1885{ 1904{
1905 struct cs_spec *spec = codec->spec;
1886 unsigned int coef; 1906 unsigned int coef;
1887 1907
1888 snd_hda_shutup_pins(codec); 1908 snd_hda_shutup_pins(codec);
@@ -1892,15 +1912,17 @@ static int cs421x_suspend(struct hda_codec *codec, pm_message_t state)
1892 snd_hda_codec_write(codec, CS4210_ADC_NID, 0, 1912 snd_hda_codec_write(codec, CS4210_ADC_NID, 0,
1893 AC_VERB_SET_POWER_STATE, AC_PWRST_D3); 1913 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
1894 1914
1895 coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG); 1915 if (spec->vendor_nid == CS4210_VENDOR_NID) {
1896 coef |= 0x0004; /* PDREF */ 1916 coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
1897 cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef); 1917 coef |= 0x0004; /* PDREF */
1918 cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
1919 }
1898 1920
1899 return 0; 1921 return 0;
1900} 1922}
1901#endif 1923#endif
1902 1924
1903static struct hda_codec_ops cs4210_patch_ops = { 1925static struct hda_codec_ops cs421x_patch_ops = {
1904 .build_controls = cs421x_build_controls, 1926 .build_controls = cs421x_build_controls,
1905 .build_pcms = cs_build_pcms, 1927 .build_pcms = cs_build_pcms,
1906 .init = cs421x_init, 1928 .init = cs421x_init,
@@ -1911,7 +1933,7 @@ static struct hda_codec_ops cs4210_patch_ops = {
1911#endif 1933#endif
1912}; 1934};
1913 1935
1914static int patch_cs421x(struct hda_codec *codec) 1936static int patch_cs4210(struct hda_codec *codec)
1915{ 1937{
1916 struct cs_spec *spec; 1938 struct cs_spec *spec;
1917 int err; 1939 int err;
@@ -1921,7 +1943,7 @@ static int patch_cs421x(struct hda_codec *codec)
1921 return -ENOMEM; 1943 return -ENOMEM;
1922 codec->spec = spec; 1944 codec->spec = spec;
1923 1945
1924 spec->vendor_nid = CS421X_VENDOR_NID; 1946 spec->vendor_nid = CS4210_VENDOR_NID;
1925 1947
1926 spec->board_config = 1948 spec->board_config =
1927 snd_hda_check_board_config(codec, CS421X_MODELS, 1949 snd_hda_check_board_config(codec, CS421X_MODELS,
@@ -1949,14 +1971,39 @@ static int patch_cs421x(struct hda_codec *codec)
1949 is auto-parsed. If GPIO or SENSE_B is forced, DMIC input 1971 is auto-parsed. If GPIO or SENSE_B is forced, DMIC input
1950 is disabled. 1972 is disabled.
1951 */ 1973 */
1952 cs421x_pinmux_init(codec); 1974 cs4210_pinmux_init(codec);
1953 1975
1954 err = cs421x_parse_auto_config(codec); 1976 err = cs421x_parse_auto_config(codec);
1955 if (err < 0) 1977 if (err < 0)
1956 goto error; 1978 goto error;
1957 1979
1958 codec->patch_ops = cs4210_patch_ops; 1980 codec->patch_ops = cs421x_patch_ops;
1981
1982 return 0;
1983
1984 error:
1985 kfree(codec->spec);
1986 codec->spec = NULL;
1987 return err;
1988}
1989
1990static int patch_cs4213(struct hda_codec *codec)
1991{
1992 struct cs_spec *spec;
1993 int err;
1994
1995 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1996 if (!spec)
1997 return -ENOMEM;
1998 codec->spec = spec;
1999
2000 spec->vendor_nid = CS4213_VENDOR_NID;
2001
2002 err = cs421x_parse_auto_config(codec);
2003 if (err < 0)
2004 goto error;
1959 2005
2006 codec->patch_ops = cs421x_patch_ops;
1960 return 0; 2007 return 0;
1961 2008
1962 error: 2009 error:
@@ -1972,13 +2019,15 @@ static int patch_cs421x(struct hda_codec *codec)
1972static const struct hda_codec_preset snd_hda_preset_cirrus[] = { 2019static const struct hda_codec_preset snd_hda_preset_cirrus[] = {
1973 { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x }, 2020 { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x },
1974 { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x }, 2021 { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x },
1975 { .id = 0x10134210, .name = "CS4210", .patch = patch_cs421x }, 2022 { .id = 0x10134210, .name = "CS4210", .patch = patch_cs4210 },
2023 { .id = 0x10134213, .name = "CS4213", .patch = patch_cs4213 },
1976 {} /* terminator */ 2024 {} /* terminator */
1977}; 2025};
1978 2026
1979MODULE_ALIAS("snd-hda-codec-id:10134206"); 2027MODULE_ALIAS("snd-hda-codec-id:10134206");
1980MODULE_ALIAS("snd-hda-codec-id:10134207"); 2028MODULE_ALIAS("snd-hda-codec-id:10134207");
1981MODULE_ALIAS("snd-hda-codec-id:10134210"); 2029MODULE_ALIAS("snd-hda-codec-id:10134210");
2030MODULE_ALIAS("snd-hda-codec-id:10134213");
1982 2031
1983MODULE_LICENSE("GPL"); 2032MODULE_LICENSE("GPL");
1984MODULE_DESCRIPTION("Cirrus Logic HD-audio codec"); 2033MODULE_DESCRIPTION("Cirrus Logic HD-audio codec");