diff options
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 134 |
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 */ | ||
2013 | static 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 */ |
2013 | static void cxt5066_hp_automute(struct hda_codec *codec) | 2053 | static 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 */ | ||
2085 | static 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 | |||
2044 | static const struct hda_input_mux cxt5066_analog_mic_boost = { | 2098 | static 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 | ||
2339 | static 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 | |||
2285 | static struct hda_verb cxt5066_init_verbs_portd_lo[] = { | 2400 | static 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 | ||
2315 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | 2432 | static 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"); | |||
2409 | MODULE_ALIAS("snd-hda-codec-id:14f15047"); | 2542 | MODULE_ALIAS("snd-hda-codec-id:14f15047"); |
2410 | MODULE_ALIAS("snd-hda-codec-id:14f15051"); | 2543 | MODULE_ALIAS("snd-hda-codec-id:14f15051"); |
2411 | MODULE_ALIAS("snd-hda-codec-id:14f15066"); | 2544 | MODULE_ALIAS("snd-hda-codec-id:14f15066"); |
2545 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); | ||
2412 | 2546 | ||
2413 | MODULE_LICENSE("GPL"); | 2547 | MODULE_LICENSE("GPL"); |
2414 | MODULE_DESCRIPTION("Conexant HD-audio codec"); | 2548 | MODULE_DESCRIPTION("Conexant HD-audio codec"); |