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.c94
1 files changed, 70 insertions, 24 deletions
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 488fd9ade1ba..460fb2ef7e39 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -65,6 +65,7 @@ struct cs_spec {
65 65
66/* available models */ 66/* available models */
67enum { 67enum {
68 CS420X_MBP53,
68 CS420X_MBP55, 69 CS420X_MBP55,
69 CS420X_IMAC27, 70 CS420X_IMAC27,
70 CS420X_AUTO, 71 CS420X_AUTO,
@@ -329,12 +330,12 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx)
329{ 330{
330 struct cs_spec *spec = codec->spec; 331 struct cs_spec *spec = codec->spec;
331 struct auto_pin_cfg *cfg = &spec->autocfg; 332 struct auto_pin_cfg *cfg = &spec->autocfg;
332 hda_nid_t pin = cfg->input_pins[idx]; 333 hda_nid_t pin = cfg->inputs[idx].pin;
333 unsigned int val = snd_hda_query_pin_caps(codec, pin); 334 unsigned int val = snd_hda_query_pin_caps(codec, pin);
334 if (!(val & AC_PINCAP_PRES_DETECT)) 335 if (!(val & AC_PINCAP_PRES_DETECT))
335 return 0; 336 return 0;
336 val = snd_hda_codec_get_pincfg(codec, pin); 337 val = snd_hda_codec_get_pincfg(codec, pin);
337 return (get_defcfg_connect(val) == AC_JACK_PORT_COMPLEX); 338 return (snd_hda_get_input_pin_attr(val) != INPUT_PIN_ATTR_INT);
338} 339}
339 340
340static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, 341static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
@@ -424,10 +425,8 @@ static int parse_input(struct hda_codec *codec)
424 struct auto_pin_cfg *cfg = &spec->autocfg; 425 struct auto_pin_cfg *cfg = &spec->autocfg;
425 int i; 426 int i;
426 427
427 for (i = 0; i < AUTO_PIN_LAST; i++) { 428 for (i = 0; i < cfg->num_inputs; i++) {
428 hda_nid_t pin = cfg->input_pins[i]; 429 hda_nid_t pin = cfg->inputs[i].pin;
429 if (!pin)
430 continue;
431 spec->input_idx[spec->num_inputs] = i; 430 spec->input_idx[spec->num_inputs] = i;
432 spec->capsrc_idx[i] = spec->num_inputs++; 431 spec->capsrc_idx[i] = spec->num_inputs++;
433 spec->cur_input = i; 432 spec->cur_input = i;
@@ -438,16 +437,17 @@ static int parse_input(struct hda_codec *codec)
438 437
439 /* check whether the automatic mic switch is available */ 438 /* check whether the automatic mic switch is available */
440 if (spec->num_inputs == 2 && 439 if (spec->num_inputs == 2 &&
441 spec->adc_nid[AUTO_PIN_MIC] && spec->adc_nid[AUTO_PIN_FRONT_MIC]) { 440 cfg->inputs[0].type == AUTO_PIN_MIC &&
442 if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_FRONT_MIC])) { 441 cfg->inputs[1].type == AUTO_PIN_MIC) {
443 if (!is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { 442 if (is_ext_mic(codec, cfg->inputs[0].pin)) {
443 if (!is_ext_mic(codec, cfg->inputs[1].pin)) {
444 spec->mic_detect = 1; 444 spec->mic_detect = 1;
445 spec->automic_idx = AUTO_PIN_FRONT_MIC; 445 spec->automic_idx = 0;
446 } 446 }
447 } else { 447 } else {
448 if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { 448 if (is_ext_mic(codec, cfg->inputs[1].pin)) {
449 spec->mic_detect = 1; 449 spec->mic_detect = 1;
450 spec->automic_idx = AUTO_PIN_MIC; 450 spec->automic_idx = 1;
451 } 451 }
452 } 452 }
453 } 453 }
@@ -674,6 +674,7 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol,
674{ 674{
675 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 675 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
676 struct cs_spec *spec = codec->spec; 676 struct cs_spec *spec = codec->spec;
677 struct auto_pin_cfg *cfg = &spec->autocfg;
677 unsigned int idx; 678 unsigned int idx;
678 679
679 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 680 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -682,7 +683,8 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol,
682 if (uinfo->value.enumerated.item >= spec->num_inputs) 683 if (uinfo->value.enumerated.item >= spec->num_inputs)
683 uinfo->value.enumerated.item = spec->num_inputs - 1; 684 uinfo->value.enumerated.item = spec->num_inputs - 1;
684 idx = spec->input_idx[uinfo->value.enumerated.item]; 685 idx = spec->input_idx[uinfo->value.enumerated.item];
685 strcpy(uinfo->value.enumerated.name, auto_pin_cfg_labels[idx]); 686 strcpy(uinfo->value.enumerated.name,
687 hda_get_input_pin_label(codec, cfg->inputs[idx].pin, 1));
686 return 0; 688 return 0;
687} 689}
688 690
@@ -740,6 +742,27 @@ static struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec,
740 return bind; 742 return bind;
741} 743}
742 744
745/* add a (input-boost) volume control to the given input pin */
746static int add_input_volume_control(struct hda_codec *codec,
747 struct auto_pin_cfg *cfg,
748 int item)
749{
750 hda_nid_t pin = cfg->inputs[item].pin;
751 u32 caps;
752 const char *label;
753 struct snd_kcontrol *kctl;
754
755 if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP))
756 return 0;
757 caps = query_amp_caps(codec, pin, HDA_INPUT);
758 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
759 if (caps <= 1)
760 return 0;
761 label = hda_get_autocfg_input_label(codec, cfg, item);
762 return add_volume(codec, label, 0,
763 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl);
764}
765
743static int build_input(struct hda_codec *codec) 766static int build_input(struct hda_codec *codec)
744{ 767{
745 struct cs_spec *spec = codec->spec; 768 struct cs_spec *spec = codec->spec;
@@ -779,6 +802,12 @@ static int build_input(struct hda_codec *codec)
779 return err; 802 return err;
780 } 803 }
781 804
805 for (i = 0; i < spec->num_inputs; i++) {
806 err = add_input_volume_control(codec, &spec->autocfg, i);
807 if (err < 0)
808 return err;
809 }
810
782 return 0; 811 return 0;
783} 812}
784 813
@@ -838,7 +867,8 @@ static void cs_automute(struct hda_codec *codec)
838 AC_VERB_SET_PIN_WIDGET_CONTROL, 867 AC_VERB_SET_PIN_WIDGET_CONTROL,
839 hp_present ? 0 : PIN_OUT); 868 hp_present ? 0 : PIN_OUT);
840 } 869 }
841 if (spec->board_config == CS420X_MBP55 || 870 if (spec->board_config == CS420X_MBP53 ||
871 spec->board_config == CS420X_MBP55 ||
842 spec->board_config == CS420X_IMAC27) { 872 spec->board_config == CS420X_IMAC27) {
843 unsigned int gpio = hp_present ? 0x02 : 0x08; 873 unsigned int gpio = hp_present ? 0x02 : 0x08;
844 snd_hda_codec_write(codec, 0x01, 0, 874 snd_hda_codec_write(codec, 0x01, 0,
@@ -853,15 +883,12 @@ static void cs_automic(struct hda_codec *codec)
853 hda_nid_t nid; 883 hda_nid_t nid;
854 unsigned int present; 884 unsigned int present;
855 885
856 nid = cfg->input_pins[spec->automic_idx]; 886 nid = cfg->inputs[spec->automic_idx].pin;
857 present = snd_hda_jack_detect(codec, nid); 887 present = snd_hda_jack_detect(codec, nid);
858 if (present) 888 if (present)
859 change_cur_input(codec, spec->automic_idx, 0); 889 change_cur_input(codec, spec->automic_idx, 0);
860 else { 890 else
861 unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? 891 change_cur_input(codec, !spec->automic_idx, 0);
862 AUTO_PIN_FRONT_MIC : AUTO_PIN_MIC;
863 change_cur_input(codec, imic, 0);
864 }
865} 892}
866 893
867/* 894/*
@@ -918,14 +945,14 @@ static void init_input(struct hda_codec *codec)
918 unsigned int coef; 945 unsigned int coef;
919 int i; 946 int i;
920 947
921 for (i = 0; i < AUTO_PIN_LAST; i++) { 948 for (i = 0; i < cfg->num_inputs; i++) {
922 unsigned int ctl; 949 unsigned int ctl;
923 hda_nid_t pin = cfg->input_pins[i]; 950 hda_nid_t pin = cfg->inputs[i].pin;
924 if (!pin || !spec->adc_nid[i]) 951 if (!spec->adc_nid[i])
925 continue; 952 continue;
926 /* set appropriate pin control and mute first */ 953 /* set appropriate pin control and mute first */
927 ctl = PIN_IN; 954 ctl = PIN_IN;
928 if (i <= AUTO_PIN_FRONT_MIC) { 955 if (cfg->inputs[i].type == AUTO_PIN_MIC) {
929 unsigned int caps = snd_hda_query_pin_caps(codec, pin); 956 unsigned int caps = snd_hda_query_pin_caps(codec, pin);
930 caps >>= AC_PINCAP_VREF_SHIFT; 957 caps >>= AC_PINCAP_VREF_SHIFT;
931 if (caps & AC_PINCAP_VREF_80) 958 if (caps & AC_PINCAP_VREF_80)
@@ -1130,6 +1157,7 @@ static int cs_parse_auto_config(struct hda_codec *codec)
1130} 1157}
1131 1158
1132static const char *cs420x_models[CS420X_MODELS] = { 1159static const char *cs420x_models[CS420X_MODELS] = {
1160 [CS420X_MBP53] = "mbp53",
1133 [CS420X_MBP55] = "mbp55", 1161 [CS420X_MBP55] = "mbp55",
1134 [CS420X_IMAC27] = "imac27", 1162 [CS420X_IMAC27] = "imac27",
1135 [CS420X_AUTO] = "auto", 1163 [CS420X_AUTO] = "auto",
@@ -1137,7 +1165,9 @@ static const char *cs420x_models[CS420X_MODELS] = {
1137 1165
1138 1166
1139static struct snd_pci_quirk cs420x_cfg_tbl[] = { 1167static struct snd_pci_quirk cs420x_cfg_tbl[] = {
1168 SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53),
1140 SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), 1169 SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
1170 SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55),
1141 SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), 1171 SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),
1142 {} /* terminator */ 1172 {} /* terminator */
1143}; 1173};
@@ -1147,6 +1177,20 @@ struct cs_pincfg {
1147 u32 val; 1177 u32 val;
1148}; 1178};
1149 1179
1180static struct cs_pincfg mbp53_pincfgs[] = {
1181 { 0x09, 0x012b4050 },
1182 { 0x0a, 0x90100141 },
1183 { 0x0b, 0x90100140 },
1184 { 0x0c, 0x018b3020 },
1185 { 0x0d, 0x90a00110 },
1186 { 0x0e, 0x400000f0 },
1187 { 0x0f, 0x01cbe030 },
1188 { 0x10, 0x014be060 },
1189 { 0x12, 0x400000f0 },
1190 { 0x15, 0x400000f0 },
1191 {} /* terminator */
1192};
1193
1150static struct cs_pincfg mbp55_pincfgs[] = { 1194static struct cs_pincfg mbp55_pincfgs[] = {
1151 { 0x09, 0x012b4030 }, 1195 { 0x09, 0x012b4030 },
1152 { 0x0a, 0x90100121 }, 1196 { 0x0a, 0x90100121 },
@@ -1176,6 +1220,7 @@ static struct cs_pincfg imac27_pincfgs[] = {
1176}; 1220};
1177 1221
1178static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { 1222static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
1223 [CS420X_MBP53] = mbp53_pincfgs,
1179 [CS420X_MBP55] = mbp55_pincfgs, 1224 [CS420X_MBP55] = mbp55_pincfgs,
1180 [CS420X_IMAC27] = imac27_pincfgs, 1225 [CS420X_IMAC27] = imac27_pincfgs,
1181}; 1226};
@@ -1208,6 +1253,7 @@ static int patch_cs420x(struct hda_codec *codec)
1208 1253
1209 switch (spec->board_config) { 1254 switch (spec->board_config) {
1210 case CS420X_IMAC27: 1255 case CS420X_IMAC27:
1256 case CS420X_MBP53:
1211 case CS420X_MBP55: 1257 case CS420X_MBP55:
1212 /* GPIO1 = headphones */ 1258 /* GPIO1 = headphones */
1213 /* GPIO3 = speakers */ 1259 /* GPIO3 = speakers */