aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_conexant.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r--sound/pci/hda/patch_conexant.c95
1 files changed, 90 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 2bf2cb5da956..df8b19b17308 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,16 +591,52 @@ 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
611 return 0;
612}
613
614#ifdef CONFIG_SND_HDA_POWER_SAVE
615static int conexant_suspend(struct hda_codec *codec, pm_message_t state)
616{
617 snd_hda_shutup_pins(codec);
583 return 0; 618 return 0;
584} 619}
620#endif
585 621
586static struct hda_codec_ops conexant_patch_ops = { 622static struct hda_codec_ops conexant_patch_ops = {
587 .build_controls = conexant_build_controls, 623 .build_controls = conexant_build_controls,
588 .build_pcms = conexant_build_pcms, 624 .build_pcms = conexant_build_pcms,
589 .init = conexant_init, 625 .init = conexant_init,
590 .free = conexant_free, 626 .free = conexant_free,
627#ifdef CONFIG_SND_HDA_POWER_SAVE
628 .suspend = conexant_suspend,
629#endif
630 .reboot_notify = snd_hda_shutup_pins,
591}; 631};
592 632
633#ifdef CONFIG_SND_HDA_INPUT_BEEP
634#define set_beep_amp(spec, nid, idx, dir) \
635 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
636#else
637#define set_beep_amp(spec, nid, idx, dir) /* NOP */
638#endif
639
593/* 640/*
594 * EAPD control 641 * EAPD control
595 * the private value = nid | (invert << 8) 642 * the private value = nid | (invert << 8)
@@ -1130,9 +1177,10 @@ static int patch_cxt5045(struct hda_codec *codec)
1130 spec->num_init_verbs = 1; 1177 spec->num_init_verbs = 1;
1131 spec->init_verbs[0] = cxt5045_init_verbs; 1178 spec->init_verbs[0] = cxt5045_init_verbs;
1132 spec->spdif_route = 0; 1179 spec->spdif_route = 0;
1133 spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes), 1180 spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes);
1134 spec->channel_mode = cxt5045_modes, 1181 spec->channel_mode = cxt5045_modes;
1135 1182
1183 set_beep_amp(spec, 0x16, 0, 1);
1136 1184
1137 codec->patch_ops = conexant_patch_ops; 1185 codec->patch_ops = conexant_patch_ops;
1138 1186
@@ -1211,6 +1259,9 @@ static int patch_cxt5045(struct hda_codec *codec)
1211 break; 1259 break;
1212 } 1260 }
1213 1261
1262 if (spec->beep_amp)
1263 snd_hda_attach_beep_device(codec, spec->beep_amp);
1264
1214 return 0; 1265 return 0;
1215} 1266}
1216 1267
@@ -1632,6 +1683,11 @@ static void cxt5051_update_speaker(struct hda_codec *codec)
1632 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; 1683 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
1633 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 1684 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1634 pinctl); 1685 pinctl);
1686 /* on ideapad there is an aditional speaker (subwoofer) to mute */
1687 if (spec->ideapad)
1688 snd_hda_codec_write(codec, 0x1b, 0,
1689 AC_VERB_SET_PIN_WIDGET_CONTROL,
1690 pinctl);
1635} 1691}
1636 1692
1637/* turn on/off EAPD (+ mute HP) as a master switch */ 1693/* turn on/off EAPD (+ mute HP) as a master switch */
@@ -1888,6 +1944,13 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
1888#endif 1944#endif
1889} 1945}
1890 1946
1947static struct hda_verb cxt5051_ideapad_init_verbs[] = {
1948 /* Subwoofer */
1949 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1950 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1951 { } /* end */
1952};
1953
1891/* initialize jack-sensing, too */ 1954/* initialize jack-sensing, too */
1892static int cxt5051_init(struct hda_codec *codec) 1955static int cxt5051_init(struct hda_codec *codec)
1893{ 1956{
@@ -1917,6 +1980,7 @@ enum {
1917 CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */ 1980 CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */
1918 CXT5051_F700, /* HP Compaq Presario F700 */ 1981 CXT5051_F700, /* HP Compaq Presario F700 */
1919 CXT5051_TOSHIBA, /* Toshiba M300 & co */ 1982 CXT5051_TOSHIBA, /* Toshiba M300 & co */
1983 CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */
1920 CXT5051_MODELS 1984 CXT5051_MODELS
1921}; 1985};
1922 1986
@@ -1927,6 +1991,7 @@ static const char *cxt5051_models[CXT5051_MODELS] = {
1927 [CXT5051_LENOVO_X200] = "lenovo-x200", 1991 [CXT5051_LENOVO_X200] = "lenovo-x200",
1928 [CXT5051_F700] = "hp-700", 1992 [CXT5051_F700] = "hp-700",
1929 [CXT5051_TOSHIBA] = "toshiba", 1993 [CXT5051_TOSHIBA] = "toshiba",
1994 [CXT5051_IDEAPAD] = "ideapad",
1930}; 1995};
1931 1996
1932static struct snd_pci_quirk cxt5051_cfg_tbl[] = { 1997static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
@@ -1938,6 +2003,7 @@ static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
1938 CXT5051_LAPTOP), 2003 CXT5051_LAPTOP),
1939 SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), 2004 SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
1940 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200), 2005 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
2006 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD),
1941 {} 2007 {}
1942}; 2008};
1943 2009
@@ -1972,6 +2038,8 @@ static int patch_cxt5051(struct hda_codec *codec)
1972 spec->cur_adc = 0; 2038 spec->cur_adc = 0;
1973 spec->cur_adc_idx = 0; 2039 spec->cur_adc_idx = 0;
1974 2040
2041 set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
2042
1975 codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; 2043 codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
1976 2044
1977 board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, 2045 board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
@@ -1989,6 +2057,10 @@ static int patch_cxt5051(struct hda_codec *codec)
1989 break; 2057 break;
1990 case CXT5051_LENOVO_X200: 2058 case CXT5051_LENOVO_X200:
1991 spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs; 2059 spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
2060 /* Thinkpad X301 does not have S/PDIF wired and no ability
2061 to use a docking station. */
2062 if (codec->subsystem_id == 0x17aa211f)
2063 spec->multiout.dig_out_nid = 0;
1992 break; 2064 break;
1993 case CXT5051_F700: 2065 case CXT5051_F700:
1994 spec->init_verbs[0] = cxt5051_f700_init_verbs; 2066 spec->init_verbs[0] = cxt5051_f700_init_verbs;
@@ -1999,8 +2071,16 @@ static int patch_cxt5051(struct hda_codec *codec)
1999 spec->mixers[0] = cxt5051_toshiba_mixers; 2071 spec->mixers[0] = cxt5051_toshiba_mixers;
2000 spec->auto_mic = AUTO_MIC_PORTB; 2072 spec->auto_mic = AUTO_MIC_PORTB;
2001 break; 2073 break;
2074 case CXT5051_IDEAPAD:
2075 spec->init_verbs[spec->num_init_verbs++] =
2076 cxt5051_ideapad_init_verbs;
2077 spec->ideapad = 1;
2078 break;
2002 } 2079 }
2003 2080
2081 if (spec->beep_amp)
2082 snd_hda_attach_beep_device(codec, spec->beep_amp);
2083
2004 return 0; 2084 return 0;
2005} 2085}
2006 2086
@@ -2616,7 +2696,6 @@ static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
2616 .put = cxt5066_mic_boost_mux_enum_put, 2696 .put = cxt5066_mic_boost_mux_enum_put,
2617 .private_value = 0x23 | 0x100, 2697 .private_value = 0x23 | 0x100,
2618 }, 2698 },
2619 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
2620 {} 2699 {}
2621}; 2700};
2622 2701
@@ -2977,8 +3056,10 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2977 SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), 3056 SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
2978 SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), 3057 SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
2979 SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD), 3058 SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD),
3059 SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
3060 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G series", CXT5066_IDEAPAD),
3061 SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G series (AMD)", CXT5066_IDEAPAD),
2980 SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), 3062 SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD),
2981 SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
2982 {} 3063 {}
2983}; 3064};
2984 3065
@@ -3014,6 +3095,8 @@ static int patch_cxt5066(struct hda_codec *codec)
3014 spec->cur_adc = 0; 3095 spec->cur_adc = 0;
3015 spec->cur_adc_idx = 0; 3096 spec->cur_adc_idx = 0;
3016 3097
3098 set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
3099
3017 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS, 3100 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
3018 cxt5066_models, cxt5066_cfg_tbl); 3101 cxt5066_models, cxt5066_cfg_tbl);
3019 switch (board_config) { 3102 switch (board_config) {
@@ -3062,7 +3145,6 @@ static int patch_cxt5066(struct hda_codec *codec)
3062 spec->port_d_mode = 0; 3145 spec->port_d_mode = 0;
3063 spec->dell_vostro = 1; 3146 spec->dell_vostro = 1;
3064 spec->mic_boost = 3; /* default 30dB gain */ 3147 spec->mic_boost = 3; /* default 30dB gain */
3065 snd_hda_attach_beep_device(codec, 0x13);
3066 3148
3067 /* no S/PDIF out */ 3149 /* no S/PDIF out */
3068 spec->multiout.dig_out_nid = 0; 3150 spec->multiout.dig_out_nid = 0;
@@ -3104,6 +3186,9 @@ static int patch_cxt5066(struct hda_codec *codec)
3104 break; 3186 break;
3105 } 3187 }
3106 3188
3189 if (spec->beep_amp)
3190 snd_hda_attach_beep_device(codec, spec->beep_amp);
3191
3107 return 0; 3192 return 0;
3108} 3193}
3109 3194