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.c248
1 files changed, 200 insertions, 48 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 3fbbc8c01e70..c578c28f368e 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -29,6 +29,7 @@
29 29
30#include "hda_codec.h" 30#include "hda_codec.h"
31#include "hda_local.h" 31#include "hda_local.h"
32#include "hda_beep.h"
32 33
33#define CXT_PIN_DIR_IN 0x00 34#define CXT_PIN_DIR_IN 0x00
34#define CXT_PIN_DIR_OUT 0x01 35#define CXT_PIN_DIR_OUT 0x01
@@ -110,6 +111,8 @@ struct conexant_spec {
110 111
111 unsigned int dell_automute; 112 unsigned int dell_automute;
112 unsigned int port_d_mode; 113 unsigned int port_d_mode;
114 unsigned char ext_mic_bias;
115 unsigned int dell_vostro;
113}; 116};
114 117
115static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, 118static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@@ -396,9 +399,7 @@ static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
396 for (i = 0; i < spec->jacks.used; i++) { 399 for (i = 0; i < spec->jacks.used; i++) {
397 if (jacks->nid == nid) { 400 if (jacks->nid == nid) {
398 unsigned int present; 401 unsigned int present;
399 present = snd_hda_codec_read(codec, nid, 0, 402 present = snd_hda_jack_detect(codec, nid);
400 AC_VERB_GET_PIN_SENSE, 0) &
401 AC_PINSENSE_PRESENCE;
402 403
403 present = (present) ? jacks->type : 0 ; 404 present = (present) ? jacks->type : 0 ;
404 405
@@ -477,6 +478,7 @@ static void conexant_free(struct hda_codec *codec)
477 snd_array_free(&spec->jacks); 478 snd_array_free(&spec->jacks);
478 } 479 }
479#endif 480#endif
481 snd_hda_detach_beep_device(codec);
480 kfree(codec->spec); 482 kfree(codec->spec);
481} 483}
482 484
@@ -749,8 +751,7 @@ static void cxt5045_hp_automic(struct hda_codec *codec)
749 }; 751 };
750 unsigned int present; 752 unsigned int present;
751 753
752 present = snd_hda_codec_read(codec, 0x12, 0, 754 present = snd_hda_jack_detect(codec, 0x12);
753 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
754 if (present) 755 if (present)
755 snd_hda_sequence_write(codec, mic_jack_on); 756 snd_hda_sequence_write(codec, mic_jack_on);
756 else 757 else
@@ -764,8 +765,7 @@ static void cxt5045_hp_automute(struct hda_codec *codec)
764 struct conexant_spec *spec = codec->spec; 765 struct conexant_spec *spec = codec->spec;
765 unsigned int bits; 766 unsigned int bits;
766 767
767 spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, 768 spec->hp_present = snd_hda_jack_detect(codec, 0x11);
768 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
769 769
770 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 770 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
771 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, 771 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
@@ -1174,9 +1174,10 @@ static int patch_cxt5045(struct hda_codec *codec)
1174 1174
1175 switch (codec->subsystem_id >> 16) { 1175 switch (codec->subsystem_id >> 16) {
1176 case 0x103c: 1176 case 0x103c:
1177 /* HP laptop has a really bad sound over 0dB on NID 0x17. 1177 case 0x1734:
1178 * Fix max PCM level to 0 dB 1178 /* HP & Fujitsu-Siemens laptops have really bad sound over 0dB
1179 * (originall it has 0x2b steps with 0dB offset 0x14) 1179 * on NID 0x17. Fix max PCM level to 0 dB
1180 * (originally it has 0x2b steps with 0dB offset 0x14)
1180 */ 1181 */
1181 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, 1182 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
1182 (0x14 << AC_AMPCAP_OFFSET_SHIFT) | 1183 (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
@@ -1242,8 +1243,7 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
1242 struct conexant_spec *spec = codec->spec; 1243 struct conexant_spec *spec = codec->spec;
1243 unsigned int bits; 1244 unsigned int bits;
1244 1245
1245 spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, 1246 spec->hp_present = snd_hda_jack_detect(codec, 0x13);
1246 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1247 1247
1248 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 1248 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
1249 /* See the note in cxt5047_hp_master_sw_put */ 1249 /* See the note in cxt5047_hp_master_sw_put */
@@ -1266,8 +1266,7 @@ static void cxt5047_hp_automic(struct hda_codec *codec)
1266 }; 1266 };
1267 unsigned int present; 1267 unsigned int present;
1268 1268
1269 present = snd_hda_codec_read(codec, 0x15, 0, 1269 present = snd_hda_jack_detect(codec, 0x15);
1270 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1271 if (present) 1270 if (present)
1272 snd_hda_sequence_write(codec, mic_jack_on); 1271 snd_hda_sequence_write(codec, mic_jack_on);
1273 else 1272 else
@@ -1414,16 +1413,7 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = {
1414 .get = conexant_mux_enum_get, 1413 .get = conexant_mux_enum_get,
1415 .put = conexant_mux_enum_put, 1414 .put = conexant_mux_enum_put,
1416 }, 1415 },
1417 HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT), 1416 HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
1418 HDA_CODEC_MUTE("Input-1 Switch", 0x1a, 0x0, HDA_INPUT),
1419 HDA_CODEC_VOLUME("Input-2 Volume", 0x1a, 0x1, HDA_INPUT),
1420 HDA_CODEC_MUTE("Input-2 Switch", 0x1a, 0x1, HDA_INPUT),
1421 HDA_CODEC_VOLUME("Input-3 Volume", 0x1a, 0x2, HDA_INPUT),
1422 HDA_CODEC_MUTE("Input-3 Switch", 0x1a, 0x2, HDA_INPUT),
1423 HDA_CODEC_VOLUME("Input-4 Volume", 0x1a, 0x3, HDA_INPUT),
1424 HDA_CODEC_MUTE("Input-4 Switch", 0x1a, 0x3, HDA_INPUT),
1425 HDA_CODEC_VOLUME("Input-5 Volume", 0x1a, 0x4, HDA_INPUT),
1426 HDA_CODEC_MUTE("Input-5 Switch", 0x1a, 0x4, HDA_INPUT),
1427 1417
1428 { } /* end */ 1418 { } /* end */
1429}; 1419};
@@ -1620,9 +1610,7 @@ static void cxt5051_portb_automic(struct hda_codec *codec)
1620 1610
1621 if (spec->no_auto_mic) 1611 if (spec->no_auto_mic)
1622 return; 1612 return;
1623 present = snd_hda_codec_read(codec, 0x17, 0, 1613 present = snd_hda_jack_detect(codec, 0x17);
1624 AC_VERB_GET_PIN_SENSE, 0) &
1625 AC_PINSENSE_PRESENCE;
1626 snd_hda_codec_write(codec, 0x14, 0, 1614 snd_hda_codec_write(codec, 0x14, 0,
1627 AC_VERB_SET_CONNECT_SEL, 1615 AC_VERB_SET_CONNECT_SEL,
1628 present ? 0x01 : 0x00); 1616 present ? 0x01 : 0x00);
@@ -1637,9 +1625,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
1637 1625
1638 if (spec->no_auto_mic) 1626 if (spec->no_auto_mic)
1639 return; 1627 return;
1640 present = snd_hda_codec_read(codec, 0x18, 0, 1628 present = snd_hda_jack_detect(codec, 0x18);
1641 AC_VERB_GET_PIN_SENSE, 0) &
1642 AC_PINSENSE_PRESENCE;
1643 if (present) 1629 if (present)
1644 spec->cur_adc_idx = 1; 1630 spec->cur_adc_idx = 1;
1645 else 1631 else
@@ -1660,9 +1646,7 @@ static void cxt5051_hp_automute(struct hda_codec *codec)
1660{ 1646{
1661 struct conexant_spec *spec = codec->spec; 1647 struct conexant_spec *spec = codec->spec;
1662 1648
1663 spec->hp_present = snd_hda_codec_read(codec, 0x16, 0, 1649 spec->hp_present = snd_hda_jack_detect(codec, 0x16);
1664 AC_VERB_GET_PIN_SENSE, 0) &
1665 AC_PINSENSE_PRESENCE;
1666 cxt5051_update_speaker(codec); 1650 cxt5051_update_speaker(codec);
1667} 1651}
1668 1652
@@ -1927,6 +1911,11 @@ static hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
1927static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 }; 1911static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
1928#define CXT5066_SPDIF_OUT 0x21 1912#define CXT5066_SPDIF_OUT 0x21
1929 1913
1914/* OLPC's microphone port is DC coupled for use with external sensors,
1915 * therefore we use a 50% mic bias in order to center the input signal with
1916 * the DC input range of the codec. */
1917#define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50
1918
1930static struct hda_channel_mode cxt5066_modes[1] = { 1919static struct hda_channel_mode cxt5066_modes[1] = {
1931 { 2, NULL }, 1920 { 2, NULL },
1932}; 1921};
@@ -1980,9 +1969,10 @@ static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1980/* toggle input of built-in and mic jack appropriately */ 1969/* toggle input of built-in and mic jack appropriately */
1981static void cxt5066_automic(struct hda_codec *codec) 1970static void cxt5066_automic(struct hda_codec *codec)
1982{ 1971{
1983 static struct hda_verb ext_mic_present[] = { 1972 struct conexant_spec *spec = codec->spec;
1973 struct hda_verb ext_mic_present[] = {
1984 /* enable external mic, port B */ 1974 /* enable external mic, port B */
1985 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1975 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias},
1986 1976
1987 /* switch to external mic input */ 1977 /* switch to external mic input */
1988 {0x17, AC_VERB_SET_CONNECT_SEL, 0}, 1978 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
@@ -2004,8 +1994,47 @@ static void cxt5066_automic(struct hda_codec *codec)
2004 }; 1994 };
2005 unsigned int present; 1995 unsigned int present;
2006 1996
2007 present = snd_hda_codec_read(codec, 0x1a, 0, 1997 present = snd_hda_jack_detect(codec, 0x1a);
2008 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1998 if (present) {
1999 snd_printdd("CXT5066: external microphone detected\n");
2000 snd_hda_sequence_write(codec, ext_mic_present);
2001 } else {
2002 snd_printdd("CXT5066: external microphone absent\n");
2003 snd_hda_sequence_write(codec, ext_mic_absent);
2004 }
2005}
2006
2007/* toggle input of built-in digital mic and mic jack appropriately */
2008static void cxt5066_vostro_automic(struct hda_codec *codec)
2009{
2010 struct conexant_spec *spec = codec->spec;
2011 unsigned int present;
2012
2013 struct hda_verb ext_mic_present[] = {
2014 /* enable external mic, port B */
2015 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias},
2016
2017 /* switch to external mic input */
2018 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
2019 {0x14, AC_VERB_SET_CONNECT_SEL, 0},
2020
2021 /* disable internal digital mic */
2022 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2023 {}
2024 };
2025 static struct hda_verb ext_mic_absent[] = {
2026 /* enable internal mic, port C */
2027 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2028
2029 /* switch to internal mic input */
2030 {0x14, AC_VERB_SET_CONNECT_SEL, 2},
2031
2032 /* disable external mic, port B */
2033 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2034 {}
2035 };
2036
2037 present = snd_hda_jack_detect(codec, 0x1a);
2009 if (present) { 2038 if (present) {
2010 snd_printdd("CXT5066: external microphone detected\n"); 2039 snd_printdd("CXT5066: external microphone detected\n");
2011 snd_hda_sequence_write(codec, ext_mic_present); 2040 snd_hda_sequence_write(codec, ext_mic_present);
@@ -2022,12 +2051,10 @@ static void cxt5066_hp_automute(struct hda_codec *codec)
2022 unsigned int portA, portD; 2051 unsigned int portA, portD;
2023 2052
2024 /* Port A */ 2053 /* Port A */
2025 portA = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0) 2054 portA = snd_hda_jack_detect(codec, 0x19);
2026 & AC_PINSENSE_PRESENCE;
2027 2055
2028 /* Port D */ 2056 /* Port D */
2029 portD = (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) 2057 portD = snd_hda_jack_detect(codec, 0x1c);
2030 & AC_PINSENSE_PRESENCE) << 1;
2031 2058
2032 spec->hp_present = !!(portA | portD); 2059 spec->hp_present = !!(portA | portD);
2033 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", 2060 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n",
@@ -2049,6 +2076,20 @@ static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
2049 } 2076 }
2050} 2077}
2051 2078
2079/* unsolicited event for jack sensing */
2080static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res)
2081{
2082 snd_printdd("CXT5066_vostro: unsol event %x (%x)\n", res, res >> 26);
2083 switch (res >> 26) {
2084 case CONEXANT_HP_EVENT:
2085 cxt5066_hp_automute(codec);
2086 break;
2087 case CONEXANT_MIC_EVENT:
2088 cxt5066_vostro_automic(codec);
2089 break;
2090 }
2091}
2092
2052static const struct hda_input_mux cxt5066_analog_mic_boost = { 2093static const struct hda_input_mux cxt5066_analog_mic_boost = {
2053 .num_items = 5, 2094 .num_items = 5,
2054 .items = { 2095 .items = {
@@ -2071,9 +2112,12 @@ static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
2071{ 2112{
2072 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2113 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2073 int val; 2114 int val;
2115 hda_nid_t nid = kcontrol->private_value & 0xff;
2116 int inout = (kcontrol->private_value & 0x100) ?
2117 AC_AMP_GET_INPUT : AC_AMP_GET_OUTPUT;
2074 2118
2075 val = snd_hda_codec_read(codec, 0x17, 0, 2119 val = snd_hda_codec_read(codec, nid, 0,
2076 AC_VERB_GET_AMP_GAIN_MUTE, AC_AMP_GET_OUTPUT); 2120 AC_VERB_GET_AMP_GAIN_MUTE, inout);
2077 2121
2078 ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN; 2122 ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN;
2079 return 0; 2123 return 0;
@@ -2085,6 +2129,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
2085 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2129 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2086 const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; 2130 const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
2087 unsigned int idx; 2131 unsigned int idx;
2132 hda_nid_t nid = kcontrol->private_value & 0xff;
2133 int inout = (kcontrol->private_value & 0x100) ?
2134 AC_AMP_SET_INPUT : AC_AMP_SET_OUTPUT;
2088 2135
2089 if (!imux->num_items) 2136 if (!imux->num_items)
2090 return 0; 2137 return 0;
@@ -2092,9 +2139,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
2092 if (idx >= imux->num_items) 2139 if (idx >= imux->num_items)
2093 idx = imux->num_items - 1; 2140 idx = imux->num_items - 1;
2094 2141
2095 snd_hda_codec_write_cache(codec, 0x17, 0, 2142 snd_hda_codec_write_cache(codec, nid, 0,
2096 AC_VERB_SET_AMP_GAIN_MUTE, 2143 AC_VERB_SET_AMP_GAIN_MUTE,
2097 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | 2144 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | inout |
2098 imux->items[idx].index); 2145 imux->items[idx].index);
2099 2146
2100 return 1; 2147 return 1;
@@ -2163,10 +2210,11 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
2163 2210
2164 { 2211 {
2165 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2212 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2166 .name = "Analog Mic Boost Capture Enum", 2213 .name = "Ext Mic Boost Capture Enum",
2167 .info = cxt5066_mic_boost_mux_enum_info, 2214 .info = cxt5066_mic_boost_mux_enum_info,
2168 .get = cxt5066_mic_boost_mux_enum_get, 2215 .get = cxt5066_mic_boost_mux_enum_get,
2169 .put = cxt5066_mic_boost_mux_enum_put, 2216 .put = cxt5066_mic_boost_mux_enum_put,
2217 .private_value = 0x17,
2170 }, 2218 },
2171 2219
2172 HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), 2220 HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
@@ -2174,6 +2222,19 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
2174 {} 2222 {}
2175}; 2223};
2176 2224
2225static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
2226 {
2227 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2228 .name = "Int Mic Boost Capture Enum",
2229 .info = cxt5066_mic_boost_mux_enum_info,
2230 .get = cxt5066_mic_boost_mux_enum_get,
2231 .put = cxt5066_mic_boost_mux_enum_put,
2232 .private_value = 0x23 | 0x100,
2233 },
2234 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
2235 {}
2236};
2237
2177static struct hda_verb cxt5066_init_verbs[] = { 2238static struct hda_verb cxt5066_init_verbs[] = {
2178 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ 2239 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
2179 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ 2240 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
@@ -2235,7 +2296,7 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = {
2235 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2296 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2236 2297
2237 /* Port B: external microphone */ 2298 /* Port B: external microphone */
2238 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2299 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, CXT5066_OLPC_EXT_MIC_BIAS},
2239 2300
2240 /* Port C: internal microphone */ 2301 /* Port C: internal microphone */
2241 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2302 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -2290,6 +2351,67 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = {
2290 { } /* end */ 2351 { } /* end */
2291}; 2352};
2292 2353
2354static struct hda_verb cxt5066_init_verbs_vostro[] = {
2355 /* Port A: headphones */
2356 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2357 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2358
2359 /* Port B: external microphone */
2360 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2361
2362 /* Port C: unused */
2363 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2364
2365 /* Port D: unused */
2366 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2367
2368 /* Port E: unused, but has primary EAPD */
2369 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2370 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2371
2372 /* Port F: unused */
2373 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2374
2375 /* Port G: internal speakers */
2376 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2377 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2378
2379 /* DAC1 */
2380 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2381
2382 /* DAC2: unused */
2383 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2384
2385 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2386 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2387 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2388 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2389 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2390 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2391 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2392 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2393 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2394 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2395 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2396 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2397
2398 /* Digital microphone port */
2399 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2400
2401 /* Audio input selectors */
2402 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2403 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2404
2405 /* Disable SPDIF */
2406 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2407 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2408
2409 /* enable unsolicited events for Port A and B */
2410 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2411 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2412 { } /* end */
2413};
2414
2293static struct hda_verb cxt5066_init_verbs_portd_lo[] = { 2415static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2294 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2416 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2295 { } /* end */ 2417 { } /* end */
@@ -2298,11 +2420,16 @@ static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2298/* initialize jack-sensing, too */ 2420/* initialize jack-sensing, too */
2299static int cxt5066_init(struct hda_codec *codec) 2421static int cxt5066_init(struct hda_codec *codec)
2300{ 2422{
2423 struct conexant_spec *spec = codec->spec;
2424
2301 snd_printdd("CXT5066: init\n"); 2425 snd_printdd("CXT5066: init\n");
2302 conexant_init(codec); 2426 conexant_init(codec);
2303 if (codec->patch_ops.unsol_event) { 2427 if (codec->patch_ops.unsol_event) {
2304 cxt5066_hp_automute(codec); 2428 cxt5066_hp_automute(codec);
2305 cxt5066_automic(codec); 2429 if (spec->dell_vostro)
2430 cxt5066_vostro_automic(codec);
2431 else
2432 cxt5066_automic(codec);
2306 } 2433 }
2307 return 0; 2434 return 0;
2308} 2435}
@@ -2311,6 +2438,7 @@ enum {
2311 CXT5066_LAPTOP, /* Laptops w/ EAPD support */ 2438 CXT5066_LAPTOP, /* Laptops w/ EAPD support */
2312 CXT5066_DELL_LAPTOP, /* Dell Laptop */ 2439 CXT5066_DELL_LAPTOP, /* Dell Laptop */
2313 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ 2440 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */
2441 CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */
2314 CXT5066_MODELS 2442 CXT5066_MODELS
2315}; 2443};
2316 2444
@@ -2318,6 +2446,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
2318 [CXT5066_LAPTOP] = "laptop", 2446 [CXT5066_LAPTOP] = "laptop",
2319 [CXT5066_DELL_LAPTOP] = "dell-laptop", 2447 [CXT5066_DELL_LAPTOP] = "dell-laptop",
2320 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", 2448 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5",
2449 [CXT5066_DELL_VOSTO] = "dell-vostro"
2321}; 2450};
2322 2451
2323static struct snd_pci_quirk cxt5066_cfg_tbl[] = { 2452static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
@@ -2325,6 +2454,8 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2325 CXT5066_LAPTOP), 2454 CXT5066_LAPTOP),
2326 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", 2455 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
2327 CXT5066_DELL_LAPTOP), 2456 CXT5066_DELL_LAPTOP),
2457 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
2458 SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
2328 {} 2459 {}
2329}; 2460};
2330 2461
@@ -2352,6 +2483,7 @@ static int patch_cxt5066(struct hda_codec *codec)
2352 spec->input_mux = &cxt5066_capture_source; 2483 spec->input_mux = &cxt5066_capture_source;
2353 2484
2354 spec->port_d_mode = PIN_HP; 2485 spec->port_d_mode = PIN_HP;
2486 spec->ext_mic_bias = PIN_VREF80;
2355 2487
2356 spec->num_init_verbs = 1; 2488 spec->num_init_verbs = 1;
2357 spec->init_verbs[0] = cxt5066_init_verbs; 2489 spec->init_verbs[0] = cxt5066_init_verbs;
@@ -2383,6 +2515,23 @@ static int patch_cxt5066(struct hda_codec *codec)
2383 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; 2515 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
2384 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 2516 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2385 spec->port_d_mode = 0; 2517 spec->port_d_mode = 0;
2518 spec->ext_mic_bias = CXT5066_OLPC_EXT_MIC_BIAS;
2519
2520 /* no S/PDIF out */
2521 spec->multiout.dig_out_nid = 0;
2522
2523 /* input source automatically selected */
2524 spec->input_mux = NULL;
2525 break;
2526 case CXT5066_DELL_VOSTO:
2527 codec->patch_ops.unsol_event = cxt5066_vostro_event;
2528 spec->init_verbs[0] = cxt5066_init_verbs_vostro;
2529 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
2530 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2531 spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers;
2532 spec->port_d_mode = 0;
2533 spec->dell_vostro = 1;
2534 snd_hda_attach_beep_device(codec, 0x13);
2386 2535
2387 /* no S/PDIF out */ 2536 /* no S/PDIF out */
2388 spec->multiout.dig_out_nid = 0; 2537 spec->multiout.dig_out_nid = 0;
@@ -2407,6 +2556,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
2407 .patch = patch_cxt5051 }, 2556 .patch = patch_cxt5051 },
2408 { .id = 0x14f15066, .name = "CX20582 (Pebble)", 2557 { .id = 0x14f15066, .name = "CX20582 (Pebble)",
2409 .patch = patch_cxt5066 }, 2558 .patch = patch_cxt5066 },
2559 { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
2560 .patch = patch_cxt5066 },
2410 {} /* terminator */ 2561 {} /* terminator */
2411}; 2562};
2412 2563
@@ -2414,6 +2565,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15045");
2414MODULE_ALIAS("snd-hda-codec-id:14f15047"); 2565MODULE_ALIAS("snd-hda-codec-id:14f15047");
2415MODULE_ALIAS("snd-hda-codec-id:14f15051"); 2566MODULE_ALIAS("snd-hda-codec-id:14f15051");
2416MODULE_ALIAS("snd-hda-codec-id:14f15066"); 2567MODULE_ALIAS("snd-hda-codec-id:14f15066");
2568MODULE_ALIAS("snd-hda-codec-id:14f15067");
2417 2569
2418MODULE_LICENSE("GPL"); 2570MODULE_LICENSE("GPL");
2419MODULE_DESCRIPTION("Conexant HD-audio codec"); 2571MODULE_DESCRIPTION("Conexant HD-audio codec");