aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt6
-rw-r--r--sound/pci/hda/hda_codec.c32
-rw-r--r--sound/pci/hda/patch_conexant.c75
-rw-r--r--sound/pci/hda/patch_realtek.c339
4 files changed, 436 insertions, 16 deletions
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 1d38b0dfba95..03771d7c5dd7 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -114,6 +114,11 @@ ALC662/663/272
114 samsung-nc10 Samsung NC10 mini notebook 114 samsung-nc10 Samsung NC10 mini notebook
115 auto auto-config reading BIOS (default) 115 auto auto-config reading BIOS (default)
116 116
117ALC680
118======
119 base Base model (ASUS NX90)
120 auto auto-config reading BIOS (default)
121
117ALC882/883/885/888/889 122ALC882/883/885/888/889
118====================== 123======================
119 3stack-dig 3-jack with SPDIF I/O 124 3stack-dig 3-jack with SPDIF I/O
@@ -282,6 +287,7 @@ Conexant 5051
282 hp HP Spartan laptop 287 hp HP Spartan laptop
283 hp-dv6736 HP dv6736 288 hp-dv6736 HP dv6736
284 hp-f700 HP Compaq Presario F700 289 hp-f700 HP Compaq Presario F700
290 ideapad Lenovo IdeaPad laptop
285 lenovo-x200 Lenovo X200 laptop 291 lenovo-x200 Lenovo X200 laptop
286 toshiba Toshiba Satellite M300 292 toshiba Toshiba Satellite M300
287 293
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index ba2098d20ccc..501cbc411a83 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1565,6 +1565,17 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
1565EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); 1565EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
1566#endif /* SND_HDA_NEEDS_RESUME */ 1566#endif /* SND_HDA_NEEDS_RESUME */
1567 1567
1568static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
1569 unsigned int ofs)
1570{
1571 u32 caps = query_amp_caps(codec, nid, dir);
1572 /* get num steps */
1573 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1574 if (ofs < caps)
1575 caps -= ofs;
1576 return caps;
1577}
1578
1568/** 1579/**
1569 * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer 1580 * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
1570 * 1581 *
@@ -1579,23 +1590,17 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1579 u8 chs = get_amp_channels(kcontrol); 1590 u8 chs = get_amp_channels(kcontrol);
1580 int dir = get_amp_direction(kcontrol); 1591 int dir = get_amp_direction(kcontrol);
1581 unsigned int ofs = get_amp_offset(kcontrol); 1592 unsigned int ofs = get_amp_offset(kcontrol);
1582 u32 caps;
1583 1593
1584 caps = query_amp_caps(codec, nid, dir); 1594 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1585 /* num steps */ 1595 uinfo->count = chs == 3 ? 2 : 1;
1586 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; 1596 uinfo->value.integer.min = 0;
1587 if (!caps) { 1597 uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs);
1598 if (!uinfo->value.integer.max) {
1588 printk(KERN_WARNING "hda_codec: " 1599 printk(KERN_WARNING "hda_codec: "
1589 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid, 1600 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1590 kcontrol->id.name); 1601 kcontrol->id.name);
1591 return -EINVAL; 1602 return -EINVAL;
1592 } 1603 }
1593 if (ofs < caps)
1594 caps -= ofs;
1595 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1596 uinfo->count = chs == 3 ? 2 : 1;
1597 uinfo->value.integer.min = 0;
1598 uinfo->value.integer.max = caps;
1599 return 0; 1604 return 0;
1600} 1605}
1601EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); 1606EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
@@ -1620,8 +1625,13 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1620 int ch, int dir, int idx, unsigned int ofs, 1625 int ch, int dir, int idx, unsigned int ofs,
1621 unsigned int val) 1626 unsigned int val)
1622{ 1627{
1628 unsigned int maxval;
1629
1623 if (val > 0) 1630 if (val > 0)
1624 val += ofs; 1631 val += ofs;
1632 maxval = get_amp_max_value(codec, nid, dir, ofs);
1633 if (val > maxval)
1634 val = maxval;
1625 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, 1635 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1626 HDA_AMP_VOLMASK, val); 1636 HDA_AMP_VOLMASK, val);
1627} 1637}
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 2bf2cb5da956..3b789ee548b4 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -131,6 +131,8 @@ struct conexant_spec {
131 unsigned int dc_enable; 131 unsigned int dc_enable;
132 unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */ 132 unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */
133 unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */ 133 unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */
134
135 unsigned int beep_amp;
134}; 136};
135 137
136static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, 138static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@@ -515,6 +517,15 @@ static struct snd_kcontrol_new cxt_capture_mixers[] = {
515 {} 517 {}
516}; 518};
517 519
520#ifdef CONFIG_SND_HDA_INPUT_BEEP
521/* additional beep mixers; the actual parameters are overwritten at build */
522static struct snd_kcontrol_new cxt_beep_mixer[] = {
523 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
524 HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
525 { } /* end */
526};
527#endif
528
518static const char *slave_vols[] = { 529static const char *slave_vols[] = {
519 "Headphone Playback Volume", 530 "Headphone Playback Volume",
520 "Speaker Playback Volume", 531 "Speaker Playback Volume",
@@ -580,6 +591,23 @@ static int conexant_build_controls(struct hda_codec *codec)
580 return err; 591 return err;
581 } 592 }
582 593
594#ifdef CONFIG_SND_HDA_INPUT_BEEP
595 /* create beep controls if needed */
596 if (spec->beep_amp) {
597 struct snd_kcontrol_new *knew;
598 for (knew = cxt_beep_mixer; knew->name; knew++) {
599 struct snd_kcontrol *kctl;
600 kctl = snd_ctl_new1(knew, codec);
601 if (!kctl)
602 return -ENOMEM;
603 kctl->private_value = spec->beep_amp;
604 err = snd_hda_ctl_add(codec, 0, kctl);
605 if (err < 0)
606 return err;
607 }
608 }
609#endif
610
583 return 0; 611 return 0;
584} 612}
585 613
@@ -590,6 +618,13 @@ static struct hda_codec_ops conexant_patch_ops = {
590 .free = conexant_free, 618 .free = conexant_free,
591}; 619};
592 620
621#ifdef CONFIG_SND_HDA_INPUT_BEEP
622#define set_beep_amp(spec, nid, idx, dir) \
623 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
624#else
625#define set_beep_amp(spec, nid, idx, dir) /* NOP */
626#endif
627
593/* 628/*
594 * EAPD control 629 * EAPD control
595 * the private value = nid | (invert << 8) 630 * the private value = nid | (invert << 8)
@@ -1130,9 +1165,10 @@ static int patch_cxt5045(struct hda_codec *codec)
1130 spec->num_init_verbs = 1; 1165 spec->num_init_verbs = 1;
1131 spec->init_verbs[0] = cxt5045_init_verbs; 1166 spec->init_verbs[0] = cxt5045_init_verbs;
1132 spec->spdif_route = 0; 1167 spec->spdif_route = 0;
1133 spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes), 1168 spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes);
1134 spec->channel_mode = cxt5045_modes, 1169 spec->channel_mode = cxt5045_modes;
1135 1170
1171 set_beep_amp(spec, 0x16, 0, 1);
1136 1172
1137 codec->patch_ops = conexant_patch_ops; 1173 codec->patch_ops = conexant_patch_ops;
1138 1174
@@ -1211,6 +1247,9 @@ static int patch_cxt5045(struct hda_codec *codec)
1211 break; 1247 break;
1212 } 1248 }
1213 1249
1250 if (spec->beep_amp)
1251 snd_hda_attach_beep_device(codec, spec->beep_amp);
1252
1214 return 0; 1253 return 0;
1215} 1254}
1216 1255
@@ -1632,6 +1671,11 @@ static void cxt5051_update_speaker(struct hda_codec *codec)
1632 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; 1671 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
1633 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 1672 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1634 pinctl); 1673 pinctl);
1674 /* on ideapad there is an aditional speaker (subwoofer) to mute */
1675 if (spec->ideapad)
1676 snd_hda_codec_write(codec, 0x1b, 0,
1677 AC_VERB_SET_PIN_WIDGET_CONTROL,
1678 pinctl);
1635} 1679}
1636 1680
1637/* turn on/off EAPD (+ mute HP) as a master switch */ 1681/* turn on/off EAPD (+ mute HP) as a master switch */
@@ -1888,6 +1932,13 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
1888#endif 1932#endif
1889} 1933}
1890 1934
1935static struct hda_verb cxt5051_ideapad_init_verbs[] = {
1936 /* Subwoofer */
1937 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1938 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1939 { } /* end */
1940};
1941
1891/* initialize jack-sensing, too */ 1942/* initialize jack-sensing, too */
1892static int cxt5051_init(struct hda_codec *codec) 1943static int cxt5051_init(struct hda_codec *codec)
1893{ 1944{
@@ -1917,6 +1968,7 @@ enum {
1917 CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */ 1968 CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */
1918 CXT5051_F700, /* HP Compaq Presario F700 */ 1969 CXT5051_F700, /* HP Compaq Presario F700 */
1919 CXT5051_TOSHIBA, /* Toshiba M300 & co */ 1970 CXT5051_TOSHIBA, /* Toshiba M300 & co */
1971 CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */
1920 CXT5051_MODELS 1972 CXT5051_MODELS
1921}; 1973};
1922 1974
@@ -1927,6 +1979,7 @@ static const char *cxt5051_models[CXT5051_MODELS] = {
1927 [CXT5051_LENOVO_X200] = "lenovo-x200", 1979 [CXT5051_LENOVO_X200] = "lenovo-x200",
1928 [CXT5051_F700] = "hp-700", 1980 [CXT5051_F700] = "hp-700",
1929 [CXT5051_TOSHIBA] = "toshiba", 1981 [CXT5051_TOSHIBA] = "toshiba",
1982 [CXT5051_IDEAPAD] = "ideapad",
1930}; 1983};
1931 1984
1932static struct snd_pci_quirk cxt5051_cfg_tbl[] = { 1985static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
@@ -1938,6 +1991,7 @@ static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
1938 CXT5051_LAPTOP), 1991 CXT5051_LAPTOP),
1939 SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), 1992 SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
1940 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200), 1993 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
1994 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD),
1941 {} 1995 {}
1942}; 1996};
1943 1997
@@ -1972,6 +2026,8 @@ static int patch_cxt5051(struct hda_codec *codec)
1972 spec->cur_adc = 0; 2026 spec->cur_adc = 0;
1973 spec->cur_adc_idx = 0; 2027 spec->cur_adc_idx = 0;
1974 2028
2029 set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
2030
1975 codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; 2031 codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
1976 2032
1977 board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, 2033 board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
@@ -1999,8 +2055,16 @@ static int patch_cxt5051(struct hda_codec *codec)
1999 spec->mixers[0] = cxt5051_toshiba_mixers; 2055 spec->mixers[0] = cxt5051_toshiba_mixers;
2000 spec->auto_mic = AUTO_MIC_PORTB; 2056 spec->auto_mic = AUTO_MIC_PORTB;
2001 break; 2057 break;
2058 case CXT5051_IDEAPAD:
2059 spec->init_verbs[spec->num_init_verbs++] =
2060 cxt5051_ideapad_init_verbs;
2061 spec->ideapad = 1;
2062 break;
2002 } 2063 }
2003 2064
2065 if (spec->beep_amp)
2066 snd_hda_attach_beep_device(codec, spec->beep_amp);
2067
2004 return 0; 2068 return 0;
2005} 2069}
2006 2070
@@ -2616,7 +2680,6 @@ static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
2616 .put = cxt5066_mic_boost_mux_enum_put, 2680 .put = cxt5066_mic_boost_mux_enum_put,
2617 .private_value = 0x23 | 0x100, 2681 .private_value = 0x23 | 0x100,
2618 }, 2682 },
2619 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
2620 {} 2683 {}
2621}; 2684};
2622 2685
@@ -3014,6 +3077,8 @@ static int patch_cxt5066(struct hda_codec *codec)
3014 spec->cur_adc = 0; 3077 spec->cur_adc = 0;
3015 spec->cur_adc_idx = 0; 3078 spec->cur_adc_idx = 0;
3016 3079
3080 set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
3081
3017 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS, 3082 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
3018 cxt5066_models, cxt5066_cfg_tbl); 3083 cxt5066_models, cxt5066_cfg_tbl);
3019 switch (board_config) { 3084 switch (board_config) {
@@ -3062,7 +3127,6 @@ static int patch_cxt5066(struct hda_codec *codec)
3062 spec->port_d_mode = 0; 3127 spec->port_d_mode = 0;
3063 spec->dell_vostro = 1; 3128 spec->dell_vostro = 1;
3064 spec->mic_boost = 3; /* default 30dB gain */ 3129 spec->mic_boost = 3; /* default 30dB gain */
3065 snd_hda_attach_beep_device(codec, 0x13);
3066 3130
3067 /* no S/PDIF out */ 3131 /* no S/PDIF out */
3068 spec->multiout.dig_out_nid = 0; 3132 spec->multiout.dig_out_nid = 0;
@@ -3104,6 +3168,9 @@ static int patch_cxt5066(struct hda_codec *codec)
3104 break; 3168 break;
3105 } 3169 }
3106 3170
3171 if (spec->beep_amp)
3172 snd_hda_attach_beep_device(codec, spec->beep_amp);
3173
3107 return 0; 3174 return 0;
3108} 3175}
3109 3176
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index ff614dd824c1..a7592f5e97d4 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -256,6 +256,13 @@ enum {
256 ALC882_MODEL_LAST, 256 ALC882_MODEL_LAST,
257}; 257};
258 258
259/* ALC680 models */
260enum {
261 ALC680_BASE,
262 ALC680_AUTO,
263 ALC680_MODEL_LAST,
264};
265
259/* for GPIO Poll */ 266/* for GPIO Poll */
260#define GPIO_MASK 0x03 267#define GPIO_MASK 0x03
261 268
@@ -18615,7 +18622,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
18615 18622
18616 add_verb(spec, alc662_init_verbs); 18623 add_verb(spec, alc662_init_verbs);
18617 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || 18624 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
18618 codec->vendor_id == 0x10ec0665) 18625 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
18619 add_verb(spec, alc663_init_verbs); 18626 add_verb(spec, alc663_init_verbs);
18620 18627
18621 if (codec->vendor_id == 0x10ec0272) 18628 if (codec->vendor_id == 0x10ec0272)
@@ -18759,6 +18766,335 @@ static int patch_alc888(struct hda_codec *codec)
18759} 18766}
18760 18767
18761/* 18768/*
18769 * ALC680 support
18770 */
18771#define ALC680_DIGOUT_NID ALC880_DIGOUT_NID
18772#define alc680_modes alc260_modes
18773
18774static hda_nid_t alc680_dac_nids[3] = {
18775 /* Lout1, Lout2, hp */
18776 0x02, 0x03, 0x04
18777};
18778
18779static hda_nid_t alc680_adc_nids[3] = {
18780 /* ADC0-2 */
18781 /* DMIC, MIC, Line-in*/
18782 0x07, 0x08, 0x09
18783};
18784
18785static struct snd_kcontrol_new alc680_base_mixer[] = {
18786 /* output mixer control */
18787 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
18788 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
18789 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT),
18790 HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT),
18791 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
18792 { }
18793};
18794
18795static struct snd_kcontrol_new alc680_capture_mixer[] = {
18796 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
18797 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
18798 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
18799 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
18800 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
18801 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
18802 { } /* end */
18803};
18804
18805/*
18806 * generic initialization of ADC, input mixers and output mixers
18807 */
18808static struct hda_verb alc680_init_verbs[] = {
18809 /* Unmute DAC0-1 and set vol = 0 */
18810 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
18811 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
18812 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
18813
18814 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
18815 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
18816 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
18817 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
18818 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
18819
18820 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
18821 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
18822 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
18823 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
18824 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
18825 { }
18826};
18827
18828/* create input playback/capture controls for the given pin */
18829static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
18830 const char *ctlname, int idx)
18831{
18832 hda_nid_t dac;
18833 int err;
18834
18835 switch (nid) {
18836 case 0x14:
18837 dac = 0x02;
18838 break;
18839 case 0x15:
18840 dac = 0x03;
18841 break;
18842 case 0x16:
18843 dac = 0x04;
18844 break;
18845 default:
18846 return 0;
18847 }
18848 if (spec->multiout.dac_nids[0] != dac &&
18849 spec->multiout.dac_nids[1] != dac) {
18850 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
18851 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
18852 HDA_OUTPUT));
18853 if (err < 0)
18854 return err;
18855
18856 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
18857 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
18858
18859 if (err < 0)
18860 return err;
18861 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
18862 }
18863
18864 return 0;
18865}
18866
18867/* add playback controls from the parsed DAC table */
18868static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec,
18869 const struct auto_pin_cfg *cfg)
18870{
18871 hda_nid_t nid;
18872 int err;
18873
18874 spec->multiout.dac_nids = spec->private_dac_nids;
18875
18876 nid = cfg->line_out_pins[0];
18877 if (nid) {
18878 const char *name;
18879 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
18880 name = "Speaker";
18881 else
18882 name = "Front";
18883 err = alc680_new_analog_output(spec, nid, name, 0);
18884 if (err < 0)
18885 return err;
18886 }
18887
18888 nid = cfg->speaker_pins[0];
18889 if (nid) {
18890 err = alc680_new_analog_output(spec, nid, "Speaker", 0);
18891 if (err < 0)
18892 return err;
18893 }
18894 nid = cfg->hp_pins[0];
18895 if (nid) {
18896 err = alc680_new_analog_output(spec, nid, "Headphone", 0);
18897 if (err < 0)
18898 return err;
18899 }
18900
18901 return 0;
18902}
18903
18904static void alc680_auto_set_output_and_unmute(struct hda_codec *codec,
18905 hda_nid_t nid, int pin_type)
18906{
18907 alc_set_pin_output(codec, nid, pin_type);
18908}
18909
18910static void alc680_auto_init_multi_out(struct hda_codec *codec)
18911{
18912 struct alc_spec *spec = codec->spec;
18913 hda_nid_t nid = spec->autocfg.line_out_pins[0];
18914 if (nid) {
18915 int pin_type = get_pin_type(spec->autocfg.line_out_type);
18916 alc680_auto_set_output_and_unmute(codec, nid, pin_type);
18917 }
18918}
18919
18920static void alc680_auto_init_hp_out(struct hda_codec *codec)
18921{
18922 struct alc_spec *spec = codec->spec;
18923 hda_nid_t pin;
18924
18925 pin = spec->autocfg.hp_pins[0];
18926 if (pin)
18927 alc680_auto_set_output_and_unmute(codec, pin, PIN_HP);
18928 pin = spec->autocfg.speaker_pins[0];
18929 if (pin)
18930 alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT);
18931}
18932
18933/* pcm configuration: identical with ALC880 */
18934#define alc680_pcm_analog_playback alc880_pcm_analog_playback
18935#define alc680_pcm_analog_capture alc880_pcm_analog_capture
18936#define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
18937#define alc680_pcm_digital_playback alc880_pcm_digital_playback
18938
18939static struct hda_input_mux alc680_capture_source = {
18940 .num_items = 1,
18941 .items = {
18942 { "Mic", 0x0 },
18943 },
18944};
18945
18946/*
18947 * BIOS auto configuration
18948 */
18949static int alc680_parse_auto_config(struct hda_codec *codec)
18950{
18951 struct alc_spec *spec = codec->spec;
18952 int err;
18953 static hda_nid_t alc680_ignore[] = { 0 };
18954
18955 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
18956 alc680_ignore);
18957 if (err < 0)
18958 return err;
18959 if (!spec->autocfg.line_outs) {
18960 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
18961 spec->multiout.max_channels = 2;
18962 spec->no_analog = 1;
18963 goto dig_only;
18964 }
18965 return 0; /* can't find valid BIOS pin config */
18966 }
18967 err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg);
18968 if (err < 0)
18969 return err;
18970
18971 spec->multiout.max_channels = 2;
18972
18973 dig_only:
18974 /* digital only support output */
18975 if (spec->autocfg.dig_outs) {
18976 spec->multiout.dig_out_nid = ALC680_DIGOUT_NID;
18977 spec->dig_out_type = spec->autocfg.dig_out_type[0];
18978 }
18979 if (spec->kctls.list)
18980 add_mixer(spec, spec->kctls.list);
18981
18982 add_verb(spec, alc680_init_verbs);
18983 spec->num_mux_defs = 1;
18984 spec->input_mux = &alc680_capture_source;
18985
18986 err = alc_auto_add_mic_boost(codec);
18987 if (err < 0)
18988 return err;
18989
18990 return 1;
18991}
18992
18993#define alc680_auto_init_analog_input alc882_auto_init_analog_input
18994
18995/* init callback for auto-configuration model -- overriding the default init */
18996static void alc680_auto_init(struct hda_codec *codec)
18997{
18998 struct alc_spec *spec = codec->spec;
18999 alc680_auto_init_multi_out(codec);
19000 alc680_auto_init_hp_out(codec);
19001 alc680_auto_init_analog_input(codec);
19002 if (spec->unsol_event)
19003 alc_inithook(codec);
19004}
19005
19006/*
19007 * configuration and preset
19008 */
19009static const char *alc680_models[ALC680_MODEL_LAST] = {
19010 [ALC680_BASE] = "base",
19011 [ALC680_AUTO] = "auto",
19012};
19013
19014static struct snd_pci_quirk alc680_cfg_tbl[] = {
19015 SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
19016 {}
19017};
19018
19019static struct alc_config_preset alc680_presets[] = {
19020 [ALC680_BASE] = {
19021 .mixers = { alc680_base_mixer },
19022 .cap_mixer = alc680_capture_mixer,
19023 .init_verbs = { alc680_init_verbs },
19024 .num_dacs = ARRAY_SIZE(alc680_dac_nids),
19025 .dac_nids = alc680_dac_nids,
19026 .num_adc_nids = ARRAY_SIZE(alc680_adc_nids),
19027 .adc_nids = alc680_adc_nids,
19028 .hp_nid = 0x04,
19029 .dig_out_nid = ALC680_DIGOUT_NID,
19030 .num_channel_mode = ARRAY_SIZE(alc680_modes),
19031 .channel_mode = alc680_modes,
19032 .input_mux = &alc680_capture_source,
19033 },
19034};
19035
19036static int patch_alc680(struct hda_codec *codec)
19037{
19038 struct alc_spec *spec;
19039 int board_config;
19040 int err;
19041
19042 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
19043 if (spec == NULL)
19044 return -ENOMEM;
19045
19046 codec->spec = spec;
19047
19048 board_config = snd_hda_check_board_config(codec, ALC680_MODEL_LAST,
19049 alc680_models,
19050 alc680_cfg_tbl);
19051
19052 if (board_config < 0 || board_config >= ALC680_MODEL_LAST) {
19053 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
19054 codec->chip_name);
19055 board_config = ALC680_AUTO;
19056 }
19057
19058 if (board_config == ALC680_AUTO) {
19059 /* automatic parse from the BIOS config */
19060 err = alc680_parse_auto_config(codec);
19061 if (err < 0) {
19062 alc_free(codec);
19063 return err;
19064 } else if (!err) {
19065 printk(KERN_INFO
19066 "hda_codec: Cannot set up configuration "
19067 "from BIOS. Using base mode...\n");
19068 board_config = ALC680_BASE;
19069 }
19070 }
19071
19072 if (board_config != ALC680_AUTO)
19073 setup_preset(codec, &alc680_presets[board_config]);
19074
19075 spec->stream_analog_playback = &alc680_pcm_analog_playback;
19076 spec->stream_analog_capture = &alc680_pcm_analog_capture;
19077 spec->stream_analog_alt_capture = &alc680_pcm_analog_alt_capture;
19078 spec->stream_digital_playback = &alc680_pcm_digital_playback;
19079
19080 if (!spec->adc_nids) {
19081 spec->adc_nids = alc680_adc_nids;
19082 spec->num_adc_nids = ARRAY_SIZE(alc680_adc_nids);
19083 }
19084
19085 if (!spec->cap_mixer)
19086 set_capture_mixer(codec);
19087
19088 spec->vmaster_nid = 0x02;
19089
19090 codec->patch_ops = alc_patch_ops;
19091 if (board_config == ALC680_AUTO)
19092 spec->init_hook = alc680_auto_init;
19093
19094 return 0;
19095}
19096
19097/*
18762 * patch entries 19098 * patch entries
18763 */ 19099 */
18764static struct hda_codec_preset snd_hda_preset_realtek[] = { 19100static struct hda_codec_preset snd_hda_preset_realtek[] = {
@@ -18782,6 +19118,7 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
18782 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, 19118 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
18783 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, 19119 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
18784 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, 19120 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
19121 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
18785 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, 19122 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
18786 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, 19123 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
18787 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, 19124 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },