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.c189
1 files changed, 150 insertions, 39 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 905859d4f4df..a09c03c3f62b 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -397,9 +397,7 @@ static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
397 for (i = 0; i < spec->jacks.used; i++) { 397 for (i = 0; i < spec->jacks.used; i++) {
398 if (jacks->nid == nid) { 398 if (jacks->nid == nid) {
399 unsigned int present; 399 unsigned int present;
400 present = snd_hda_codec_read(codec, nid, 0, 400 present = snd_hda_jack_detect(codec, nid);
401 AC_VERB_GET_PIN_SENSE, 0) &
402 AC_PINSENSE_PRESENCE;
403 401
404 present = (present) ? jacks->type : 0 ; 402 present = (present) ? jacks->type : 0 ;
405 403
@@ -750,8 +748,7 @@ static void cxt5045_hp_automic(struct hda_codec *codec)
750 }; 748 };
751 unsigned int present; 749 unsigned int present;
752 750
753 present = snd_hda_codec_read(codec, 0x12, 0, 751 present = snd_hda_jack_detect(codec, 0x12);
754 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
755 if (present) 752 if (present)
756 snd_hda_sequence_write(codec, mic_jack_on); 753 snd_hda_sequence_write(codec, mic_jack_on);
757 else 754 else
@@ -765,8 +762,7 @@ static void cxt5045_hp_automute(struct hda_codec *codec)
765 struct conexant_spec *spec = codec->spec; 762 struct conexant_spec *spec = codec->spec;
766 unsigned int bits; 763 unsigned int bits;
767 764
768 spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, 765 spec->hp_present = snd_hda_jack_detect(codec, 0x11);
769 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
770 766
771 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 767 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
772 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, 768 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
@@ -1175,9 +1171,10 @@ static int patch_cxt5045(struct hda_codec *codec)
1175 1171
1176 switch (codec->subsystem_id >> 16) { 1172 switch (codec->subsystem_id >> 16) {
1177 case 0x103c: 1173 case 0x103c:
1178 /* HP laptop has a really bad sound over 0dB on NID 0x17. 1174 case 0x1734:
1179 * Fix max PCM level to 0 dB 1175 /* HP & Fujitsu-Siemens laptops have really bad sound over 0dB
1180 * (originall it has 0x2b steps with 0dB offset 0x14) 1176 * on NID 0x17. Fix max PCM level to 0 dB
1177 * (originally it has 0x2b steps with 0dB offset 0x14)
1181 */ 1178 */
1182 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, 1179 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
1183 (0x14 << AC_AMPCAP_OFFSET_SHIFT) | 1180 (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
@@ -1243,8 +1240,7 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
1243 struct conexant_spec *spec = codec->spec; 1240 struct conexant_spec *spec = codec->spec;
1244 unsigned int bits; 1241 unsigned int bits;
1245 1242
1246 spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, 1243 spec->hp_present = snd_hda_jack_detect(codec, 0x13);
1247 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1248 1244
1249 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 1245 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
1250 /* See the note in cxt5047_hp_master_sw_put */ 1246 /* See the note in cxt5047_hp_master_sw_put */
@@ -1267,8 +1263,7 @@ static void cxt5047_hp_automic(struct hda_codec *codec)
1267 }; 1263 };
1268 unsigned int present; 1264 unsigned int present;
1269 1265
1270 present = snd_hda_codec_read(codec, 0x15, 0, 1266 present = snd_hda_jack_detect(codec, 0x15);
1271 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1272 if (present) 1267 if (present)
1273 snd_hda_sequence_write(codec, mic_jack_on); 1268 snd_hda_sequence_write(codec, mic_jack_on);
1274 else 1269 else
@@ -1415,16 +1410,7 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = {
1415 .get = conexant_mux_enum_get, 1410 .get = conexant_mux_enum_get,
1416 .put = conexant_mux_enum_put, 1411 .put = conexant_mux_enum_put,
1417 }, 1412 },
1418 HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT), 1413 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 1414
1429 { } /* end */ 1415 { } /* end */
1430}; 1416};
@@ -1621,9 +1607,7 @@ static void cxt5051_portb_automic(struct hda_codec *codec)
1621 1607
1622 if (spec->no_auto_mic) 1608 if (spec->no_auto_mic)
1623 return; 1609 return;
1624 present = snd_hda_codec_read(codec, 0x17, 0, 1610 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, 1611 snd_hda_codec_write(codec, 0x14, 0,
1628 AC_VERB_SET_CONNECT_SEL, 1612 AC_VERB_SET_CONNECT_SEL,
1629 present ? 0x01 : 0x00); 1613 present ? 0x01 : 0x00);
@@ -1638,9 +1622,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
1638 1622
1639 if (spec->no_auto_mic) 1623 if (spec->no_auto_mic)
1640 return; 1624 return;
1641 present = snd_hda_codec_read(codec, 0x18, 0, 1625 present = snd_hda_jack_detect(codec, 0x18);
1642 AC_VERB_GET_PIN_SENSE, 0) &
1643 AC_PINSENSE_PRESENCE;
1644 if (present) 1626 if (present)
1645 spec->cur_adc_idx = 1; 1627 spec->cur_adc_idx = 1;
1646 else 1628 else
@@ -1661,9 +1643,7 @@ static void cxt5051_hp_automute(struct hda_codec *codec)
1661{ 1643{
1662 struct conexant_spec *spec = codec->spec; 1644 struct conexant_spec *spec = codec->spec;
1663 1645
1664 spec->hp_present = snd_hda_codec_read(codec, 0x16, 0, 1646 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); 1647 cxt5051_update_speaker(codec);
1668} 1648}
1669 1649
@@ -2011,8 +1991,47 @@ static void cxt5066_automic(struct hda_codec *codec)
2011 }; 1991 };
2012 unsigned int present; 1992 unsigned int present;
2013 1993
2014 present = snd_hda_codec_read(codec, 0x1a, 0, 1994 present = snd_hda_jack_detect(codec, 0x1a);
2015 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1995 if (present) {
1996 snd_printdd("CXT5066: external microphone detected\n");
1997 snd_hda_sequence_write(codec, ext_mic_present);
1998 } else {
1999 snd_printdd("CXT5066: external microphone absent\n");
2000 snd_hda_sequence_write(codec, ext_mic_absent);
2001 }
2002}
2003
2004/* toggle input of built-in digital mic and mic jack appropriately */
2005static void cxt5066_vostro_automic(struct hda_codec *codec)
2006{
2007 struct conexant_spec *spec = codec->spec;
2008 unsigned int present;
2009
2010 struct hda_verb ext_mic_present[] = {
2011 /* enable external mic, port B */
2012 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias},
2013
2014 /* switch to external mic input */
2015 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
2016 {0x14, AC_VERB_SET_CONNECT_SEL, 0},
2017
2018 /* disable internal digital mic */
2019 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2020 {}
2021 };
2022 static struct hda_verb ext_mic_absent[] = {
2023 /* enable internal mic, port C */
2024 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2025
2026 /* switch to internal mic input */
2027 {0x14, AC_VERB_SET_CONNECT_SEL, 2},
2028
2029 /* disable external mic, port B */
2030 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2031 {}
2032 };
2033
2034 present = snd_hda_jack_detect(codec, 0x1a);
2016 if (present) { 2035 if (present) {
2017 snd_printdd("CXT5066: external microphone detected\n"); 2036 snd_printdd("CXT5066: external microphone detected\n");
2018 snd_hda_sequence_write(codec, ext_mic_present); 2037 snd_hda_sequence_write(codec, ext_mic_present);
@@ -2029,12 +2048,10 @@ static void cxt5066_hp_automute(struct hda_codec *codec)
2029 unsigned int portA, portD; 2048 unsigned int portA, portD;
2030 2049
2031 /* Port A */ 2050 /* Port A */
2032 portA = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0) 2051 portA = snd_hda_jack_detect(codec, 0x19);
2033 & AC_PINSENSE_PRESENCE;
2034 2052
2035 /* Port D */ 2053 /* Port D */
2036 portD = (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) 2054 portD = snd_hda_jack_detect(codec, 0x1c);
2037 & AC_PINSENSE_PRESENCE) << 1;
2038 2055
2039 spec->hp_present = !!(portA | portD); 2056 spec->hp_present = !!(portA | portD);
2040 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", 2057 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n",
@@ -2056,6 +2073,20 @@ static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
2056 } 2073 }
2057} 2074}
2058 2075
2076/* unsolicited event for jack sensing */
2077static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res)
2078{
2079 snd_printdd("CXT5066_vostro: unsol event %x (%x)\n", res, res >> 26);
2080 switch (res >> 26) {
2081 case CONEXANT_HP_EVENT:
2082 cxt5066_hp_automute(codec);
2083 break;
2084 case CONEXANT_MIC_EVENT:
2085 cxt5066_vostro_automic(codec);
2086 break;
2087 }
2088}
2089
2059static const struct hda_input_mux cxt5066_analog_mic_boost = { 2090static const struct hda_input_mux cxt5066_analog_mic_boost = {
2060 .num_items = 5, 2091 .num_items = 5,
2061 .items = { 2092 .items = {
@@ -2297,6 +2328,67 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = {
2297 { } /* end */ 2328 { } /* end */
2298}; 2329};
2299 2330
2331static struct hda_verb cxt5066_init_verbs_vostro[] = {
2332 /* Port A: headphones */
2333 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2334 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2335
2336 /* Port B: external microphone */
2337 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2338
2339 /* Port C: unused */
2340 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2341
2342 /* Port D: unused */
2343 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2344
2345 /* Port E: unused, but has primary EAPD */
2346 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2347 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2348
2349 /* Port F: unused */
2350 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2351
2352 /* Port G: internal speakers */
2353 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2354 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2355
2356 /* DAC1 */
2357 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2358
2359 /* DAC2: unused */
2360 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2361
2362 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2363 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2364 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2365 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2366 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2367 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2368 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2369 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2370 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2371 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2372 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2373 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2374
2375 /* Digital microphone port */
2376 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2377
2378 /* Audio input selectors */
2379 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2380 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2381
2382 /* Disable SPDIF */
2383 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2384 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2385
2386 /* enable unsolicited events for Port A and B */
2387 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2388 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2389 { } /* end */
2390};
2391
2300static struct hda_verb cxt5066_init_verbs_portd_lo[] = { 2392static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2301 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2393 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2302 { } /* end */ 2394 { } /* end */
@@ -2318,6 +2410,7 @@ enum {
2318 CXT5066_LAPTOP, /* Laptops w/ EAPD support */ 2410 CXT5066_LAPTOP, /* Laptops w/ EAPD support */
2319 CXT5066_DELL_LAPTOP, /* Dell Laptop */ 2411 CXT5066_DELL_LAPTOP, /* Dell Laptop */
2320 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ 2412 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */
2413 CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */
2321 CXT5066_MODELS 2414 CXT5066_MODELS
2322}; 2415};
2323 2416
@@ -2325,6 +2418,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
2325 [CXT5066_LAPTOP] = "laptop", 2418 [CXT5066_LAPTOP] = "laptop",
2326 [CXT5066_DELL_LAPTOP] = "dell-laptop", 2419 [CXT5066_DELL_LAPTOP] = "dell-laptop",
2327 [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"
2328}; 2422};
2329 2423
2330static struct snd_pci_quirk cxt5066_cfg_tbl[] = { 2424static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
@@ -2333,6 +2427,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2333 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", 2427 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
2334 CXT5066_DELL_LAPTOP), 2428 CXT5066_DELL_LAPTOP),
2335 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), 2429 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
2430 SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
2336 {} 2431 {}
2337}; 2432};
2338 2433
@@ -2400,6 +2495,19 @@ static int patch_cxt5066(struct hda_codec *codec)
2400 /* input source automatically selected */ 2495 /* input source automatically selected */
2401 spec->input_mux = NULL; 2496 spec->input_mux = NULL;
2402 break; 2497 break;
2498 case CXT5066_DELL_VOSTO:
2499 codec->patch_ops.unsol_event = cxt5066_vostro_event;
2500 spec->init_verbs[0] = cxt5066_init_verbs_vostro;
2501 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
2502 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2503 spec->port_d_mode = 0;
2504
2505 /* no S/PDIF out */
2506 spec->multiout.dig_out_nid = 0;
2507
2508 /* input source automatically selected */
2509 spec->input_mux = NULL;
2510 break;
2403 } 2511 }
2404 2512
2405 return 0; 2513 return 0;
@@ -2417,6 +2525,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
2417 .patch = patch_cxt5051 }, 2525 .patch = patch_cxt5051 },
2418 { .id = 0x14f15066, .name = "CX20582 (Pebble)", 2526 { .id = 0x14f15066, .name = "CX20582 (Pebble)",
2419 .patch = patch_cxt5066 }, 2527 .patch = patch_cxt5066 },
2528 { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
2529 .patch = patch_cxt5066 },
2420 {} /* terminator */ 2530 {} /* terminator */
2421}; 2531};
2422 2532
@@ -2424,6 +2534,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15045");
2424MODULE_ALIAS("snd-hda-codec-id:14f15047"); 2534MODULE_ALIAS("snd-hda-codec-id:14f15047");
2425MODULE_ALIAS("snd-hda-codec-id:14f15051"); 2535MODULE_ALIAS("snd-hda-codec-id:14f15051");
2426MODULE_ALIAS("snd-hda-codec-id:14f15066"); 2536MODULE_ALIAS("snd-hda-codec-id:14f15066");
2537MODULE_ALIAS("snd-hda-codec-id:14f15067");
2427 2538
2428MODULE_LICENSE("GPL"); 2539MODULE_LICENSE("GPL");
2429MODULE_DESCRIPTION("Conexant HD-audio codec"); 2540MODULE_DESCRIPTION("Conexant HD-audio codec");