diff options
Diffstat (limited to 'sound/pci/hda/patch_cirrus.c')
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 65 |
1 files changed, 43 insertions, 22 deletions
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 8ba306856d38..350ee8ac4153 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -66,6 +66,7 @@ struct cs_spec { | |||
66 | /* available models */ | 66 | /* available models */ |
67 | enum { | 67 | enum { |
68 | CS420X_MBP55, | 68 | CS420X_MBP55, |
69 | CS420X_IMAC27, | ||
69 | CS420X_AUTO, | 70 | CS420X_AUTO, |
70 | CS420X_MODELS | 71 | CS420X_MODELS |
71 | }; | 72 | }; |
@@ -500,7 +501,8 @@ static int add_mute(struct hda_codec *codec, const char *name, int index, | |||
500 | knew.private_value = pval; | 501 | knew.private_value = pval; |
501 | snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); | 502 | snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); |
502 | *kctlp = snd_ctl_new1(&knew, codec); | 503 | *kctlp = snd_ctl_new1(&knew, codec); |
503 | return snd_hda_ctl_add(codec, *kctlp); | 504 | (*kctlp)->id.subdevice = HDA_SUBDEV_AMP_FLAG; |
505 | return snd_hda_ctl_add(codec, 0, *kctlp); | ||
504 | } | 506 | } |
505 | 507 | ||
506 | static int add_volume(struct hda_codec *codec, const char *name, | 508 | static int add_volume(struct hda_codec *codec, const char *name, |
@@ -513,7 +515,8 @@ static int add_volume(struct hda_codec *codec, const char *name, | |||
513 | knew.private_value = pval; | 515 | knew.private_value = pval; |
514 | snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); | 516 | snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); |
515 | *kctlp = snd_ctl_new1(&knew, codec); | 517 | *kctlp = snd_ctl_new1(&knew, codec); |
516 | return snd_hda_ctl_add(codec, *kctlp); | 518 | (*kctlp)->id.subdevice = HDA_SUBDEV_AMP_FLAG; |
519 | return snd_hda_ctl_add(codec, 0, *kctlp); | ||
517 | } | 520 | } |
518 | 521 | ||
519 | static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) | 522 | static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) |
@@ -536,14 +539,14 @@ static int add_vmaster(struct hda_codec *codec, hda_nid_t dac) | |||
536 | 539 | ||
537 | spec->vmaster_sw = | 540 | spec->vmaster_sw = |
538 | snd_ctl_make_virtual_master("Master Playback Switch", NULL); | 541 | snd_ctl_make_virtual_master("Master Playback Switch", NULL); |
539 | err = snd_hda_ctl_add(codec, spec->vmaster_sw); | 542 | err = snd_hda_ctl_add(codec, dac, spec->vmaster_sw); |
540 | if (err < 0) | 543 | if (err < 0) |
541 | return err; | 544 | return err; |
542 | 545 | ||
543 | snd_hda_set_vmaster_tlv(codec, dac, HDA_OUTPUT, tlv); | 546 | snd_hda_set_vmaster_tlv(codec, dac, HDA_OUTPUT, tlv); |
544 | spec->vmaster_vol = | 547 | spec->vmaster_vol = |
545 | snd_ctl_make_virtual_master("Master Playback Volume", tlv); | 548 | snd_ctl_make_virtual_master("Master Playback Volume", tlv); |
546 | err = snd_hda_ctl_add(codec, spec->vmaster_vol); | 549 | err = snd_hda_ctl_add(codec, dac, spec->vmaster_vol); |
547 | if (err < 0) | 550 | if (err < 0) |
548 | return err; | 551 | return err; |
549 | return 0; | 552 | return 0; |
@@ -750,19 +753,27 @@ static int build_input(struct hda_codec *codec) | |||
750 | spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol); | 753 | spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol); |
751 | for (i = 0; i < 2; i++) { | 754 | for (i = 0; i < 2; i++) { |
752 | struct snd_kcontrol *kctl; | 755 | struct snd_kcontrol *kctl; |
756 | int n; | ||
753 | if (!spec->capture_bind[i]) | 757 | if (!spec->capture_bind[i]) |
754 | return -ENOMEM; | 758 | return -ENOMEM; |
755 | kctl = snd_ctl_new1(&cs_capture_ctls[i], codec); | 759 | kctl = snd_ctl_new1(&cs_capture_ctls[i], codec); |
756 | if (!kctl) | 760 | if (!kctl) |
757 | return -ENOMEM; | 761 | return -ENOMEM; |
758 | kctl->private_value = (long)spec->capture_bind[i]; | 762 | kctl->private_value = (long)spec->capture_bind[i]; |
759 | err = snd_hda_ctl_add(codec, kctl); | 763 | err = snd_hda_ctl_add(codec, 0, kctl); |
760 | if (err < 0) | 764 | if (err < 0) |
761 | return err; | 765 | return err; |
766 | for (n = 0; n < AUTO_PIN_LAST; n++) { | ||
767 | if (!spec->adc_nid[n]) | ||
768 | continue; | ||
769 | err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[n]); | ||
770 | if (err < 0) | ||
771 | return err; | ||
772 | } | ||
762 | } | 773 | } |
763 | 774 | ||
764 | if (spec->num_inputs > 1 && !spec->mic_detect) { | 775 | if (spec->num_inputs > 1 && !spec->mic_detect) { |
765 | err = snd_hda_ctl_add(codec, | 776 | err = snd_hda_ctl_add(codec, 0, |
766 | snd_ctl_new1(&cs_capture_source, codec)); | 777 | snd_ctl_new1(&cs_capture_source, codec)); |
767 | if (err < 0) | 778 | if (err < 0) |
768 | return err; | 779 | return err; |
@@ -807,7 +818,7 @@ static void cs_automute(struct hda_codec *codec) | |||
807 | { | 818 | { |
808 | struct cs_spec *spec = codec->spec; | 819 | struct cs_spec *spec = codec->spec; |
809 | struct auto_pin_cfg *cfg = &spec->autocfg; | 820 | struct auto_pin_cfg *cfg = &spec->autocfg; |
810 | unsigned int caps, present, hp_present; | 821 | unsigned int caps, hp_present; |
811 | hda_nid_t nid; | 822 | hda_nid_t nid; |
812 | int i; | 823 | int i; |
813 | 824 | ||
@@ -817,12 +828,7 @@ static void cs_automute(struct hda_codec *codec) | |||
817 | caps = snd_hda_query_pin_caps(codec, nid); | 828 | caps = snd_hda_query_pin_caps(codec, nid); |
818 | if (!(caps & AC_PINCAP_PRES_DETECT)) | 829 | if (!(caps & AC_PINCAP_PRES_DETECT)) |
819 | continue; | 830 | continue; |
820 | if (caps & AC_PINCAP_TRIG_REQ) | 831 | hp_present = snd_hda_jack_detect(codec, nid); |
821 | snd_hda_codec_read(codec, nid, 0, | ||
822 | AC_VERB_SET_PIN_SENSE, 0); | ||
823 | present = snd_hda_codec_read(codec, nid, 0, | ||
824 | AC_VERB_GET_PIN_SENSE, 0); | ||
825 | hp_present |= (present & AC_PINSENSE_PRESENCE) != 0; | ||
826 | if (hp_present) | 832 | if (hp_present) |
827 | break; | 833 | break; |
828 | } | 834 | } |
@@ -832,7 +838,8 @@ static void cs_automute(struct hda_codec *codec) | |||
832 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 838 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
833 | hp_present ? 0 : PIN_OUT); | 839 | hp_present ? 0 : PIN_OUT); |
834 | } | 840 | } |
835 | if (spec->board_config == CS420X_MBP55) { | 841 | if (spec->board_config == CS420X_MBP55 || |
842 | spec->board_config == CS420X_IMAC27) { | ||
836 | unsigned int gpio = hp_present ? 0x02 : 0x08; | 843 | unsigned int gpio = hp_present ? 0x02 : 0x08; |
837 | snd_hda_codec_write(codec, 0x01, 0, | 844 | snd_hda_codec_write(codec, 0x01, 0, |
838 | AC_VERB_SET_GPIO_DATA, gpio); | 845 | AC_VERB_SET_GPIO_DATA, gpio); |
@@ -844,15 +851,11 @@ static void cs_automic(struct hda_codec *codec) | |||
844 | struct cs_spec *spec = codec->spec; | 851 | struct cs_spec *spec = codec->spec; |
845 | struct auto_pin_cfg *cfg = &spec->autocfg; | 852 | struct auto_pin_cfg *cfg = &spec->autocfg; |
846 | hda_nid_t nid; | 853 | hda_nid_t nid; |
847 | unsigned int caps, present; | 854 | unsigned int present; |
848 | 855 | ||
849 | nid = cfg->input_pins[spec->automic_idx]; | 856 | nid = cfg->input_pins[spec->automic_idx]; |
850 | caps = snd_hda_query_pin_caps(codec, nid); | 857 | present = snd_hda_jack_detect(codec, nid); |
851 | if (caps & AC_PINCAP_TRIG_REQ) | 858 | if (present) |
852 | snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); | ||
853 | present = snd_hda_codec_read(codec, nid, 0, | ||
854 | AC_VERB_GET_PIN_SENSE, 0); | ||
855 | if (present & AC_PINSENSE_PRESENCE) | ||
856 | change_cur_input(codec, spec->automic_idx, 0); | 859 | change_cur_input(codec, spec->automic_idx, 0); |
857 | else { | 860 | else { |
858 | unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? | 861 | unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? |
@@ -947,7 +950,7 @@ static void init_input(struct hda_codec *codec) | |||
947 | coef |= 0x0500; /* DMIC2 enable 2 channels, disable GPIO1 */ | 950 | coef |= 0x0500; /* DMIC2 enable 2 channels, disable GPIO1 */ |
948 | if (is_active_pin(codec, CS_DMIC1_PIN_NID)) | 951 | if (is_active_pin(codec, CS_DMIC1_PIN_NID)) |
949 | coef |= 0x1800; /* DMIC1 enable 2 channels, disable GPIO0 | 952 | coef |= 0x1800; /* DMIC1 enable 2 channels, disable GPIO0 |
950 | * No effect if SPDIF_OUT2 is slected in | 953 | * No effect if SPDIF_OUT2 is selected in |
951 | * IDX_SPDIF_CTL. | 954 | * IDX_SPDIF_CTL. |
952 | */ | 955 | */ |
953 | cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); | 956 | cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); |
@@ -1078,12 +1081,14 @@ static int cs_parse_auto_config(struct hda_codec *codec) | |||
1078 | 1081 | ||
1079 | static const char *cs420x_models[CS420X_MODELS] = { | 1082 | static const char *cs420x_models[CS420X_MODELS] = { |
1080 | [CS420X_MBP55] = "mbp55", | 1083 | [CS420X_MBP55] = "mbp55", |
1084 | [CS420X_IMAC27] = "imac27", | ||
1081 | [CS420X_AUTO] = "auto", | 1085 | [CS420X_AUTO] = "auto", |
1082 | }; | 1086 | }; |
1083 | 1087 | ||
1084 | 1088 | ||
1085 | static struct snd_pci_quirk cs420x_cfg_tbl[] = { | 1089 | static struct snd_pci_quirk cs420x_cfg_tbl[] = { |
1086 | SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), | 1090 | SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), |
1091 | SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), | ||
1087 | {} /* terminator */ | 1092 | {} /* terminator */ |
1088 | }; | 1093 | }; |
1089 | 1094 | ||
@@ -1106,8 +1111,23 @@ static struct cs_pincfg mbp55_pincfgs[] = { | |||
1106 | {} /* terminator */ | 1111 | {} /* terminator */ |
1107 | }; | 1112 | }; |
1108 | 1113 | ||
1114 | static struct cs_pincfg imac27_pincfgs[] = { | ||
1115 | { 0x09, 0x012b4050 }, | ||
1116 | { 0x0a, 0x90100140 }, | ||
1117 | { 0x0b, 0x90100142 }, | ||
1118 | { 0x0c, 0x018b3020 }, | ||
1119 | { 0x0d, 0x90a00110 }, | ||
1120 | { 0x0e, 0x400000f0 }, | ||
1121 | { 0x0f, 0x01cbe030 }, | ||
1122 | { 0x10, 0x014be060 }, | ||
1123 | { 0x12, 0x01ab9070 }, | ||
1124 | { 0x15, 0x400000f0 }, | ||
1125 | {} /* terminator */ | ||
1126 | }; | ||
1127 | |||
1109 | static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { | 1128 | static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { |
1110 | [CS420X_MBP55] = mbp55_pincfgs, | 1129 | [CS420X_MBP55] = mbp55_pincfgs, |
1130 | [CS420X_IMAC27] = imac27_pincfgs, | ||
1111 | }; | 1131 | }; |
1112 | 1132 | ||
1113 | static void fix_pincfg(struct hda_codec *codec, int model) | 1133 | static void fix_pincfg(struct hda_codec *codec, int model) |
@@ -1137,6 +1157,7 @@ static int patch_cs420x(struct hda_codec *codec) | |||
1137 | fix_pincfg(codec, spec->board_config); | 1157 | fix_pincfg(codec, spec->board_config); |
1138 | 1158 | ||
1139 | switch (spec->board_config) { | 1159 | switch (spec->board_config) { |
1160 | case CS420X_IMAC27: | ||
1140 | case CS420X_MBP55: | 1161 | case CS420X_MBP55: |
1141 | /* GPIO1 = headphones */ | 1162 | /* GPIO1 = headphones */ |
1142 | /* GPIO3 = speakers */ | 1163 | /* GPIO3 = speakers */ |