From patchwork Fri Nov 22 14:30:46 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Henningsson X-Patchwork-Id: 293468 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 75A492C00E0 for ; Sat, 23 Nov 2013 01:31:51 +1100 (EST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1Vjrlr-0006CA-30; Fri, 22 Nov 2013 14:31:47 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1Vjrky-0005pc-Ak for kernel-team@lists.ubuntu.com; Fri, 22 Nov 2013 14:30:52 +0000 Received: from hd9483857.selulk5.dyn.perspektivbredband.net ([217.72.56.87] helo=localhost.localdomain) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1Vjrky-0003Le-4C; Fri, 22 Nov 2013 14:30:52 +0000 From: David Henningsson To: kernel-team@lists.ubuntu.com Subject: [PATCH 02/15] ALSA: hda - allow "Headphone Mic" parser flag Date: Fri, 22 Nov 2013 15:30:46 +0100 Message-Id: <1385130659-29870-3-git-send-email-david.henningsson@canonical.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1385130659-29870-1-git-send-email-david.henningsson@canonical.com> References: <1385130659-29870-1-git-send-email-david.henningsson@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: kernel-team-bounces@lists.ubuntu.com This allows a specific mic to get the "Headphone Mic" name, in addition to the existing "Headset Mic" name. Also, it allows for a special mark: if the sequence number is set to 0xc, that's an indication to prefer it for headset mic, and if it's set to 0xd, that's an indication to prefer it for headphone mic. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai (backported from commit cb420b1186e0090f24137855e14e6f3bf7cb769d) Conflicts: sound/pci/hda/hda_auto_parser.c sound/pci/hda/hda_generic.c Signed-off-by: David Henningsson --- sound/pci/hda/hda_auto_parser.c | 68 ++++++++++++++++++++++++++++++++------- sound/pci/hda/hda_auto_parser.h | 8 +++-- 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 3ca379e..8483980 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -97,6 +97,32 @@ static void reorder_outputs(unsigned int nums, hda_nid_t *pins) } } +static bool can_be_headset_mic(struct hda_codec *codec, + struct auto_pin_cfg_item *item, + int seq_number) +{ + int attr; + unsigned int def_conf; + if (item->type != AUTO_PIN_MIC) + return false; + + if (item->is_headset_mic || item->is_headphone_mic) + return false; /* Already assigned */ + + def_conf = snd_hda_codec_get_pincfg(codec, item->pin); + attr = snd_hda_get_input_pin_attr(def_conf); + if (attr <= INPUT_PIN_ATTR_DOCK) + return false; + + if (seq_number >= 0) { + int seq = get_defcfg_sequence(def_conf); + if (seq != seq_number) + return false; + } + + return true; +} + /* * Parse all pin widgets and store the useful pin nids to cfg * @@ -231,20 +257,36 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, } } - /* Take first mic to be a headset mic pin */ - if (cond_flags & HDA_PINCFG_HEADSET_MIC) { - for (i = 0; i < cfg->num_inputs; i++) { - int attr; - unsigned int def_conf; - if (cfg->inputs[i].type != AUTO_PIN_MIC) - continue; - def_conf = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin); - attr = snd_hda_get_input_pin_attr(def_conf); - if (attr <= INPUT_PIN_ATTR_DOCK) + /* Find a pin that could be a headset or headphone mic */ + if (cond_flags & HDA_PINCFG_HEADSET_MIC || cond_flags & HDA_PINCFG_HEADPHONE_MIC) { + bool hsmic = !!(cond_flags & HDA_PINCFG_HEADSET_MIC); + bool hpmic = !!(cond_flags & HDA_PINCFG_HEADPHONE_MIC); + for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++) + if (hsmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xc)) { + cfg->inputs[i].is_headset_mic = 1; + hsmic = false; + } else if (hpmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xd)) { + cfg->inputs[i].is_headphone_mic = 1; + hpmic = false; + } + + /* If we didn't find our sequence number mark, fall back to any sequence number */ + for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++) { + if (!can_be_headset_mic(codec, &cfg->inputs[i], -1)) continue; - cfg->inputs[i].is_headset_mic = 1; - break; + if (hsmic) { + cfg->inputs[i].is_headset_mic = 1; + hsmic = false; + } else if (hpmic) { + cfg->inputs[i].is_headphone_mic = 1; + hpmic = false; + } } + + if (hsmic) + snd_printdd("Told to look for a headset mic, but didn't find any.\n"); + if (hpmic) + snd_printdd("Told to look for a headphone mic, but didn't find any.\n"); } /* FIX-UP: @@ -390,6 +432,8 @@ static const char *hda_get_input_pin_label(struct hda_codec *codec, case AC_JACK_MIC_IN: if (item && item->is_headset_mic) return "Headset Mic"; + if (item && item->is_headphone_mic) + return "Headphone Mic"; if (!check_location) return "Mic"; attr = snd_hda_get_input_pin_attr(def_conf); diff --git a/sound/pci/hda/hda_auto_parser.h b/sound/pci/hda/hda_auto_parser.h index 74b2ae5..19251b8 100644 --- a/sound/pci/hda/hda_auto_parser.h +++ b/sound/pci/hda/hda_auto_parser.h @@ -37,6 +37,7 @@ struct auto_pin_cfg_item { hda_nid_t pin; int type; unsigned int is_headset_mic:1; + unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */ }; struct auto_pin_cfg; @@ -78,9 +79,10 @@ struct auto_pin_cfg { }; /* bit-flags for snd_hda_parse_pin_def_config() behavior */ -#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */ -#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */ -#define HDA_PINCFG_HEADSET_MIC (1 << 2) /* Take first mic as headset mic */ +#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */ +#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */ +#define HDA_PINCFG_HEADSET_MIC (1 << 2) /* Try to find headset mic; mark seq number as 0xc to trigger */ +#define HDA_PINCFG_HEADPHONE_MIC (1 << 3) /* Try to find headphone mic; mark seq number as 0xd to trigger */ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, struct auto_pin_cfg *cfg,