Received: by 2002:a05:7412:7c14:b0:fa:6e18:a558 with SMTP id ii20csp399401rdb; Mon, 22 Jan 2024 07:37:32 -0800 (PST) X-Google-Smtp-Source: AGHT+IGH57cCaV6EzyW6qBb2ZmFGyxk+DegQPRb1iiO+UAAxTf0UnPAaejl5bn0PD22FKH5l/qEx X-Received: by 2002:a05:6a00:1a90:b0:6db:cff7:bc4b with SMTP id e16-20020a056a001a9000b006dbcff7bc4bmr1781668pfv.48.1705937851975; Mon, 22 Jan 2024 07:37:31 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705937851; cv=pass; d=google.com; s=arc-20160816; b=spfaDBteqDilIxn0/Xjmt8jJ7WeJ155qtxy2d53Iw8TJQC/uoJEjaCmAo1IAsoZudQ pROIRJOWKbkHcc3WOFX4TNErhcUwJqX1iPaguXdmWu+8MFeuoJolzZ9ddb+ul987AfcX lVGuPiF5jdR/XM6Y0BQalbo1k2ONDMwOCsyE9j7qomdZnKEHqFyN7oX36DkdB8mzwA40 F35rFt4nBsCElntnd69X4rXtQFuI6NmPAkGG10EwqU7pvi3KCnkNrM37/JvMLeP7KVT5 UeZ34GE0OAIbL1KadEZjf0DDGupCCxh3Wwy8Rb7ApgqQPEDCrsVQL2XUoQCyiiny0Sqc 5BUQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=Mg6eqsstTucGznUh4KwA/EbGwi6qCkTzsLM6H1qBP70=; fh=1oAedcvxnhmNt/ijdvD7L9+cthEB1Rox2C8ZUCk7Q90=; b=OwmbKiy/DQrb3ui9TRtKApSl6OHp+KYgOG4HR+H0eppv14aq8oHH7VEXbkdVdWSsk4 o/TvNfDN6Zeb0iOyqu3LOWpROd1DlRvNXN4AZeLvrmi0M4cYJ/oKZfzJRma1tq0kgHz/ WJA7+zxnCwQEkZxIneUF0HnOGs5YOOxrBfiJV4/lc+S5u9OHD6mRJ7bCSjic2MxFJ58i lqo1DiJl/Gw1JPalpsLQo47lPYo9ZrXFkDulHKNElihv7/Bn/38AenvShgRA3u34+jH4 A1O1gh8G2y/qm2jFGmZ1NSfT7HKQ6QDqjPB4JHqTlzaOHAr0plqVYYkhFnRvg2o6ovG2 5naA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=ptZgbpBx; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-33307-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-33307-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id c12-20020a63d50c000000b00565e0624182si8284601pgg.404.2024.01.22.07.37.31 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jan 2024 07:37:31 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-33307-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=ptZgbpBx; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-33307-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-33307-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 9378B288FF6 for ; Mon, 22 Jan 2024 15:29:58 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B3A365FDA1; Mon, 22 Jan 2024 15:02:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ptZgbpBx" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B56CB5FB82; Mon, 22 Jan 2024 15:02:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705935741; cv=none; b=H/Z8KMYVo/c1ZnnhMBaCfLcOagNqOcTu5UVrBySx5jSywqanSfhBSv4S5veOOMIA3X2Cu+iaRWnXvJISTsuKIq/lIcjLvhqBQtO60jhHLSDT98aAPrUzlIV0mEOyTxabz7O0dpf7MNq5MEmPi/jjxdCJwv+juJwWkGEbYWqiLJ4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705935741; c=relaxed/simple; bh=v5lblB5HIWBpKL1xZFHrgqsw1lO2Xc8IWd4GEe+xRJY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EeFglPLPFAdrukT9sGK+6UVSOsA0AV6EYzLWYx7s+7Hoyqe66olOsrYCtF/ksGvoxcBr0zlDzcR062pMa0A26xqVs19Gq3G62t47ZBUojCgiVpWrVFB/j4sE4fkWY0tr3Od0hwkWS5aTbi2CHYY4MlL+8zhlqNcqh/sKf+dFMf4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ptZgbpBx; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8CE86C43142; Mon, 22 Jan 2024 15:02:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1705935741; bh=v5lblB5HIWBpKL1xZFHrgqsw1lO2Xc8IWd4GEe+xRJY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ptZgbpBxD9ZoZCFCoNNS1xjCCBh9/oFuj55MlYwtA3lIXzQPBoE/8hJ4tnIAeeeXP 62udfkGJQia1OaeO8a2eF+D/fJEyxGN2klv+T2XMuD/kBhfQ0ylhZRu+nplj/UVmaA u31eZk/qlc9HSasjVu5OwO0jx+N0kwliInRxZusHSxBh7RGU+1eG27ZHWsYNaspbEc yjZqXdJG+Xs/erUZlQ5y2fpWBS4GYJq52yRfNJ2R8ffhiBba/UuiUVsRaxfodXmZ2M WWyAN4YnXTAmUGUPrLU3UH6dqkt1SSBxZYdQ4klHHHi0HE8nXv8dtYYaOMSSqB8HQ0 ioHqueXTsWRFw== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: bo liu , Takashi Iwai , Sasha Levin , perex@perex.cz, tiwai@suse.com, linux-sound@vger.kernel.org Subject: [PATCH AUTOSEL 6.7 85/88] ALSA: hda/conexant: Fix headset auto detect fail in cx8070 and SN6140 Date: Mon, 22 Jan 2024 09:51:58 -0500 Message-ID: <20240122145608.990137-85-sashal@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240122145608.990137-1-sashal@kernel.org> References: <20240122145608.990137-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.7.1 Content-Transfer-Encoding: 8bit From: bo liu [ Upstream commit 7aeb259086487417f0fecf66e325bee133e8813a ] When OMTP headset plugin the headset jack of CX8070 and SN6160 sound cards, the headset type detection circuit will recognize the headset type as CTIA. At this point, plugout and plugin the headset will get the correct headset type as OMTP. The reason for the failure of headset type recognition is that the sound card creation will enable the VREF voltage of the headset mic, which interferes with the headset type automatic detection circuit. Plugout and plugin the headset will restart the headset detection and get the correct headset type. The patch is disable the VREF voltage when the headset is not present, and will enable the VREF voltage when the headset is present. Signed-off-by: bo liu Link: https://lore.kernel.org/r/20240108110235.3867-1-bo.liu@senarytech.com Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/pci/hda/patch_conexant.c | 115 ++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index a889cccdd607..e8819e8a9876 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -21,6 +21,12 @@ #include "hda_jack.h" #include "hda_generic.h" +enum { + CX_HEADSET_NOPRESENT = 0, + CX_HEADSET_PARTPRESENT, + CX_HEADSET_ALLPRESENT, +}; + struct conexant_spec { struct hda_gen_spec gen; @@ -42,7 +48,8 @@ struct conexant_spec { unsigned int gpio_led; unsigned int gpio_mute_led_mask; unsigned int gpio_mic_led_mask; - + unsigned int headset_present_flag; + bool is_cx8070_sn6140; }; @@ -164,6 +171,27 @@ static void cxt_init_gpio_led(struct hda_codec *codec) } } +static void cx_fixup_headset_recog(struct hda_codec *codec) +{ + unsigned int mic_persent; + + /* fix some headset type recognize fail issue, such as EDIFIER headset */ + /* set micbiasd output current comparator threshold from 66% to 55%. */ + snd_hda_codec_write(codec, 0x1c, 0, 0x320, 0x010); + /* set OFF voltage for DFET from -1.2V to -0.8V, set headset micbias registor + * value adjustment trim from 2.2K ohms to 2.0K ohms. + */ + snd_hda_codec_write(codec, 0x1c, 0, 0x3b0, 0xe10); + /* fix reboot headset type recognize fail issue */ + mic_persent = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0x0); + if (mic_persent & AC_PINSENSE_PRESENCE) + /* enable headset mic VREF */ + snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24); + else + /* disable headset mic VREF */ + snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20); +} + static int cx_auto_init(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; @@ -174,6 +202,9 @@ static int cx_auto_init(struct hda_codec *codec) cxt_init_gpio_led(codec); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); + if (spec->is_cx8070_sn6140) + cx_fixup_headset_recog(codec); + return 0; } @@ -192,6 +223,77 @@ static void cx_auto_free(struct hda_codec *codec) snd_hda_gen_free(codec); } +static void cx_process_headset_plugin(struct hda_codec *codec) +{ + unsigned int val; + unsigned int count = 0; + + /* Wait headset detect done. */ + do { + val = snd_hda_codec_read(codec, 0x1c, 0, 0xca0, 0x0); + if (val & 0x080) { + codec_dbg(codec, "headset type detect done!\n"); + break; + } + msleep(20); + count++; + } while (count < 3); + val = snd_hda_codec_read(codec, 0x1c, 0, 0xcb0, 0x0); + if (val & 0x800) { + codec_dbg(codec, "headset plugin, type is CTIA\n"); + snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24); + } else if (val & 0x400) { + codec_dbg(codec, "headset plugin, type is OMTP\n"); + snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24); + } else { + codec_dbg(codec, "headphone plugin\n"); + } +} + +static void cx_update_headset_mic_vref(struct hda_codec *codec, unsigned int res) +{ + unsigned int phone_present, mic_persent, phone_tag, mic_tag; + struct conexant_spec *spec = codec->spec; + + /* In cx8070 and sn6140, the node 16 can only be config to headphone or disabled, + * the node 19 can only be config to microphone or disabled. + * Check hp&mic tag to process headset pulgin&plugout. + */ + phone_tag = snd_hda_codec_read(codec, 0x16, 0, AC_VERB_GET_UNSOLICITED_RESPONSE, 0x0); + mic_tag = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_UNSOLICITED_RESPONSE, 0x0); + if ((phone_tag & (res >> AC_UNSOL_RES_TAG_SHIFT)) || + (mic_tag & (res >> AC_UNSOL_RES_TAG_SHIFT))) { + phone_present = snd_hda_codec_read(codec, 0x16, 0, AC_VERB_GET_PIN_SENSE, 0x0); + if (!(phone_present & AC_PINSENSE_PRESENCE)) {/* headphone plugout */ + spec->headset_present_flag = CX_HEADSET_NOPRESENT; + snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20); + return; + } + if (spec->headset_present_flag == CX_HEADSET_NOPRESENT) { + spec->headset_present_flag = CX_HEADSET_PARTPRESENT; + } else if (spec->headset_present_flag == CX_HEADSET_PARTPRESENT) { + mic_persent = snd_hda_codec_read(codec, 0x19, 0, + AC_VERB_GET_PIN_SENSE, 0x0); + /* headset is present */ + if ((phone_present & AC_PINSENSE_PRESENCE) && + (mic_persent & AC_PINSENSE_PRESENCE)) { + cx_process_headset_plugin(codec); + spec->headset_present_flag = CX_HEADSET_ALLPRESENT; + } + } + } +} + +static void cx_jack_unsol_event(struct hda_codec *codec, unsigned int res) +{ + struct conexant_spec *spec = codec->spec; + + if (spec->is_cx8070_sn6140) + cx_update_headset_mic_vref(codec, res); + + snd_hda_jack_unsol_event(codec, res); +} + #ifdef CONFIG_PM static int cx_auto_suspend(struct hda_codec *codec) { @@ -205,7 +307,7 @@ static const struct hda_codec_ops cx_auto_patch_ops = { .build_pcms = snd_hda_gen_build_pcms, .init = cx_auto_init, .free = cx_auto_free, - .unsol_event = snd_hda_jack_unsol_event, + .unsol_event = cx_jack_unsol_event, #ifdef CONFIG_PM .suspend = cx_auto_suspend, .check_power_status = snd_hda_gen_check_power_status, @@ -1042,6 +1144,15 @@ static int patch_conexant_auto(struct hda_codec *codec) codec->spec = spec; codec->patch_ops = cx_auto_patch_ops; + /* init cx8070/sn6140 flag and reset headset_present_flag */ + switch (codec->core.vendor_id) { + case 0x14f11f86: + case 0x14f11f87: + spec->is_cx8070_sn6140 = true; + spec->headset_present_flag = CX_HEADSET_NOPRESENT; + break; + } + cx_auto_parse_eapd(codec); spec->gen.own_eapd_ctl = 1; -- 2.43.0