diff options
Diffstat (limited to 'sound/pci/hda/patch_cirrus.c')
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 8ba306856d3..fe0423c3959 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -66,6 +66,7 @@ struct cs_spec { /* available models */ enum { CS420X_MBP55, + CS420X_IMAC27, CS420X_AUTO, CS420X_MODELS }; @@ -500,7 +501,7 @@ static int add_mute(struct hda_codec *codec, const char *name, int index, knew.private_value = pval; snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); *kctlp = snd_ctl_new1(&knew, codec); - return snd_hda_ctl_add(codec, *kctlp); + return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp); } static int add_volume(struct hda_codec *codec, const char *name, @@ -513,7 +514,7 @@ static int add_volume(struct hda_codec *codec, const char *name, knew.private_value = pval; snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); *kctlp = snd_ctl_new1(&knew, codec); - return snd_hda_ctl_add(codec, *kctlp); + return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp); } static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) @@ -536,14 +537,14 @@ static int add_vmaster(struct hda_codec *codec, hda_nid_t dac) spec->vmaster_sw = snd_ctl_make_virtual_master("Master Playback Switch", NULL); - err = snd_hda_ctl_add(codec, spec->vmaster_sw); + err = snd_hda_ctl_add(codec, dac, spec->vmaster_sw); if (err < 0) return err; snd_hda_set_vmaster_tlv(codec, dac, HDA_OUTPUT, tlv); spec->vmaster_vol = snd_ctl_make_virtual_master("Master Playback Volume", tlv); - err = snd_hda_ctl_add(codec, spec->vmaster_vol); + err = snd_hda_ctl_add(codec, dac, spec->vmaster_vol); if (err < 0) return err; return 0; @@ -756,13 +757,13 @@ static int build_input(struct hda_codec *codec) if (!kctl) return -ENOMEM; kctl->private_value = (long)spec->capture_bind[i]; - err = snd_hda_ctl_add(codec, kctl); + err = snd_hda_ctl_add(codec, 0, kctl); if (err < 0) return err; } if (spec->num_inputs > 1 && !spec->mic_detect) { - err = snd_hda_ctl_add(codec, + err = snd_hda_ctl_add(codec, 0, snd_ctl_new1(&cs_capture_source, codec)); if (err < 0) return err; @@ -807,7 +808,7 @@ static void cs_automute(struct hda_codec *codec) { struct cs_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int caps, present, hp_present; + unsigned int caps, hp_present; hda_nid_t nid; int i; @@ -817,12 +818,7 @@ static void cs_automute(struct hda_codec *codec) caps = snd_hda_query_pin_caps(codec, nid); if (!(caps & AC_PINCAP_PRES_DETECT)) continue; - if (caps & AC_PINCAP_TRIG_REQ) - snd_hda_codec_read(codec, nid, 0, - AC_VERB_SET_PIN_SENSE, 0); - present = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_SENSE, 0); - hp_present |= (present & AC_PINSENSE_PRESENCE) != 0; + hp_present = snd_hda_jack_detect(codec, nid); if (hp_present) break; } @@ -832,7 +828,8 @@ static void cs_automute(struct hda_codec *codec) AC_VERB_SET_PIN_WIDGET_CONTROL, hp_present ? 0 : PIN_OUT); } - if (spec->board_config == CS420X_MBP55) { + if (spec->board_config == CS420X_MBP55 || + spec->board_config == CS420X_IMAC27) { unsigned int gpio = hp_present ? 0x02 : 0x08; snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, gpio); @@ -844,15 +841,11 @@ static void cs_automic(struct hda_codec *codec) struct cs_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; hda_nid_t nid; - unsigned int caps, present; + unsigned int present; nid = cfg->input_pins[spec->automic_idx]; - caps = snd_hda_query_pin_caps(codec, nid); - if (caps & AC_PINCAP_TRIG_REQ) - snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); - present = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_SENSE, 0); - if (present & AC_PINSENSE_PRESENCE) + present = snd_hda_jack_detect(codec, nid); + if (present) change_cur_input(codec, spec->automic_idx, 0); else { unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? @@ -947,7 +940,7 @@ static void init_input(struct hda_codec *codec) coef |= 0x0500; /* DMIC2 enable 2 channels, disable GPIO1 */ if (is_active_pin(codec, CS_DMIC1_PIN_NID)) coef |= 0x1800; /* DMIC1 enable 2 channels, disable GPIO0 - * No effect if SPDIF_OUT2 is slected in + * No effect if SPDIF_OUT2 is selected in * IDX_SPDIF_CTL. */ cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); @@ -1078,12 +1071,14 @@ static int cs_parse_auto_config(struct hda_codec *codec) static const char *cs420x_models[CS420X_MODELS] = { [CS420X_MBP55] = "mbp55", + [CS420X_IMAC27] = "imac27", [CS420X_AUTO] = "auto", }; static struct snd_pci_quirk cs420x_cfg_tbl[] = { SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), + SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), {} /* terminator */ }; @@ -1106,8 +1101,23 @@ static struct cs_pincfg mbp55_pincfgs[] = { {} /* terminator */ }; +static struct cs_pincfg imac27_pincfgs[] = { + { 0x09, 0x012b4050 }, + { 0x0a, 0x90100140 }, + { 0x0b, 0x90100142 }, + { 0x0c, 0x018b3020 }, + { 0x0d, 0x90a00110 }, + { 0x0e, 0x400000f0 }, + { 0x0f, 0x01cbe030 }, + { 0x10, 0x014be060 }, + { 0x12, 0x01ab9070 }, + { 0x15, 0x400000f0 }, + {} /* terminator */ +}; + static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { [CS420X_MBP55] = mbp55_pincfgs, + [CS420X_IMAC27] = imac27_pincfgs, }; static void fix_pincfg(struct hda_codec *codec, int model) @@ -1137,6 +1147,7 @@ static int patch_cs420x(struct hda_codec *codec) fix_pincfg(codec, spec->board_config); switch (spec->board_config) { + case CS420X_IMAC27: case CS420X_MBP55: /* GPIO1 = headphones */ /* GPIO3 = speakers */ |