aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_conexant.c
diff options
context:
space:
mode:
authorEinar Rünkaru <einarry@smail.ee>2009-11-23 15:23:49 -0500
committerTakashi Iwai <tiwai@suse.de>2009-11-24 03:01:48 -0500
commit95a618bdac29c7b0f1a516aec9fc37626dec1af9 (patch)
tree6a73f53909bac4f16d3db8c3b6ed3b62a4bb06f9 /sound/pci/hda/patch_conexant.c
parent83dd7408b59c1945069199d712df8c7c64a76e1f (diff)
ALSA: hda - Make Dell Vostro 1015n mic and speaker switching work
Dell Vostro 1015n uses Conexant CX20583-10Z (0x14f1:5067). Patch is based on "olpc-xo-1_5" branch. Dell uses digital mic. Signed-off-by: Einar Rünkaru <einarry@smail.ee> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r--sound/pci/hda/patch_conexant.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 0b097fa5421f..36dd5a6bf874 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -2009,6 +2009,46 @@ static void cxt5066_automic(struct hda_codec *codec)
2009 } 2009 }
2010} 2010}
2011 2011
2012/* toggle input of built-in digital mic and mic jack appropriately */
2013static void cxt5066_vostro_automic(struct hda_codec *codec)
2014{
2015 struct conexant_spec *spec = codec->spec;
2016 unsigned int present;
2017
2018 struct hda_verb ext_mic_present[] = {
2019 /* enable external mic, port B */
2020 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias},
2021
2022 /* switch to external mic input */
2023 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
2024 {0x14, AC_VERB_SET_CONNECT_SEL, 0},
2025
2026 /* disable internal digital mic */
2027 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2028 {}
2029 };
2030 static struct hda_verb ext_mic_absent[] = {
2031 /* enable internal mic, port C */
2032 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2033
2034 /* switch to internal mic input */
2035 {0x14, AC_VERB_SET_CONNECT_SEL, 2},
2036
2037 /* disable external mic, port B */
2038 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2039 {}
2040 };
2041
2042 present = snd_hda_jack_detect(codec, 0x1a);
2043 if (present) {
2044 snd_printdd("CXT5066: external microphone detected\n");
2045 snd_hda_sequence_write(codec, ext_mic_present);
2046 } else {
2047 snd_printdd("CXT5066: external microphone absent\n");
2048 snd_hda_sequence_write(codec, ext_mic_absent);
2049 }
2050}
2051
2012/* mute internal speaker if HP is plugged */ 2052/* mute internal speaker if HP is plugged */
2013static void cxt5066_hp_automute(struct hda_codec *codec) 2053static void cxt5066_hp_automute(struct hda_codec *codec)
2014{ 2054{
@@ -2041,6 +2081,20 @@ static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
2041 } 2081 }
2042} 2082}
2043 2083
2084/* unsolicited event for jack sensing */
2085static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res)
2086{
2087 snd_printdd("CXT5066_vostro: unsol event %x (%x)\n", res, res >> 26);
2088 switch (res >> 26) {
2089 case CONEXANT_HP_EVENT:
2090 cxt5066_hp_automute(codec);
2091 break;
2092 case CONEXANT_MIC_EVENT:
2093 cxt5066_vostro_automic(codec);
2094 break;
2095 }
2096}
2097
2044static const struct hda_input_mux cxt5066_analog_mic_boost = { 2098static const struct hda_input_mux cxt5066_analog_mic_boost = {
2045 .num_items = 5, 2099 .num_items = 5,
2046 .items = { 2100 .items = {
@@ -2282,6 +2336,67 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = {
2282 { } /* end */ 2336 { } /* end */
2283}; 2337};
2284 2338
2339static struct hda_verb cxt5066_init_verbs_vostro[] = {
2340 /* Port A: headphones */
2341 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2342 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2343
2344 /* Port B: external microphone */
2345 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2346
2347 /* Port C: unused */
2348 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2349
2350 /* Port D: unused */
2351 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2352
2353 /* Port E: unused, but has primary EAPD */
2354 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2355 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2356
2357 /* Port F: unused */
2358 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2359
2360 /* Port G: internal speakers */
2361 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2362 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2363
2364 /* DAC1 */
2365 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2366
2367 /* DAC2: unused */
2368 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2369
2370 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2371 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2372 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2373 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2374 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2375 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2376 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2377 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2378 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2379 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2380 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2381 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2382
2383 /* Digital microphone port */
2384 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2385
2386 /* Audio input selectors */
2387 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2388 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2389
2390 /* Disable SPDIF */
2391 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2392 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2393
2394 /* enable unsolicited events for Port A and B */
2395 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2396 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2397 { } /* end */
2398};
2399
2285static struct hda_verb cxt5066_init_verbs_portd_lo[] = { 2400static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2286 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2401 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2287 { } /* end */ 2402 { } /* end */
@@ -2303,6 +2418,7 @@ enum {
2303 CXT5066_LAPTOP, /* Laptops w/ EAPD support */ 2418 CXT5066_LAPTOP, /* Laptops w/ EAPD support */
2304 CXT5066_DELL_LAPTOP, /* Dell Laptop */ 2419 CXT5066_DELL_LAPTOP, /* Dell Laptop */
2305 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ 2420 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */
2421 CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */
2306 CXT5066_MODELS 2422 CXT5066_MODELS
2307}; 2423};
2308 2424
@@ -2310,6 +2426,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
2310 [CXT5066_LAPTOP] = "laptop", 2426 [CXT5066_LAPTOP] = "laptop",
2311 [CXT5066_DELL_LAPTOP] = "dell-laptop", 2427 [CXT5066_DELL_LAPTOP] = "dell-laptop",
2312 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", 2428 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5",
2429 [CXT5066_DELL_VOSTO] = "dell-vostro"
2313}; 2430};
2314 2431
2315static struct snd_pci_quirk cxt5066_cfg_tbl[] = { 2432static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
@@ -2318,6 +2435,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2318 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", 2435 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
2319 CXT5066_DELL_LAPTOP), 2436 CXT5066_DELL_LAPTOP),
2320 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), 2437 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
2438 SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
2321 {} 2439 {}
2322}; 2440};
2323 2441
@@ -2385,6 +2503,19 @@ static int patch_cxt5066(struct hda_codec *codec)
2385 /* input source automatically selected */ 2503 /* input source automatically selected */
2386 spec->input_mux = NULL; 2504 spec->input_mux = NULL;
2387 break; 2505 break;
2506 case CXT5066_DELL_VOSTO:
2507 codec->patch_ops.unsol_event = cxt5066_vostro_event;
2508 spec->init_verbs[0] = cxt5066_init_verbs_vostro;
2509 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
2510 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2511 spec->port_d_mode = 0;
2512
2513 /* no S/PDIF out */
2514 spec->multiout.dig_out_nid = 0;
2515
2516 /* input source automatically selected */
2517 spec->input_mux = NULL;
2518 break;
2388 } 2519 }
2389 2520
2390 return 0; 2521 return 0;
@@ -2402,6 +2533,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
2402 .patch = patch_cxt5051 }, 2533 .patch = patch_cxt5051 },
2403 { .id = 0x14f15066, .name = "CX20582 (Pebble)", 2534 { .id = 0x14f15066, .name = "CX20582 (Pebble)",
2404 .patch = patch_cxt5066 }, 2535 .patch = patch_cxt5066 },
2536 { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
2537 .patch = patch_cxt5066 },
2405 {} /* terminator */ 2538 {} /* terminator */
2406}; 2539};
2407 2540
@@ -2409,6 +2542,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15045");
2409MODULE_ALIAS("snd-hda-codec-id:14f15047"); 2542MODULE_ALIAS("snd-hda-codec-id:14f15047");
2410MODULE_ALIAS("snd-hda-codec-id:14f15051"); 2543MODULE_ALIAS("snd-hda-codec-id:14f15051");
2411MODULE_ALIAS("snd-hda-codec-id:14f15066"); 2544MODULE_ALIAS("snd-hda-codec-id:14f15066");
2545MODULE_ALIAS("snd-hda-codec-id:14f15067");
2412 2546
2413MODULE_LICENSE("GPL"); 2547MODULE_LICENSE("GPL");
2414MODULE_DESCRIPTION("Conexant HD-audio codec"); 2548MODULE_DESCRIPTION("Conexant HD-audio codec");