From: Greg Kroah-Hartman Date: Wed, 9 Apr 2014 23:38:05 +0000 (-0700) Subject: 3.4-stable patches X-Git-Tag: v3.10.37~19 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=22016aaae31bfde894a78e534bb89e513f52c193;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: alsa-hda-fix-internal-mic-for-lenovo-ideapad-u300s.patch --- diff --git a/queue-3.4/alsa-hda-fix-internal-mic-for-lenovo-ideapad-u300s.patch b/queue-3.4/alsa-hda-fix-internal-mic-for-lenovo-ideapad-u300s.patch new file mode 100644 index 00000000000..b1ca1b03ced --- /dev/null +++ b/queue-3.4/alsa-hda-fix-internal-mic-for-lenovo-ideapad-u300s.patch @@ -0,0 +1,220 @@ +From 18dcd3044e4c4b3ab6341c98e8d0e81e0d58d5e3 Mon Sep 17 00:00:00 2001 +From: David Henningsson +Date: Mon, 2 Apr 2012 15:40:27 +0200 +Subject: ALSA: hda - Fix internal mic for Lenovo Ideapad U300s + +From: David Henningsson + +commit 18dcd3044e4c4b3ab6341c98e8d0e81e0d58d5e3 upstream. + +The internal mic input is phase inverted on one channel. +To avoid people in userspace summing the channels together +and get zero result, use a separate mixer control for the +inverted channel. + +BugLink: https://bugs.launchpad.net/bugs/903853 +Signed-off-by: David Henningsson +Signed-off-by: Takashi Iwai +[wml: Backported to 3.4: + - Adjust context + - one more enum value CXT_PINCFG_LENOVO_TP410 + - Change both invocations of apply_pin_fixup()] +Signed-off-by: Weng Meiling +--- + sound/pci/hda/patch_conexant.c | 92 ++++++++++++++++++++++++++++++++++------- + 1 file changed, 77 insertions(+), 15 deletions(-) + +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -141,6 +141,7 @@ struct conexant_spec { + unsigned int hp_laptop:1; + unsigned int asus:1; + unsigned int pin_eapd_ctrls:1; ++ unsigned int fixup_stereo_dmic:1; + + unsigned int adc_switching:1; + +@@ -4071,9 +4072,9 @@ static int cx_auto_init(struct hda_codec + + static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename, + const char *dir, int cidx, +- hda_nid_t nid, int hda_dir, int amp_idx) ++ hda_nid_t nid, int hda_dir, int amp_idx, int chs) + { +- static char name[32]; ++ static char name[44]; + static struct snd_kcontrol_new knew[] = { + HDA_CODEC_VOLUME(name, 0, 0, 0), + HDA_CODEC_MUTE(name, 0, 0, 0), +@@ -4083,7 +4084,7 @@ static int cx_auto_add_volume_idx(struct + + for (i = 0; i < 2; i++) { + struct snd_kcontrol *kctl; +- knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx, ++ knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, chs, amp_idx, + hda_dir); + knew[i].subdevice = HDA_SUBDEV_AMP_FLAG; + knew[i].index = cidx; +@@ -4102,7 +4103,7 @@ static int cx_auto_add_volume_idx(struct + } + + #define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \ +- cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0) ++ cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0, 3) + + #define cx_auto_add_pb_volume(codec, nid, str, idx) \ + cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) +@@ -4172,6 +4173,36 @@ static int cx_auto_build_output_controls + return 0; + } + ++/* Returns zero if this is a normal stereo channel, and non-zero if it should ++ be split in two independent channels. ++ dest_label must be at least 44 characters. */ ++static int cx_auto_get_rightch_label(struct hda_codec *codec, const char *label, ++ char *dest_label, int nid) ++{ ++ struct conexant_spec *spec = codec->spec; ++ int i; ++ ++ if (!spec->fixup_stereo_dmic) ++ return 0; ++ ++ for (i = 0; i < AUTO_CFG_MAX_INS; i++) { ++ int def_conf; ++ if (spec->autocfg.inputs[i].pin != nid) ++ continue; ++ ++ if (spec->autocfg.inputs[i].type != AUTO_PIN_MIC) ++ return 0; ++ def_conf = snd_hda_codec_get_pincfg(codec, nid); ++ if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) ++ return 0; ++ ++ /* Finally found the inverted internal mic! */ ++ snprintf(dest_label, 44, "Inverted %s", label); ++ return 1; ++ } ++ return 0; ++} ++ + static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, + const char *label, const char *pfx, + int cidx) +@@ -4180,14 +4211,25 @@ static int cx_auto_add_capture_volume(st + int i; + + for (i = 0; i < spec->num_adc_nids; i++) { ++ char rightch_label[44]; + hda_nid_t adc_nid = spec->adc_nids[i]; + int idx = get_input_connection(codec, adc_nid, nid); + if (idx < 0) + continue; + if (codec->single_adc_amp) + idx = 0; ++ ++ if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) { ++ /* Make two independent kcontrols for left and right */ ++ int err = cx_auto_add_volume_idx(codec, label, pfx, ++ cidx, adc_nid, HDA_INPUT, idx, 1); ++ if (err < 0) ++ return err; ++ return cx_auto_add_volume_idx(codec, rightch_label, pfx, ++ cidx, adc_nid, HDA_INPUT, idx, 2); ++ } + return cx_auto_add_volume_idx(codec, label, pfx, +- cidx, adc_nid, HDA_INPUT, idx); ++ cidx, adc_nid, HDA_INPUT, idx, 3); + } + return 0; + } +@@ -4200,9 +4242,19 @@ static int cx_auto_add_boost_volume(stru + int i, con; + + nid = spec->imux_info[idx].pin; +- if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) ++ if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { ++ char rightch_label[44]; ++ if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) { ++ int err = cx_auto_add_volume_idx(codec, label, " Boost", ++ cidx, nid, HDA_INPUT, 0, 1); ++ if (err < 0) ++ return err; ++ return cx_auto_add_volume_idx(codec, rightch_label, " Boost", ++ cidx, nid, HDA_INPUT, 0, 2); ++ } + return cx_auto_add_volume(codec, label, " Boost", cidx, + nid, HDA_INPUT); ++ } + con = __select_input_connection(codec, spec->imux_info[idx].adc, nid, + &mux, false, 0); + if (con < 0) +@@ -4365,23 +4417,31 @@ static void apply_pincfg(struct hda_code + + } + +-static void apply_pin_fixup(struct hda_codec *codec, ++enum { ++ CXT_PINCFG_LENOVO_X200, ++ CXT_PINCFG_LENOVO_TP410, ++ CXT_FIXUP_STEREO_DMIC ++}; ++ ++static void apply_fixup(struct hda_codec *codec, + const struct snd_pci_quirk *quirk, + const struct cxt_pincfg **table) + { ++ struct conexant_spec *spec = codec->spec; ++ + quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); +- if (quirk) { ++ if (quirk && table[quirk->value]) { + snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n", + quirk->name); + apply_pincfg(codec, table[quirk->value]); + } ++ if (quirk->value == CXT_FIXUP_STEREO_DMIC) { ++ snd_printdd(KERN_INFO "hda_codec: applying internal mic workaround for %s\n", ++ quirk->name); ++ spec->fixup_stereo_dmic = 1; ++ } + } + +-enum { +- CXT_PINCFG_LENOVO_X200, +- CXT_PINCFG_LENOVO_TP410, +-}; +- + /* ThinkPad X200 & co with cxt5051 */ + static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { + { 0x16, 0x042140ff }, /* HP (seq# overridden) */ +@@ -4402,6 +4462,7 @@ static const struct cxt_pincfg cxt_pincf + static const struct cxt_pincfg *cxt_pincfg_tbl[] = { + [CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200, + [CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410, ++ [CXT_FIXUP_STEREO_DMIC] = NULL, + }; + + static const struct snd_pci_quirk cxt5051_fixups[] = { +@@ -4415,6 +4476,7 @@ static const struct snd_pci_quirk cxt506 + SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), ++ SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), + {} + }; + +@@ -4454,11 +4516,11 @@ static int patch_conexant_auto(struct hd + case 0x14f15051: + add_cx5051_fake_mutes(codec); + codec->pin_amp_workaround = 1; +- apply_pin_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl); ++ apply_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl); + break; + default: + codec->pin_amp_workaround = 1; +- apply_pin_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl); ++ apply_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl); + } + + /* Show mute-led control only on HP laptops diff --git a/queue-3.4/series b/queue-3.4/series index 9c4f6e4e038..f8e8245cbab 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -53,3 +53,4 @@ alsa-hda-fix-non-snoop-page-handling.patch alsa-hda-add-conexant-cx20751-2-3-4-codec-support.patch revert-alsa-hda-shut-up-pins-at-power-saving-mode-with-conexnat-codecs.patch alsa-hda-always-turn-on-pins-for-hdmi-dp.patch +alsa-hda-fix-internal-mic-for-lenovo-ideapad-u300s.patch