diff options
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 95 |
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 | ||
136 | static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, | 138 | static 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 */ | ||
522 | static 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 | |||
518 | static const char *slave_vols[] = { | 529 | static 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 | ||
615 | static 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 | ||
586 | static struct hda_codec_ops conexant_patch_ops = { | 622 | static 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 | ||
1947 | static 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 */ |
1892 | static int cxt5051_init(struct hda_codec *codec) | 1955 | static 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 | ||
1932 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { | 1997 | static 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 | ||