25 #include <linux/slab.h>
26 #include <linux/pci.h>
27 #include <linux/module.h>
37 #define CXT_PIN_DIR_IN 0x00
38 #define CXT_PIN_DIR_OUT 0x01
39 #define CXT_PIN_DIR_INOUT 0x02
40 #define CXT_PIN_DIR_IN_NOMICBIAS 0x03
41 #define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04
43 #define CONEXANT_HP_EVENT 0x37
44 #define CONEXANT_MIC_EVENT 0x38
45 #define CONEXANT_LINE_EVENT 0x39
49 #define CXT5051_SPDIF_OUT 0x12
50 #define CXT5051_PORTB_EVENT 0x38
51 #define CXT5051_PORTC_EVENT 0x39
53 #define AUTO_MIC_PORTB (1 << 1)
54 #define AUTO_MIC_PORTC (1 << 2)
172 static int conexant_playback_pcm_open(
struct hda_pcm_stream *hinfo,
181 static int conexant_playback_pcm_prepare(
struct hda_pcm_stream *hinfo,
183 unsigned int stream_tag,
193 static int conexant_playback_pcm_cleanup(
struct hda_pcm_stream *hinfo,
204 static int conexant_dig_playback_pcm_open(
struct hda_pcm_stream *hinfo,
212 static int conexant_dig_playback_pcm_close(
struct hda_pcm_stream *hinfo,
220 static int conexant_dig_playback_pcm_prepare(
struct hda_pcm_stream *hinfo,
222 unsigned int stream_tag,
235 static int conexant_capture_pcm_prepare(
struct hda_pcm_stream *hinfo,
237 unsigned int stream_tag,
245 stream_tag, 0, format);
249 static int conexant_capture_pcm_cleanup(
struct hda_pcm_stream *hinfo,
262 static const struct hda_pcm_stream conexant_pcm_analog_playback = {
268 .open = conexant_playback_pcm_open,
269 .prepare = conexant_playback_pcm_prepare,
270 .cleanup = conexant_playback_pcm_cleanup
274 static const struct hda_pcm_stream conexant_pcm_analog_capture = {
280 .prepare = conexant_capture_pcm_prepare,
281 .cleanup = conexant_capture_pcm_cleanup
286 static const struct hda_pcm_stream conexant_pcm_digital_playback = {
292 .open = conexant_dig_playback_pcm_open,
293 .close = conexant_dig_playback_pcm_close,
294 .prepare = conexant_dig_playback_pcm_prepare
298 static const struct hda_pcm_stream conexant_pcm_digital_capture = {
305 static int cx5051_capture_pcm_prepare(
struct hda_pcm_stream *hinfo,
307 unsigned int stream_tag,
319 static int cx5051_capture_pcm_cleanup(
struct hda_pcm_stream *hinfo,
335 .prepare = cx5051_capture_pcm_prepare,
336 .cleanup = cx5051_capture_pcm_cleanup
340 static int conexant_build_pcms(
struct hda_codec *codec)
348 info->
name =
"CONEXANT Analog";
359 cx5051_pcm_analog_capture;
362 conexant_pcm_analog_capture;
372 info->
name =
"Conexant Digital";
375 conexant_pcm_digital_playback;
380 conexant_pcm_digital_capture;
391 static int conexant_mux_enum_info(
struct snd_kcontrol *kcontrol,
400 static int conexant_mux_enum_get(
struct snd_kcontrol *kcontrol,
405 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->
id);
407 ucontrol->
value.enumerated.item[0] = spec->
cur_mux[adc_idx];
411 static int conexant_mux_enum_put(
struct snd_kcontrol *kcontrol,
416 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->
id);
436 static int conexant_init(
struct hda_codec *codec)
446 static void conexant_free(
struct hda_codec *codec)
449 snd_hda_gen_free(&spec->
gen);
457 .name =
"Capture Source",
458 .info = conexant_mux_enum_info,
459 .get = conexant_mux_enum_get,
460 .put = conexant_mux_enum_put
465 #ifdef CONFIG_SND_HDA_INPUT_BEEP
474 static const char *
const slave_pfxs[] = {
475 "Headphone",
"Speaker",
"Front",
"Surround",
"CLFE",
479 static int conexant_build_controls(
struct hda_codec *codec)
511 unsigned int vmaster_tlv[4];
515 vmaster_tlv, slave_pfxs,
524 "Playback Switch",
true,
536 #ifdef CONFIG_SND_HDA_INPUT_BEEP
540 for (knew = cxt_beep_mixer; knew->
name; knew++) {
557 static int conexant_suspend(
struct hda_codec *codec)
565 .build_controls = conexant_build_controls,
566 .build_pcms = conexant_build_pcms,
567 .init = conexant_init,
568 .free = conexant_free,
569 .set_power_state = conexant_set_power,
571 .suspend = conexant_suspend,
576 #ifdef CONFIG_SND_HDA_INPUT_BEEP
577 #define set_beep_amp(spec, nid, idx, dir) \
578 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
580 #define set_beep_amp(spec, nid, idx, dir)
583 static int patch_conexant_auto(
struct hda_codec *codec);
589 #define cxt_eapd_info snd_ctl_boolean_mono_info
614 eapd = !!ucontrol->
value.integer.value[0];
628 #ifdef CONFIG_SND_DEBUG
630 #define CXT_EAPD_SWITCH(xname, nid, mask) \
631 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
632 .info = cxt_eapd_info, \
633 .get = cxt_eapd_get, \
634 .put = cxt_eapd_put, \
635 .private_value = nid | (mask<<16) }
639 static int conexant_ch_mode_info(
struct snd_kcontrol *kcontrol,
648 static int conexant_ch_mode_get(
struct snd_kcontrol *kcontrol,
658 static int conexant_ch_mode_put(
struct snd_kcontrol *kcontrol,
671 #define CXT_PIN_MODE(xname, nid, dir) \
672 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
673 .info = conexant_ch_mode_info, \
674 .get = conexant_ch_mode_get, \
675 .put = conexant_ch_mode_put, \
676 .private_value = nid | (dir<<16) }
682 static const hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
683 static const hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
684 static const hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
685 #define CXT5045_SPDIF_OUT 0x18
694 {
"Internal Mic", 0x1 },
699 static const struct hda_input_mux cxt5045_capture_source_benq = {
702 {
"Internal Mic", 0x1 },
709 static const struct hda_input_mux cxt5045_capture_source_hp530 = {
713 {
"Internal Mic", 0x2 },
718 static int cxt5045_hp_master_sw_put(
struct snd_kcontrol *kcontrol,
725 if (!cxt_eapd_put(kcontrol, ucontrol))
742 static const struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
752 static void cxt5045_hp_automic(
struct hda_codec *codec)
754 static const struct hda_verb mic_jack_on[] = {
759 static const struct hda_verb mic_jack_off[] = {
764 unsigned int present;
775 static void cxt5045_hp_automute(
struct hda_codec *codec)
788 static void cxt5045_hp_unsol_event(
struct hda_codec *codec,
794 cxt5045_hp_automute(codec);
797 cxt5045_hp_automic(codec);
812 HDA_BIND_VOL(
"Master Playback Volume", &cxt5045_hp_bind_master_vol),
815 .name =
"Master Playback Switch",
818 .put = cxt5045_hp_master_sw_put,
819 .private_value = 0x10,
841 HDA_BIND_VOL(
"Master Playback Volume", &cxt5045_hp_bind_master_vol),
844 .name =
"Master Playback Switch",
847 .put = cxt5045_hp_master_sw_put,
848 .private_value = 0x10,
854 static const struct hda_verb cxt5045_init_verbs[] = {
880 static const struct hda_verb cxt5045_benq_init_verbs[] = {
906 static const struct hda_verb cxt5045_hp_sense_init_verbs[] = {
912 static const struct hda_verb cxt5045_mic_sense_init_verbs[] = {
918 #ifdef CONFIG_SND_DEBUG
922 static const struct hda_input_mux cxt5045_test_capture_source = {
927 {
"LINE1 pin", 0x2 },
928 {
"HP-OUT pin", 0x3 },
948 CXT_EAPD_SWITCH(
"External Amplifier", 0x10, 0x0),
964 .name =
"Input Source",
965 .info = conexant_mux_enum_info,
966 .get = conexant_mux_enum_get,
967 .put = conexant_mux_enum_put,
975 static const struct hda_verb cxt5045_test_init_verbs[] = {
1023 static int cxt5045_init(
struct hda_codec *codec)
1025 conexant_init(codec);
1026 cxt5045_hp_automute(codec);
1037 #ifdef CONFIG_SND_DEBUG
1050 #ifdef CONFIG_SND_DEBUG
1051 [CXT5045_TEST] =
"test",
1056 static const struct snd_pci_quirk cxt5045_cfg_tbl[] = {
1059 SND_PCI_QUIRK(0x152d, 0x0753,
"Benq R55E",
CXT5045_BENQ),
1062 SND_PCI_QUIRK(0x1734, 0x110e,
"Fujitsu V5505",
1067 SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100,
"Packard Bell",
1073 static int patch_cxt5045(
struct hda_codec *codec)
1081 if (board_config < 0)
1084 return patch_conexant_auto(codec);
1094 spec->
multiout.dac_nids = cxt5045_dac_nids;
1099 spec->
input_mux = &cxt5045_capture_source;
1101 spec->
mixers[0] = cxt5045_mixers;
1112 switch (board_config) {
1114 codec->
patch_ops.unsol_event = cxt5045_hp_unsol_event;
1115 spec->
input_mux = &cxt5045_capture_source;
1117 spec->
init_verbs[1] = cxt5045_hp_sense_init_verbs;
1118 spec->
mixers[0] = cxt5045_mixers;
1122 codec->
patch_ops.unsol_event = cxt5045_hp_unsol_event;
1123 spec->
input_mux = &cxt5045_capture_source;
1125 spec->
init_verbs[1] = cxt5045_mic_sense_init_verbs;
1126 spec->
mixers[0] = cxt5045_mixers;
1131 codec->
patch_ops.unsol_event = cxt5045_hp_unsol_event;
1132 spec->
input_mux = &cxt5045_capture_source;
1134 spec->
init_verbs[1] = cxt5045_hp_sense_init_verbs;
1135 spec->
init_verbs[2] = cxt5045_mic_sense_init_verbs;
1136 spec->
mixers[0] = cxt5045_mixers;
1140 codec->
patch_ops.unsol_event = cxt5045_hp_unsol_event;
1141 spec->
input_mux = &cxt5045_capture_source_benq;
1143 spec->
init_verbs[0] = cxt5045_benq_init_verbs;
1144 spec->
mixers[0] = cxt5045_mixers;
1145 spec->
mixers[1] = cxt5045_benq_mixers;
1150 codec->
patch_ops.unsol_event = cxt5045_hp_unsol_event;
1151 spec->
input_mux = &cxt5045_capture_source_hp530;
1153 spec->
init_verbs[1] = cxt5045_hp_sense_init_verbs;
1154 spec->
mixers[0] = cxt5045_mixers_hp530;
1157 #ifdef CONFIG_SND_DEBUG
1159 spec->
input_mux = &cxt5045_test_capture_source;
1160 spec->
mixers[0] = cxt5045_test_mixer;
1161 spec->
init_verbs[0] = cxt5045_test_init_verbs;
1192 #define CXT5047_SPDIF_OUT 0x11
1194 static const hda_nid_t cxt5047_dac_nids[1] = { 0x10 };
1195 static const hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
1196 static const hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
1202 static const struct hda_input_mux cxt5047_toshiba_capture_source = {
1211 static int cxt5047_hp_master_sw_put(
struct snd_kcontrol *kcontrol,
1218 if (!cxt_eapd_put(kcontrol, ucontrol))
1238 static void cxt5047_hp_automute(
struct hda_codec *codec)
1252 static void cxt5047_hp_automic(
struct hda_codec *codec)
1254 static const struct hda_verb mic_jack_on[] = {
1259 static const struct hda_verb mic_jack_off[] = {
1264 unsigned int present;
1274 static void cxt5047_hp_unsol_event(
struct hda_codec *codec,
1277 switch (res >> 26) {
1279 cxt5047_hp_automute(codec);
1282 cxt5047_hp_automic(codec);
1297 .name =
"Master Playback Switch",
1299 .get = cxt_eapd_get,
1300 .put = cxt5047_hp_master_sw_put,
1301 .private_value = 0x13,
1319 static const struct hda_verb cxt5047_init_verbs[] = {
1346 static const struct hda_verb cxt5047_toshiba_init_verbs[] = {
1354 #ifdef CONFIG_SND_DEBUG
1355 static const struct hda_input_mux cxt5047_test_capture_source = {
1358 {
"LINE1 pin", 0x0 },
1359 {
"MIC1 pin", 0x1 },
1360 {
"MIC2 pin", 0x2 },
1386 CXT_EAPD_SWITCH(
"External Amplifier", 0x13, 0x0),
1408 .name =
"Input Source",
1409 .info = conexant_mux_enum_info,
1410 .get = conexant_mux_enum_get,
1411 .put = conexant_mux_enum_put,
1418 static const struct hda_verb cxt5047_test_init_verbs[] = {
1475 static int cxt5047_hp_init(
struct hda_codec *codec)
1477 conexant_init(codec);
1478 cxt5047_hp_automute(codec);
1487 #ifdef CONFIG_SND_DEBUG
1498 #ifdef CONFIG_SND_DEBUG
1499 [CXT5047_TEST] =
"test",
1504 static const struct snd_pci_quirk cxt5047_cfg_tbl[] = {
1506 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000,
"HP DV Series",
1512 static int patch_cxt5047(
struct hda_codec *codec)
1520 if (board_config < 0)
1523 return patch_conexant_auto(codec);
1533 spec->
multiout.dac_nids = cxt5047_dac_nids;
1539 spec->
mixers[0] = cxt5047_base_mixers;
1548 switch (board_config) {
1551 spec->
mixers[1] = cxt5047_hp_spk_mixers;
1552 codec->
patch_ops.unsol_event = cxt5047_hp_unsol_event;
1556 spec->
mixers[1] = cxt5047_hp_only_mixers;
1557 codec->
patch_ops.unsol_event = cxt5047_hp_unsol_event;
1558 codec->
patch_ops.init = cxt5047_hp_init;
1561 spec->
input_mux = &cxt5047_toshiba_capture_source;
1563 spec->
mixers[1] = cxt5047_hp_spk_mixers;
1565 spec->
init_verbs[1] = cxt5047_toshiba_init_verbs;
1566 codec->
patch_ops.unsol_event = cxt5047_hp_unsol_event;
1568 #ifdef CONFIG_SND_DEBUG
1570 spec->
input_mux = &cxt5047_test_capture_source;
1571 spec->
mixers[0] = cxt5047_test_mixer;
1572 spec->
init_verbs[0] = cxt5047_test_init_verbs;
1573 codec->
patch_ops.unsol_event = cxt5047_hp_unsol_event;
1596 static const hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
1597 static const hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
1603 static void cxt5051_update_speaker(
struct hda_codec *codec)
1606 unsigned int pinctl;
1609 snd_hda_set_pin_ctl(codec, 0x16, pinctl);
1612 snd_hda_set_pin_ctl(codec, 0x1a, pinctl);
1615 snd_hda_set_pin_ctl(codec, 0x1b, pinctl);
1619 static int cxt5051_hp_master_sw_put(
struct snd_kcontrol *kcontrol,
1624 if (!cxt_eapd_put(kcontrol, ucontrol))
1626 cxt5051_update_speaker(codec);
1631 static void cxt5051_portb_automic(
struct hda_codec *codec)
1634 unsigned int present;
1641 present ? 0x01 : 0x00);
1645 static void cxt5051_portc_automic(
struct hda_codec *codec)
1648 unsigned int present;
1670 static void cxt5051_hp_automute(
struct hda_codec *codec)
1675 cxt5051_update_speaker(codec);
1679 static void cxt5051_hp_unsol_event(
struct hda_codec *codec,
1682 switch (res >> 26) {
1684 cxt5051_hp_automute(codec);
1687 cxt5051_portb_automic(codec);
1690 cxt5051_portc_automic(codec);
1699 .name =
"Master Playback Switch",
1701 .get = cxt_eapd_get,
1702 .put = cxt5051_hp_master_sw_put,
1703 .private_value = 0x1a,
1746 static const struct hda_verb cxt5051_init_verbs[] = {
1775 static const struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
1800 static const struct hda_verb cxt5051_f700_init_verbs[] = {
1833 static const struct hda_verb cxt5051_ideapad_init_verbs[] = {
1841 static int cxt5051_init(
struct hda_codec *codec)
1845 conexant_init(codec);
1853 cxt5051_hp_automute(codec);
1854 cxt5051_portb_automic(codec);
1855 cxt5051_portc_automic(codec);
1882 static const struct snd_pci_quirk cxt5051_cfg_tbl[] = {
1884 SND_PCI_QUIRK(0x103c, 0x360b,
"Compaq Presario CQ60",
CXT5051_HP),
1885 SND_PCI_QUIRK(0x103c, 0x30ea,
"Compaq Presario F700",
CXT5051_F700),
1887 SND_PCI_QUIRK(0x14f1, 0x0101,
"Conexant Reference board",
1889 SND_PCI_QUIRK(0x14f1, 0x5051,
"HP Spartan 1.1",
CXT5051_HP),
1894 static int patch_cxt5051(
struct hda_codec *codec)
1902 if (board_config < 0)
1905 return patch_conexant_auto(codec);
1918 spec->
multiout.dac_nids = cxt5051_dac_nids;
1923 spec->
mixers[0] = cxt5051_capture_mixers;
1924 spec->
mixers[1] = cxt5051_playback_mixers;
1935 codec->
patch_ops.unsol_event = cxt5051_hp_unsol_event;
1938 switch (board_config) {
1940 spec->
mixers[0] = cxt5051_hp_mixers;
1943 spec->
init_verbs[0] = cxt5051_hp_dv6736_init_verbs;
1944 spec->
mixers[0] = cxt5051_hp_dv6736_mixers;
1948 spec->
init_verbs[0] = cxt5051_f700_init_verbs;
1949 spec->
mixers[0] = cxt5051_f700_mixers;
1953 spec->
mixers[0] = cxt5051_toshiba_mixers;
1958 cxt5051_ideapad_init_verbs;
1971 static const hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
1972 static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
1973 static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
1974 static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 };
1979 #define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50
1985 #define HP_PRESENT_PORT_A (1 << 0)
1986 #define HP_PRESENT_PORT_D (1 << 1)
1987 #define hp_port_a_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_A)
1988 #define hp_port_d_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_D)
1990 static void cxt5066_update_speaker(
struct hda_codec *codec)
1993 unsigned int pinctl;
1995 snd_printdd(
"CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n",
2000 snd_hda_set_pin_ctl(codec, 0x19, pinctl);
2013 snd_hda_set_pin_ctl(codec, 0x1c, pinctl);
2017 snd_hda_set_pin_ctl(codec, 0x1f, pinctl);
2021 static int cxt5066_hp_master_sw_put(
struct snd_kcontrol *kcontrol,
2026 if (!cxt_eapd_put(kcontrol, ucontrol))
2029 cxt5066_update_speaker(codec);
2042 static int cxt5066_set_olpc_dc_bias(
struct hda_codec *codec)
2048 return snd_hda_set_pin_ctl_cache(codec, 0x1a,
2056 static void cxt5066_olpc_select_mic(
struct hda_codec *codec)
2065 const struct hda_verb enable_dc_mode[] = {
2076 cxt5066_set_olpc_dc_bias(codec);
2081 snd_hda_set_pin_ctl(codec, 0x1e, 0);
2084 snd_hda_set_pin_ctl(codec, 0x1a,
2088 snd_hda_set_pin_ctl(codec, 0x1b,
2093 static void cxt5066_olpc_automic(
struct hda_codec *codec)
2096 unsigned int present;
2104 snd_printdd(
"CXT5066: external microphone detected\n");
2106 snd_printdd(
"CXT5066: external microphone absent\n");
2112 cxt5066_olpc_select_mic(codec);
2116 static void cxt5066_vostro_automic(
struct hda_codec *codec)
2118 unsigned int present;
2120 struct hda_verb ext_mic_present[] = {
2132 static const struct hda_verb ext_mic_absent[] = {
2146 snd_printdd(
"CXT5066: external microphone detected\n");
2149 snd_printdd(
"CXT5066: external microphone absent\n");
2155 static void cxt5066_ideapad_automic(
struct hda_codec *codec)
2157 unsigned int present;
2159 struct hda_verb ext_mic_present[] = {
2165 static const struct hda_verb ext_mic_absent[] = {
2174 snd_printdd(
"CXT5066: external microphone detected\n");
2177 snd_printdd(
"CXT5066: external microphone absent\n");
2184 static void cxt5066_asus_automic(
struct hda_codec *codec)
2186 unsigned int present;
2189 snd_printdd(
"CXT5066: external microphone present=%d\n", present);
2196 static void cxt5066_hp_laptop_automic(
struct hda_codec *codec)
2198 unsigned int present;
2201 snd_printdd(
"CXT5066: external microphone present=%d\n", present);
2209 static void cxt5066_thinkpad_automic(
struct hda_codec *codec)
2211 unsigned int ext_present, dock_present;
2213 static const struct hda_verb ext_mic_present[] = {
2221 static const struct hda_verb dock_mic_present[] = {
2229 static const struct hda_verb ext_mic_absent[] = {
2240 snd_printdd(
"CXT5066: external microphone detected\n");
2242 }
else if (dock_present) {
2243 snd_printdd(
"CXT5066: dock microphone detected\n");
2246 snd_printdd(
"CXT5066: external microphone absent\n");
2252 static void cxt5066_hp_automute(
struct hda_codec *codec)
2255 unsigned int portA, portD;
2265 snd_printdd(
"CXT5066: hp automute portA=%x portD=%x present=%d\n",
2267 cxt5066_update_speaker(codec);
2271 static void cxt5066_automic(
struct hda_codec *codec)
2276 cxt5066_vostro_automic(codec);
2278 cxt5066_ideapad_automic(codec);
2280 cxt5066_thinkpad_automic(codec);
2282 cxt5066_hp_laptop_automic(codec);
2283 else if (spec->
asus)
2284 cxt5066_asus_automic(codec);
2288 static void cxt5066_olpc_unsol_event(
struct hda_codec *codec,
unsigned int res)
2291 snd_printdd(
"CXT5066: unsol event %x (%x)\n", res, res >> 26);
2292 switch (res >> 26) {
2294 cxt5066_hp_automute(codec);
2299 cxt5066_olpc_automic(codec);
2305 static void cxt5066_unsol_event(
struct hda_codec *codec,
unsigned int res)
2307 snd_printdd(
"CXT5066: unsol event %x (%x)\n", res, res >> 26);
2308 switch (res >> 26) {
2310 cxt5066_hp_automute(codec);
2313 cxt5066_automic(codec);
2319 static const struct hda_input_mux cxt5066_analog_mic_boost = {
2330 static void cxt5066_set_mic_boost(
struct hda_codec *codec)
2342 cxt5066_analog_mic_boost.
2347 static int cxt5066_mic_boost_mux_enum_info(
struct snd_kcontrol *kcontrol,
2353 static int cxt5066_mic_boost_mux_enum_get(
struct snd_kcontrol *kcontrol,
2362 static int cxt5066_mic_boost_mux_enum_put(
struct snd_kcontrol *kcontrol,
2367 const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
2369 idx = ucontrol->
value.enumerated.item[0];
2375 cxt5066_set_mic_boost(codec);
2379 static void cxt5066_enable_dc(
struct hda_codec *codec)
2381 const struct hda_verb enable_dc_mode[] = {
2392 cxt5066_olpc_select_mic(codec);
2395 static void cxt5066_disable_dc(
struct hda_codec *codec)
2398 cxt5066_set_mic_boost(codec);
2400 cxt5066_olpc_automic(codec);
2403 static int cxt5066_olpc_dc_get(
struct snd_kcontrol *kcontrol,
2412 static int cxt5066_olpc_dc_put(
struct snd_kcontrol *kcontrol,
2424 cxt5066_enable_dc(codec);
2426 cxt5066_disable_dc(codec);
2431 static int cxt5066_olpc_dc_bias_enum_info(
struct snd_kcontrol *kcontrol,
2437 static int cxt5066_olpc_dc_bias_enum_get(
struct snd_kcontrol *kcontrol,
2446 static int cxt5066_olpc_dc_bias_enum_put(
struct snd_kcontrol *kcontrol,
2451 const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
2454 idx = ucontrol->
value.enumerated.item[0];
2460 cxt5066_set_olpc_dc_bias(codec);
2464 static void cxt5066_olpc_capture_prepare(
struct hda_codec *codec)
2470 cxt5066_olpc_select_mic(codec);
2473 static void cxt5066_olpc_capture_cleanup(
struct hda_codec *codec)
2476 const struct hda_verb disable_mics[] = {
2492 static void conexant_check_dig_outs(
struct hda_codec *codec,
2500 for (i = 0; i < num_pins; i++, dig_pins++) {
2513 static const struct hda_input_mux cxt5066_capture_source = {
2523 static const struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
2532 static const struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
2549 .name =
"Master Playback Volume",
2568 .name =
"DC Mode Enable Switch",
2570 .get = cxt5066_olpc_dc_get,
2571 .put = cxt5066_olpc_dc_put,
2575 .name =
"DC Input Bias Enum",
2576 .info = cxt5066_olpc_dc_bias_enum_info,
2577 .get = cxt5066_olpc_dc_bias_enum_get,
2578 .put = cxt5066_olpc_dc_bias_enum_put,
2586 .name =
"Master Playback Switch",
2588 .get = cxt_eapd_get,
2589 .put = cxt5066_hp_master_sw_put,
2590 .private_value = 0x1d,
2595 .name =
"Analog Mic Boost Capture Enum",
2596 .info = cxt5066_mic_boost_mux_enum_info,
2597 .get = cxt5066_mic_boost_mux_enum_get,
2598 .put = cxt5066_mic_boost_mux_enum_put,
2601 HDA_BIND_VOL(
"Capture Volume", &cxt5066_bind_capture_vol_others),
2602 HDA_BIND_SW(
"Capture Switch", &cxt5066_bind_capture_sw_others),
2609 .name =
"Internal Mic Boost Capture Enum",
2610 .info = cxt5066_mic_boost_mux_enum_info,
2611 .get = cxt5066_mic_boost_mux_enum_get,
2612 .put = cxt5066_mic_boost_mux_enum_put,
2613 .private_value = 0x23 | 0x100,
2618 static const struct hda_verb cxt5066_init_verbs[] = {
2673 static const struct hda_verb cxt5066_init_verbs_olpc[] = {
2734 static const struct hda_verb cxt5066_init_verbs_vostro[] = {
2795 static const struct hda_verb cxt5066_init_verbs_ideapad[] = {
2845 static const struct hda_verb cxt5066_init_verbs_thinkpad[] = {
2903 static const struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2909 static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = {
2917 static int cxt5066_init(
struct hda_codec *codec)
2920 conexant_init(codec);
2922 cxt5066_hp_automute(codec);
2923 cxt5066_automic(codec);
2925 cxt5066_set_mic_boost(codec);
2929 static int cxt5066_olpc_init(
struct hda_codec *codec)
2933 conexant_init(codec);
2934 cxt5066_hp_automute(codec);
2936 cxt5066_set_mic_boost(codec);
2937 cxt5066_olpc_automic(codec);
2939 cxt5066_enable_dc(codec);
2969 static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2974 SND_PCI_QUIRK(0x1028, 0x0408,
"Dell Inspiron One 19T",
CXT5066_IDEAPAD),
2978 SND_PCI_QUIRK(0x1043, 0x13f3,
"Asus A52J",
CXT5066_ASUS),
2979 SND_PCI_QUIRK(0x1043, 0x1643,
"Asus K52JU",
CXT5066_ASUS),
2980 SND_PCI_QUIRK(0x1043, 0x1993,
"Asus U50F",
CXT5066_ASUS),
2981 SND_PCI_QUIRK(0x1179, 0xff1e,
"Toshiba Satellite C650D",
CXT5066_IDEAPAD),
2982 SND_PCI_QUIRK(0x1179, 0xff50,
"Toshiba Satellite P500-PSPGSC-01800T",
CXT5066_OLPC_XO_1_5),
2983 SND_PCI_QUIRK(0x14f1, 0x0101,
"Conexant Reference board",
2988 SND_PCI_QUIRK(0x17aa, 0x21c6,
"Thinkpad Edge 13",
CXT5066_ASUS),
2991 SND_PCI_QUIRK(0x17aa, 0x3a0d,
"Lenovo U350",
CXT5066_ASUS),
2992 SND_PCI_QUIRK(0x17aa, 0x38af,
"Lenovo G560",
CXT5066_ASUS),
2996 static int patch_cxt5066(
struct hda_codec *codec)
3002 cxt5066_models, cxt5066_cfg_tbl);
3003 if (board_config < 0)
3006 return patch_conexant_auto(codec);
3019 spec->
multiout.dac_nids = cxt5066_dac_nids;
3020 conexant_check_dig_outs(codec, cxt5066_digout_pin_nids,
3025 spec->
input_mux = &cxt5066_capture_source;
3038 switch (board_config) {
3056 codec->
patch_ops.unsol_event = cxt5066_unsol_event;
3058 cxt5066_init_verbs_hp_laptop;
3074 codec->
patch_ops.init = cxt5066_olpc_init;
3075 codec->
patch_ops.unsol_event = cxt5066_olpc_unsol_event;
3076 spec->
init_verbs[0] = cxt5066_init_verbs_olpc;
3096 codec->
patch_ops.unsol_event = cxt5066_unsol_event;
3097 spec->
init_verbs[0] = cxt5066_init_verbs_vostro;
3113 codec->
patch_ops.unsol_event = cxt5066_unsol_event;
3116 spec->
init_verbs[0] = cxt5066_init_verbs_ideapad;
3129 codec->
patch_ops.unsol_event = cxt5066_unsol_event;
3132 spec->
init_verbs[0] = cxt5066_init_verbs_thinkpad;
3155 static int cx_auto_capture_pcm_prepare(
struct hda_pcm_stream *hinfo,
3157 unsigned int stream_tag,
3158 unsigned int format,
3172 static int cx_auto_capture_pcm_cleanup(
struct hda_pcm_stream *hinfo,
3182 static const struct hda_pcm_stream cx_auto_pcm_analog_capture = {
3188 .prepare = cx_auto_capture_pcm_prepare,
3189 .cleanup = cx_auto_capture_pcm_cleanup
3193 static const hda_nid_t cx_auto_adc_nids[] = { 0x14 };
3195 #define get_connection_index(codec, mux, nid)\
3196 snd_hda_get_conn_index(codec, mux, nid, 0)
3205 int i, nums = *num_dacs;
3208 for (i = 0; i < nums; i++) {
3222 #define MAX_AUTO_DACS 5
3224 #define DAC_SLAVE_FLAG 0x8000
3233 for (nid = codec->
start_nid; nid < end_nid; nid++) {
3234 unsigned int wcaps = get_wcaps(codec, nid);
3235 unsigned int type = get_wcaps_type(wcaps);
3253 for (i = 0; i < num_pins; i++, nums++) {
3254 filled[nums].
pin = pins[
i];
3256 filled[nums].
dac = get_unassigned_dac(codec, pins[i], dacs, rest);
3257 if (filled[nums].dac)
3267 snd_printdd(
"Failed to find a DAC for pin 0x%x", pins[i]);
3273 static void cx_auto_parse_output(
struct hda_codec *codec)
3280 rest = fill_cx_auto_dacs(codec, dacs);
3293 for (i = 0; i < nums; i++) {
3309 if (!spec->
multiout.extra_out_nid[j]) {
3319 for (i = 0; i < cfg->
hp_outs; i++) {
3342 static void cx_auto_turn_eapd(
struct hda_codec *codec,
int num_pins,
3345 static void do_automute(
struct hda_codec *codec,
int num_pins,
3350 for (i = 0; i < num_pins; i++)
3351 snd_hda_set_pin_ctl(codec, pins[i], on ?
PIN_OUT : 0);
3353 cx_auto_turn_eapd(codec, num_pins, pins, on);
3360 for (i = 0; i < num_pins; i++) {
3370 static void cx_auto_update_speakers(
struct hda_codec *codec)
3413 cx_auto_update_speakers(codec);
3425 cx_auto_update_speakers(codec);
3428 static int cx_automute_mode_info(
struct snd_kcontrol *kcontrol,
3433 static const char *
const texts2[] = {
3434 "Disabled",
"Enabled"
3436 static const char *
const texts3[] = {
3437 "Disabled",
"Speaker Only",
"Line Out+Speaker"
3439 const char *
const *texts;
3457 static int cx_automute_mode_get(
struct snd_kcontrol *kcontrol,
3469 ucontrol->
value.enumerated.item[0] =
val;
3473 static int cx_automute_mode_put(
struct snd_kcontrol *kcontrol,
3479 switch (ucontrol->
value.enumerated.item[0]) {
3502 cx_auto_update_speakers(codec);
3509 .name =
"Auto-Mute Mode",
3510 .info = cx_automute_mode_info,
3511 .get = cx_automute_mode_get,
3512 .put = cx_automute_mode_put,
3517 static int cx_auto_mux_enum_info(
struct snd_kcontrol *kcontrol,
3526 static int cx_auto_mux_enum_get(
struct snd_kcontrol *kcontrol,
3545 int startidx,
i, nums;
3547 switch (get_wcaps_type(get_wcaps(codec, mux))) {
3557 for (i = 0; i < nums; i++)
3558 if (conn[i] == pin) {
3579 for (i = 0; i < nums; i++) {
3580 int j = (i + startidx) % nums;
3581 int ret = __select_input_connection(codec, conn[j], pin, srcp,
3596 __select_input_connection(codec, mux, pin,
NULL,
true, 0);
3602 return __select_input_connection(codec, mux, pin,
NULL,
false, 0);
3605 static int cx_auto_mux_enum_update(
struct hda_codec *codec,
3620 select_input_connection(codec, spec->
imux_info[idx].adc,
3634 static int cx_auto_mux_enum_put(
struct snd_kcontrol *kcontrol,
3640 return cx_auto_mux_enum_update(codec, &spec->
private_imux,
3641 ucontrol->
value.enumerated.item[0]);
3647 .name =
"Capture Source",
3648 .info = cx_auto_mux_enum_info,
3649 .get = cx_auto_mux_enum_get,
3650 .put = cx_auto_mux_enum_put
3655 static bool select_automic(
struct hda_codec *codec,
int idx,
bool detect)
3662 cx_auto_mux_enum_update(codec, &spec->
private_imux, idx);
3682 static void cx_auto_check_auto_mic(
struct hda_codec *codec)
3706 if (pset[attr] >= 0)
3719 static void cx_auto_parse_input(
struct hda_codec *codec)
3730 int idx = get_input_connection(codec, adc,
3746 cx_auto_check_auto_mic(codec);
3763 for (nid = codec->
start_nid; nid < end_nid; nid++) {
3764 unsigned int wcaps = get_wcaps(codec, nid);
3765 unsigned int type = get_wcaps_type(wcaps);
3774 static void cx_auto_parse_digital(
struct hda_codec *codec)
3787 #ifdef CONFIG_SND_HDA_INPUT_BEEP
3794 for (nid = codec->
start_nid; nid < end_nid; nid++)
3795 if (get_wcaps_type(get_wcaps(codec, nid)) ==
AC_WID_BEEP) {
3801 #define cx_auto_parse_beep(codec)
3805 static void cx_auto_parse_eapd(
struct hda_codec *codec)
3811 for (nid = codec->
start_nid; nid < end_nid; nid++) {
3812 if (get_wcaps_type(get_wcaps(codec, nid)) !=
AC_WID_PIN)
3830 static int cx_auto_parse_auto_config(
struct hda_codec *codec)
3839 cx_auto_parse_output(codec);
3840 cx_auto_parse_input(codec);
3841 cx_auto_parse_digital(codec);
3843 cx_auto_parse_eapd(codec);
3847 static void cx_auto_turn_eapd(
struct hda_codec *codec,
int num_pins,
3851 for (i = 0; i < num_pins; i++) {
3868 static void mute_outputs(
struct hda_codec *codec,
int num_nids,
3873 for (i = 0; i < num_nids; i++) {
3886 static void enable_unsol_pins(
struct hda_codec *codec,
int num_pins,
3891 for (i = 0; i < num_pins; i++)
3898 for (i = 0; i < nums; i++)
3915 if (cfg->
inputs[i].pin == nid)
3925 static void clear_unsol_on_unused_pins(
struct hda_codec *codec)
3931 for (i = 0; i < codec->
init_pins.used; i++) {
3933 if (!found_in_autocfg(cfg, pin->
nid))
3946 cx_auto_update_speakers(codec);
3952 static void cx_auto_init_output(
struct hda_codec *codec)
3960 for (i = 0; i < cfg->
hp_outs; i++) {
3965 snd_hda_set_pin_ctl(codec, cfg->
hp_pins[i], val);
3974 else if (nid & DAC_SLAVE_FLAG)
3975 nid &= ~DAC_SLAVE_FLAG;
3976 select_connection(codec, spec->
dac_info[i].pin, nid);
3984 enable_unsol_pins(codec, cfg->
line_outs,
3987 cx_auto_line_automute);
3993 cx_auto_update_speakers(codec);
3997 clear_unsol_on_unused_pins(codec);
4000 static void cx_auto_init_input(
struct hda_codec *codec)
4020 unsigned int type =
PIN_IN;
4023 snd_hda_set_pin_ctl(codec, pin, type);
4037 cx_auto_automic(codec,
NULL);
4039 select_input_connection(codec, spec->
imux_info[0].adc,
4044 static void cx_auto_init_digital(
struct hda_codec *codec)
4050 snd_hda_set_pin_ctl(codec, cfg->
dig_out_pins[0], PIN_OUT);
4055 static int cx_auto_init(
struct hda_codec *codec)
4059 cx_auto_init_output(codec);
4060 cx_auto_init_input(codec);
4061 cx_auto_init_digital(codec);
4066 static int cx_auto_add_volume_idx(
struct hda_codec *codec,
const char *basename,
4067 const char *dir,
int cidx,
4068 hda_nid_t nid,
int hda_dir,
int amp_idx,
int chs)
4070 static char name[44];
4075 static const char *
const sfx[2] = {
"Volume",
"Switch" };
4078 for (i = 0; i < 2; i++) {
4084 snprintf(name,
sizeof(name),
"%s%s %s", basename, dir, sfx[i]);
4098 #define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \
4099 cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0, 3)
4101 #define cx_auto_add_pb_volume(codec, nid, str, idx) \
4102 cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
4105 hda_nid_t pin,
const char *name,
int idx)
4108 if (dac && !(dac & DAC_SLAVE_FLAG)) {
4119 static int cx_auto_build_output_controls(
struct hda_codec *codec)
4123 int num_line = 0, num_hp = 0, num_spk = 0;
4124 static const char *
const texts[3] = {
"Front",
"Surround",
"CLFE" };
4127 return try_add_pb_volume(codec, spec->
dac_info[0].dac,
4137 type = spec->
autocfg.line_out_type;
4141 label = texts[num_line++];
4145 label =
"Headphone";
4153 err = try_add_pb_volume(codec, dac,
4172 static int cx_auto_get_rightch_label(
struct hda_codec *codec,
const char *label,
4173 char *dest_label,
int nid)
4183 if (spec->
autocfg.inputs[i].pin != nid)
4193 snprintf(dest_label, 44,
"Inverted %s", label);
4200 const char *label,
const char *pfx,
4207 char rightch_label[44];
4209 int idx = get_input_connection(codec, adc_nid, nid);
4215 if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) {
4217 int err = cx_auto_add_volume_idx(codec, label, pfx,
4221 return cx_auto_add_volume_idx(codec, rightch_label, pfx,
4224 return cx_auto_add_volume_idx(codec, label, pfx,
4230 static int cx_auto_add_boost_volume(
struct hda_codec *codec,
int idx,
4231 const char *label,
int cidx)
4238 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
4239 char rightch_label[44];
4240 if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) {
4241 int err = cx_auto_add_volume_idx(codec, label,
" Boost",
4245 return cx_auto_add_volume_idx(codec, rightch_label,
" Boost",
4251 con = __select_input_connection(codec, spec->
imux_info[idx].adc, nid,
4255 for (i = 0; i <
idx; i++) {
4260 if (get_wcaps(codec, mux) & AC_WCAP_OUT_AMP) {
4268 static int cx_auto_build_input_controls(
struct hda_codec *codec)
4272 const char *prev_label;
4274 int i,
j,
err, cidx;
4275 int multi_connection;
4280 multi_connection = 0;
4282 cidx = get_input_connection(codec, spec->
imux_info[i].adc,
4288 input_conn[
i] |= cidx << 8;
4289 if (i > 0 && input_conn[i] != input_conn[0])
4290 multi_connection = 1;
4301 if (label == prev_label)
4307 err = cx_auto_add_boost_volume(codec, i, label, cidx);
4311 if (!multi_connection) {
4314 err = cx_auto_add_capture_volume(codec, nid,
4315 "Capture",
"", cidx);
4317 bool dup_found =
false;
4318 for (j = 0; j <
i; j++) {
4319 if (input_conn[j] == input_conn[i]) {
4326 err = cx_auto_add_capture_volume(codec, nid,
4327 label,
" Capture", cidx);
4342 static int cx_auto_build_controls(
struct hda_codec *codec)
4347 err = cx_auto_build_output_controls(codec);
4350 err = cx_auto_build_input_controls(codec);
4353 err = conexant_build_controls(codec);
4369 static int cx_auto_search_adcs(
struct hda_codec *codec)
4375 for (nid = codec->
start_nid; nid < end_nid; nid++) {
4376 unsigned int caps = get_wcaps(codec, nid);
4379 if (caps & AC_WCAP_DIGITAL)
4391 .build_controls = cx_auto_build_controls,
4392 .build_pcms = conexant_build_pcms,
4393 .init = cx_auto_init,
4394 .free = conexant_free,
4397 .suspend = conexant_suspend,
4411 static void cxt_fixup_stereo_dmic(
struct hda_codec *codec,
4412 const struct hda_fixup *fix,
int action)
4419 static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
4420 { 0x16, 0x042140ff },
4421 { 0x17, 0x21a11000 },
4422 { 0x19, 0x2121103f },
4423 { 0x1c, 0x21440100 },
4428 static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = {
4429 { 0x19, 0x042110ff },
4430 { 0x1a, 0x21a190f0 },
4431 { 0x1c, 0x212140ff },
4435 static const struct hda_fixup cxt_fixups[] = {
4438 .v.pins = cxt_pincfg_lenovo_x200,
4442 .v.pins = cxt_pincfg_lenovo_tp410,
4446 .v.func = cxt_fixup_stereo_dmic,
4450 static const struct snd_pci_quirk cxt5051_fixups[] = {
4455 static const struct snd_pci_quirk cxt5066_fixups[] = {
4470 static void add_cx5051_fake_mutes(
struct hda_codec *codec)
4477 for (p = out_nids; *
p; p++)
4483 static int patch_conexant_auto(
struct hda_codec *codec)
4495 snd_hda_gen_init(&spec->
gen);
4502 add_cx5051_fake_mutes(codec);
4526 err = cx_auto_search_adcs(codec);
4529 err = cx_auto_parse_auto_config(codec);
4544 if (!codec->
bus->sync_write) {
4546 "Enable sync_write for stable communication\n");
4547 codec->
bus->sync_write = 1;
4548 codec->
bus->allow_bus_reset = 1;
4558 { .id = 0x14f15045, .name =
"CX20549 (Venice)",
4559 .patch = patch_cxt5045 },
4560 { .id = 0x14f15047, .name =
"CX20551 (Waikiki)",
4561 .patch = patch_cxt5047 },
4562 { .id = 0x14f15051, .name =
"CX20561 (Hermosa)",
4563 .patch = patch_cxt5051 },
4564 { .id = 0x14f15066, .name =
"CX20582 (Pebble)",
4565 .patch = patch_cxt5066 },
4566 { .id = 0x14f15067, .name =
"CX20583 (Pebble HSF)",
4567 .patch = patch_cxt5066 },
4568 { .id = 0x14f15068, .name =
"CX20584",
4569 .patch = patch_cxt5066 },
4570 { .id = 0x14f15069, .name =
"CX20585",
4571 .patch = patch_cxt5066 },
4572 { .id = 0x14f1506c, .name =
"CX20588",
4573 .patch = patch_cxt5066 },
4574 { .id = 0x14f1506e, .name =
"CX20590",
4575 .patch = patch_cxt5066 },
4576 { .id = 0x14f15097, .name =
"CX20631",
4577 .patch = patch_conexant_auto },
4578 { .id = 0x14f15098, .name =
"CX20632",
4579 .patch = patch_conexant_auto },
4580 { .id = 0x14f150a1, .name =
"CX20641",
4581 .patch = patch_conexant_auto },
4582 { .id = 0x14f150a2, .name =
"CX20642",
4583 .patch = patch_conexant_auto },
4584 { .id = 0x14f150ab, .name =
"CX20651",
4585 .patch = patch_conexant_auto },
4586 { .id = 0x14f150ac, .name =
"CX20652",
4587 .patch = patch_conexant_auto },
4588 { .id = 0x14f150b8, .name =
"CX20664",
4589 .patch = patch_conexant_auto },
4590 { .id = 0x14f150b9, .name =
"CX20665",
4591 .patch = patch_conexant_auto },
4592 { .id = 0x14f1510f, .name =
"CX20751/2",
4593 .patch = patch_conexant_auto },
4594 { .id = 0x14f15110, .name =
"CX20751/2",
4595 .patch = patch_conexant_auto },
4596 { .id = 0x14f15111, .name =
"CX20753/4",
4597 .patch = patch_conexant_auto },
4626 .preset = snd_hda_preset_conexant,
4630 static int __init patch_conexant_init(
void)
4635 static void __exit patch_conexant_exit(
void)