All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] Inverted internal mic
@ 2012-02-28  8:57 David Henningsson
  2012-02-28  9:24 ` Takashi Iwai
                   ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: David Henningsson @ 2012-02-28  8:57 UTC (permalink / raw)
  To: Takashi Iwai, ALSA Development Mailing List; +Cc: 903853

[-- Attachment #1: Type: text/plain, Size: 2040 bytes --]

Hi,

One of the more common problems on laptop machines, is that the internal 
mic provides a stereo signal but with one channel phase inverted, or 
differential output.

This means problems for applications recording two channels but later 
merging them into one, leaving them with zero or near-zero output.

There are various ways we can work around this in both the kernel, 
alsa-lib and PulseAudio layers. It's a matter of picking the right one. 
I'm leaning towards trying to fix it in the kernel's codec drivers, because
1) we already have quirking infrastructure there
2) we already have some working quirks already in that layer
3) it would benefit other sound applications that use ALSA directly.

The downside to that is really that we're silencing out one channel for
everyone, leading to no application being able to use both channels, 
even if they would implement some kind of 
"auto-detect-and-reverse-one-channel" functionality.

For the most part, this has been some Acer Aspire machines running 
Realtek ALC268 / ALC269 / ALC271X / ALC272X, and for two of these we 
have proc coefs we can set, but for the other two these proc coefs, if 
they exist, are unknown to us.

Recently I came across a Conexant as well, and I decided to write a 
patch for it, that would take the approach that the internal mic is 
forced mono on the kcontrol, and make sure the right channel is always 
muted. The patch is verified by the reporter to fix this problem. It 
could use some perfection though - it would make sense to to the same to 
the internal mic boost as well, and the strcmp('Internal Mic') call 
could maybe be turned into something more elegant. But before going 
ahead with that, I'd like to hear your opinion on the matter, if you 
agree that this is a good approach to the problem?

References:

https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/903853/+attachment/2631623/+files/alsa-info.txt.VmCN7lMBL4

https://bugs.launchpad.net/bugs/903853

-- 
David Henningsson, Canonical Ltd.
http://launchpad.net/~diwic

[-- Attachment #2: 0001-Fix-internal-mic-for-Lenovo-Ideapad-U300s.patch --]
[-- Type: text/x-patch, Size: 4831 bytes --]

>From 3ef2a105a85195c14e25190bca53bb55260feffa Mon Sep 17 00:00:00 2001
From: David Henningsson <david.henningsson@canonical.com>
Date: Fri, 24 Feb 2012 14:57:44 +0100
Subject: [PATCH] Fix internal mic for Lenovo Ideapad U300s

The internal mic input is phase inverted on one channel.
To avoid people in userspace summing the channels together
and get zero result, mute the right channel and make sure
they can't unmute it.

BugLink: https://bugs.launchpad.net/bugs/903853
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
---
 sound/pci/hda/patch_conexant.c |   41 +++++++++++++++++++++++++++++----------
 1 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 266e5a6..4a05817 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -140,6 +140,7 @@ struct conexant_spec {
 	unsigned int asus:1;
 	unsigned int pin_eapd_ctrls:1;
 	unsigned int single_adc_amp:1;
+	unsigned int fixup_stereo_dmic:1;
 
 	unsigned int adc_switching:1;
 
@@ -4044,7 +4045,7 @@ static int cx_auto_init(struct hda_codec *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 struct snd_kcontrol_new knew[] = {
@@ -4056,7 +4057,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
 
 	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;
@@ -4074,7 +4075,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
 }
 
 #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)
@@ -4152,14 +4153,22 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
 	int i;
 
 	for (i = 0; i < spec->num_adc_nids; i++) {
+		int chs = 3;
 		hda_nid_t adc_nid = spec->adc_nids[i];
 		int idx = get_input_connection(codec, adc_nid, nid);
 		if (idx < 0)
 			continue;
 		if (spec->single_adc_amp)
 			idx = 0;
+
+		if (spec->fixup_stereo_dmic && (strcmp("Internal Mic", label) == 0)) {
+			/* Make left channel controllable and right channel muted */
+			chs = 1;
+			snd_hda_codec_write_cache(codec, adc_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 
+				AC_AMP_SET_RIGHT | AC_AMP_SET_INPUT | (idx << AC_AMP_SET_INDEX_SHIFT) | AC_AMP_MUTE);
+		}
 		return cx_auto_add_volume_idx(codec, label, pfx,
-					      cidx, adc_nid, HDA_INPUT, idx);
+					      cidx, adc_nid, HDA_INPUT, idx, chs);
 	}
 	return 0;
 }
@@ -4335,22 +4344,30 @@ static void apply_pincfg(struct hda_codec *codec, const struct cxt_pincfg *cfg)
 
 }
 
-static void apply_pin_fixup(struct hda_codec *codec,
+enum {
+	CXT_PINCFG_LENOVO_X200,
+	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,
-};
-
 static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
 	{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
 	{ 0x17, 0x21a11000 }, /* dock-mic */
@@ -4360,10 +4377,12 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
 
 static const struct cxt_pincfg *cxt_pincfg_tbl[] = {
 	[CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200,
+	[CXT_FIXUP_STEREO_DMIC] = NULL,
 };
 
 static const struct snd_pci_quirk cxt_fixups[] = {
 	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200),
+	SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
 	{}
 };
 
@@ -4387,7 +4406,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
 		break;
 	}
 
-	apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl);
+	apply_fixup(codec, cxt_fixups, cxt_pincfg_tbl);
 
 	err = cx_auto_search_adcs(codec);
 	if (err < 0)
-- 
1.7.9


[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related	[flat|nested] 40+ messages in thread
* [RFC PATCH] Inverted internal mic
@ 2014-10-20 13:52 rodney byne
  0 siblings, 0 replies; 40+ messages in thread
From: rodney byne @ 2014-10-20 13:52 UTC (permalink / raw)
  To: alsa-devel

Hello to David Henningsson and associates,

I have been trawling the internet to find out
why the internal mic on my Acer Aspire One AOA-110
netbook is permanently inhibited by Alsa.
This little pc runs Linux Peppermint 5 OS, which contains
PulseAudio ESD over-riding the Alsa sound architecture.

Thinking initially this was a "programming" fault, I
have read as much of the history up to the patch need as
I can understand and so appreciate this action on your
part was deliberate - but must comment nonetheless that
this matter is disconcerting from a casual user perspective.

In short, the owner just wants everything on his
machine to work normally and so I would really like to
use the internal mic function for what it was intended.

Personally I have often wondered why PA was ever introduced,
as Alsa & AlsaMixer are perfectly capable of working on
their own, as testament to early releases of Linux Mint.
My opinion is PA just makes the sound system too complicated.
I call it guilding the lilly - so use the principle K.I.S.S

My question therefore is, can the patch be easily lifted
at will to re-enable the internal microphone?

Thanks and best regards,
from Rodney.

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2014-10-20 13:53 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-28  8:57 [RFC PATCH] Inverted internal mic David Henningsson
2012-02-28  9:24 ` Takashi Iwai
2012-02-28  9:54   ` David Henningsson
2012-02-28 10:38     ` Takashi Iwai
2012-02-28 13:07       ` David Henningsson
2012-02-28 13:22         ` Takashi Iwai
2012-02-28 14:19           ` David Henningsson
2012-02-28 15:20             ` Takashi Iwai
2012-02-28 18:11               ` David Henningsson
2012-02-28 19:42                 ` Takashi Iwai
2012-02-29  9:21                   ` David Henningsson
2012-02-29  9:56                     ` Takashi Iwai
2012-02-29 10:45                       ` David Henningsson
2012-02-29 16:36                         ` Takashi Iwai
2012-06-19  3:07             ` Eliot Blennerhassett
2012-06-19  7:43               ` David Henningsson
2012-06-20 13:31                 ` Takashi Iwai
2012-06-21  1:15                   ` David Henningsson
2012-06-21 12:52                     ` Takashi Iwai
2012-06-21 13:04                       ` David Henningsson
2012-06-21 13:19                         ` Takashi Iwai
2012-06-21 14:23                           ` David Henningsson
2012-06-22  9:33                             ` Takashi Iwai
2012-06-22 10:46                               ` David Henningsson
2012-06-22 11:00                                 ` Takashi Iwai
2012-06-22 12:46                                   ` Takashi Iwai
2012-06-22 15:27                                     ` David Henningsson
2012-06-22 15:37                                       ` Takashi Iwai
2012-06-22 17:33                                         ` David Henningsson
2012-06-23  2:58                                           ` Eliot Blennerhassett
2012-06-23  8:40                                             ` Takashi Iwai
2012-06-23  8:39                                           ` Takashi Iwai
2012-06-25  8:04                                             ` David Henningsson
2012-06-25  8:18                                               ` Takashi Iwai
2012-06-20  8:02               ` Takashi Iwai
2012-06-20 10:54                 ` Eliot Blennerhassett
2012-02-29 11:02 ` Raymond Yau
2012-06-20 21:53 ` James Courtier-Dutton
2012-06-21  5:56   ` Takashi Iwai
2014-10-20 13:52 rodney byne

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.