aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_conexant.c
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2010-01-28 16:38:25 -0500
committerGrant Likely <grant.likely@secretlab.ca>2010-01-28 16:38:25 -0500
commit0ada0a73120c28cc432bcdbac061781465c2f48f (patch)
treed17cadd4ea47e25d9e48e7d409a39c84268fbd27 /sound/pci/hda/patch_conexant.c
parent6016a363f6b56b46b24655bcfc0499b715851cf3 (diff)
parent92dcffb916d309aa01778bf8963a6932e4014d07 (diff)
Merge commit 'v2.6.33-rc5' into secretlab/test-devicetree
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r--sound/pci/hda/patch_conexant.c232
1 files changed, 187 insertions, 45 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 905859d4f4df..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
@@ -111,6 +112,7 @@ struct conexant_spec {
111 unsigned int dell_automute; 112 unsigned int dell_automute;
112 unsigned int port_d_mode; 113 unsigned int port_d_mode;
113 unsigned char ext_mic_bias; 114 unsigned char ext_mic_bias;
115 unsigned int dell_vostro;
114}; 116};
115 117
116static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, 118static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@@ -397,9 +399,7 @@ static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
397 for (i = 0; i < spec->jacks.used; i++) { 399 for (i = 0; i < spec->jacks.used; i++) {
398 if (jacks->nid == nid) { 400 if (jacks->nid == nid) {
399 unsigned int present; 401 unsigned int present;
400 present = snd_hda_codec_read(codec, nid, 0, 402 present = snd_hda_jack_detect(codec, nid);
401 AC_VERB_GET_PIN_SENSE, 0) &
402 AC_PINSENSE_PRESENCE;
403 403
404 present = (present) ? jacks->type : 0 ; 404 present = (present) ? jacks->type : 0 ;
405 405
@@ -478,6 +478,7 @@ static void conexant_free(struct hda_codec *codec)
478 snd_array_free(&spec->jacks); 478 snd_array_free(&spec->jacks);
479 } 479 }
480#endif 480#endif
481 snd_hda_detach_beep_device(codec);
481 kfree(codec->spec); 482 kfree(codec->spec);
482} 483}
483 484
@@ -750,8 +751,7 @@ static void cxt5045_hp_automic(struct hda_codec *codec)
750 }; 751 };
751 unsigned int present; 752 unsigned int present;
752 753
753 present = snd_hda_codec_read(codec, 0x12, 0, 754 present = snd_hda_jack_detect(codec, 0x12);
754 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
755 if (present) 755 if (present)
756 snd_hda_sequence_write(codec, mic_jack_on); 756 snd_hda_sequence_write(codec, mic_jack_on);
757 else 757 else
@@ -765,8 +765,7 @@ static void cxt5045_hp_automute(struct hda_codec *codec)
765 struct conexant_spec *spec = codec->spec; 765 struct conexant_spec *spec = codec->spec;
766 unsigned int bits; 766 unsigned int bits;
767 767
768 spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, 768 spec->hp_present = snd_hda_jack_detect(codec, 0x11);
769 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
770 769
771 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 770 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
772 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, 771 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
@@ -1175,9 +1174,10 @@ static int patch_cxt5045(struct hda_codec *codec)
1175 1174
1176 switch (codec->subsystem_id >> 16) { 1175 switch (codec->subsystem_id >> 16) {
1177 case 0x103c: 1176 case 0x103c:
1178 /* HP laptop has a really bad sound over 0dB on NID 0x17. 1177 case 0x1734:
1179 * Fix max PCM level to 0 dB 1178 /* HP & Fujitsu-Siemens laptops have really bad sound over 0dB
1180 * (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)
1181 */ 1181 */
1182 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, 1182 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
1183 (0x14 << AC_AMPCAP_OFFSET_SHIFT) | 1183 (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
@@ -1243,8 +1243,7 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
1243 struct conexant_spec *spec = codec->spec; 1243 struct conexant_spec *spec = codec->spec;
1244 unsigned int bits; 1244 unsigned int bits;
1245 1245
1246 spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, 1246 spec->hp_present = snd_hda_jack_detect(codec, 0x13);
1247 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1248 1247
1249 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 1248 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
1250 /* See the note in cxt5047_hp_master_sw_put */ 1249 /* See the note in cxt5047_hp_master_sw_put */
@@ -1267,8 +1266,7 @@ static void cxt5047_hp_automic(struct hda_codec *codec)
1267 }; 1266 };
1268 unsigned int present; 1267 unsigned int present;
1269 1268
1270 present = snd_hda_codec_read(codec, 0x15, 0, 1269 present = snd_hda_jack_detect(codec, 0x15);
1271 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1272 if (present) 1270 if (present)
1273 snd_hda_sequence_write(codec, mic_jack_on); 1271 snd_hda_sequence_write(codec, mic_jack_on);
1274 else 1272 else
@@ -1415,16 +1413,7 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = {
1415 .get = conexant_mux_enum_get, 1413 .get = conexant_mux_enum_get,
1416 .put = conexant_mux_enum_put, 1414 .put = conexant_mux_enum_put,
1417 }, 1415 },
1418 HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT), 1416 HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
1419 HDA_CODEC_MUTE("Input-1 Switch", 0x1a, 0x0, HDA_INPUT),
1420 HDA_CODEC_VOLUME("Input-2 Volume", 0x1a, 0x1, HDA_INPUT),
1421 HDA_CODEC_MUTE("Input-2 Switch", 0x1a, 0x1, HDA_INPUT),
1422 HDA_CODEC_VOLUME("Input-3 Volume", 0x1a, 0x2, HDA_INPUT),
1423 HDA_CODEC_MUTE("Input-3 Switch", 0x1a, 0x2, HDA_INPUT),
1424 HDA_CODEC_VOLUME("Input-4 Volume", 0x1a, 0x3, HDA_INPUT),
1425 HDA_CODEC_MUTE("Input-4 Switch", 0x1a, 0x3, HDA_INPUT),
1426 HDA_CODEC_VOLUME("Input-5 Volume", 0x1a, 0x4, HDA_INPUT),
1427 HDA_CODEC_MUTE("Input-5 Switch", 0x1a, 0x4, HDA_INPUT),
1428 1417
1429 { } /* end */ 1418 { } /* end */
1430}; 1419};
@@ -1621,9 +1610,7 @@ static void cxt5051_portb_automic(struct hda_codec *codec)
1621 1610
1622 if (spec->no_auto_mic) 1611 if (spec->no_auto_mic)
1623 return; 1612 return;
1624 present = snd_hda_codec_read(codec, 0x17, 0, 1613 present = snd_hda_jack_detect(codec, 0x17);
1625 AC_VERB_GET_PIN_SENSE, 0) &
1626 AC_PINSENSE_PRESENCE;
1627 snd_hda_codec_write(codec, 0x14, 0, 1614 snd_hda_codec_write(codec, 0x14, 0,
1628 AC_VERB_SET_CONNECT_SEL, 1615 AC_VERB_SET_CONNECT_SEL,
1629 present ? 0x01 : 0x00); 1616 present ? 0x01 : 0x00);
@@ -1638,9 +1625,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
1638 1625
1639 if (spec->no_auto_mic) 1626 if (spec->no_auto_mic)
1640 return; 1627 return;
1641 present = snd_hda_codec_read(codec, 0x18, 0, 1628 present = snd_hda_jack_detect(codec, 0x18);
1642 AC_VERB_GET_PIN_SENSE, 0) &
1643 AC_PINSENSE_PRESENCE;
1644 if (present) 1629 if (present)
1645 spec->cur_adc_idx = 1; 1630 spec->cur_adc_idx = 1;
1646 else 1631 else
@@ -1661,9 +1646,7 @@ static void cxt5051_hp_automute(struct hda_codec *codec)
1661{ 1646{
1662 struct conexant_spec *spec = codec->spec; 1647 struct conexant_spec *spec = codec->spec;
1663 1648
1664 spec->hp_present = snd_hda_codec_read(codec, 0x16, 0, 1649 spec->hp_present = snd_hda_jack_detect(codec, 0x16);
1665 AC_VERB_GET_PIN_SENSE, 0) &
1666 AC_PINSENSE_PRESENCE;
1667 cxt5051_update_speaker(codec); 1650 cxt5051_update_speaker(codec);
1668} 1651}
1669 1652
@@ -2011,8 +1994,47 @@ static void cxt5066_automic(struct hda_codec *codec)
2011 }; 1994 };
2012 unsigned int present; 1995 unsigned int present;
2013 1996
2014 present = snd_hda_codec_read(codec, 0x1a, 0, 1997 present = snd_hda_jack_detect(codec, 0x1a);
2015 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);
2016 if (present) { 2038 if (present) {
2017 snd_printdd("CXT5066: external microphone detected\n"); 2039 snd_printdd("CXT5066: external microphone detected\n");
2018 snd_hda_sequence_write(codec, ext_mic_present); 2040 snd_hda_sequence_write(codec, ext_mic_present);
@@ -2029,12 +2051,10 @@ static void cxt5066_hp_automute(struct hda_codec *codec)
2029 unsigned int portA, portD; 2051 unsigned int portA, portD;
2030 2052
2031 /* Port A */ 2053 /* Port A */
2032 portA = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0) 2054 portA = snd_hda_jack_detect(codec, 0x19);
2033 & AC_PINSENSE_PRESENCE;
2034 2055
2035 /* Port D */ 2056 /* Port D */
2036 portD = (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) 2057 portD = snd_hda_jack_detect(codec, 0x1c);
2037 & AC_PINSENSE_PRESENCE) << 1;
2038 2058
2039 spec->hp_present = !!(portA | portD); 2059 spec->hp_present = !!(portA | portD);
2040 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",
@@ -2056,6 +2076,20 @@ static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
2056 } 2076 }
2057} 2077}
2058 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
2059static const struct hda_input_mux cxt5066_analog_mic_boost = { 2093static const struct hda_input_mux cxt5066_analog_mic_boost = {
2060 .num_items = 5, 2094 .num_items = 5,
2061 .items = { 2095 .items = {
@@ -2078,9 +2112,12 @@ static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
2078{ 2112{
2079 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2113 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2080 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;
2081 2118
2082 val = snd_hda_codec_read(codec, 0x17, 0, 2119 val = snd_hda_codec_read(codec, nid, 0,
2083 AC_VERB_GET_AMP_GAIN_MUTE, AC_AMP_GET_OUTPUT); 2120 AC_VERB_GET_AMP_GAIN_MUTE, inout);
2084 2121
2085 ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN; 2122 ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN;
2086 return 0; 2123 return 0;
@@ -2092,6 +2129,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
2092 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2129 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2093 const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; 2130 const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
2094 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;
2095 2135
2096 if (!imux->num_items) 2136 if (!imux->num_items)
2097 return 0; 2137 return 0;
@@ -2099,9 +2139,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
2099 if (idx >= imux->num_items) 2139 if (idx >= imux->num_items)
2100 idx = imux->num_items - 1; 2140 idx = imux->num_items - 1;
2101 2141
2102 snd_hda_codec_write_cache(codec, 0x17, 0, 2142 snd_hda_codec_write_cache(codec, nid, 0,
2103 AC_VERB_SET_AMP_GAIN_MUTE, 2143 AC_VERB_SET_AMP_GAIN_MUTE,
2104 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | 2144 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | inout |
2105 imux->items[idx].index); 2145 imux->items[idx].index);
2106 2146
2107 return 1; 2147 return 1;
@@ -2170,10 +2210,11 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
2170 2210
2171 { 2211 {
2172 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2212 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2173 .name = "Analog Mic Boost Capture Enum", 2213 .name = "Ext Mic Boost Capture Enum",
2174 .info = cxt5066_mic_boost_mux_enum_info, 2214 .info = cxt5066_mic_boost_mux_enum_info,
2175 .get = cxt5066_mic_boost_mux_enum_get, 2215 .get = cxt5066_mic_boost_mux_enum_get,
2176 .put = cxt5066_mic_boost_mux_enum_put, 2216 .put = cxt5066_mic_boost_mux_enum_put,
2217 .private_value = 0x17,
2177 }, 2218 },
2178 2219
2179 HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), 2220 HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
@@ -2181,6 +2222,19 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
2181 {} 2222 {}
2182}; 2223};
2183 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
2184static struct hda_verb cxt5066_init_verbs[] = { 2238static struct hda_verb cxt5066_init_verbs[] = {
2185 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ 2239 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
2186 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ 2240 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
@@ -2297,6 +2351,67 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = {
2297 { } /* end */ 2351 { } /* end */
2298}; 2352};
2299 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
2300static struct hda_verb cxt5066_init_verbs_portd_lo[] = { 2415static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2301 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2416 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2302 { } /* end */ 2417 { } /* end */
@@ -2305,11 +2420,16 @@ static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2305/* initialize jack-sensing, too */ 2420/* initialize jack-sensing, too */
2306static int cxt5066_init(struct hda_codec *codec) 2421static int cxt5066_init(struct hda_codec *codec)
2307{ 2422{
2423 struct conexant_spec *spec = codec->spec;
2424
2308 snd_printdd("CXT5066: init\n"); 2425 snd_printdd("CXT5066: init\n");
2309 conexant_init(codec); 2426 conexant_init(codec);
2310 if (codec->patch_ops.unsol_event) { 2427 if (codec->patch_ops.unsol_event) {
2311 cxt5066_hp_automute(codec); 2428 cxt5066_hp_automute(codec);
2312 cxt5066_automic(codec); 2429 if (spec->dell_vostro)
2430 cxt5066_vostro_automic(codec);
2431 else
2432 cxt5066_automic(codec);
2313 } 2433 }
2314 return 0; 2434 return 0;
2315} 2435}
@@ -2318,6 +2438,7 @@ enum {
2318 CXT5066_LAPTOP, /* Laptops w/ EAPD support */ 2438 CXT5066_LAPTOP, /* Laptops w/ EAPD support */
2319 CXT5066_DELL_LAPTOP, /* Dell Laptop */ 2439 CXT5066_DELL_LAPTOP, /* Dell Laptop */
2320 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 */
2321 CXT5066_MODELS 2442 CXT5066_MODELS
2322}; 2443};
2323 2444
@@ -2325,6 +2446,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
2325 [CXT5066_LAPTOP] = "laptop", 2446 [CXT5066_LAPTOP] = "laptop",
2326 [CXT5066_DELL_LAPTOP] = "dell-laptop", 2447 [CXT5066_DELL_LAPTOP] = "dell-laptop",
2327 [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"
2328}; 2450};
2329 2451
2330static struct snd_pci_quirk cxt5066_cfg_tbl[] = { 2452static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
@@ -2333,6 +2455,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2333 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", 2455 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
2334 CXT5066_DELL_LAPTOP), 2456 CXT5066_DELL_LAPTOP),
2335 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), 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),
2336 {} 2459 {}
2337}; 2460};
2338 2461
@@ -2400,6 +2523,22 @@ static int patch_cxt5066(struct hda_codec *codec)
2400 /* input source automatically selected */ 2523 /* input source automatically selected */
2401 spec->input_mux = NULL; 2524 spec->input_mux = NULL;
2402 break; 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);
2535
2536 /* no S/PDIF out */
2537 spec->multiout.dig_out_nid = 0;
2538
2539 /* input source automatically selected */
2540 spec->input_mux = NULL;
2541 break;
2403 } 2542 }
2404 2543
2405 return 0; 2544 return 0;
@@ -2417,6 +2556,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
2417 .patch = patch_cxt5051 }, 2556 .patch = patch_cxt5051 },
2418 { .id = 0x14f15066, .name = "CX20582 (Pebble)", 2557 { .id = 0x14f15066, .name = "CX20582 (Pebble)",
2419 .patch = patch_cxt5066 }, 2558 .patch = patch_cxt5066 },
2559 { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
2560 .patch = patch_cxt5066 },
2420 {} /* terminator */ 2561 {} /* terminator */
2421}; 2562};
2422 2563
@@ -2424,6 +2565,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15045");
2424MODULE_ALIAS("snd-hda-codec-id:14f15047"); 2565MODULE_ALIAS("snd-hda-codec-id:14f15047");
2425MODULE_ALIAS("snd-hda-codec-id:14f15051"); 2566MODULE_ALIAS("snd-hda-codec-id:14f15051");
2426MODULE_ALIAS("snd-hda-codec-id:14f15066"); 2567MODULE_ALIAS("snd-hda-codec-id:14f15066");
2568MODULE_ALIAS("snd-hda-codec-id:14f15067");
2427 2569
2428MODULE_LICENSE("GPL"); 2570MODULE_LICENSE("GPL");
2429MODULE_DESCRIPTION("Conexant HD-audio codec"); 2571MODULE_DESCRIPTION("Conexant HD-audio codec");