Due to returning the email and resending it//答复: [PATCH 1/3] Fix headset auto detect fail in cx8070 and SN6140

From: 刘博
Date: Thu Dec 28 2023 - 10:54:20 EST


FYI

Best Regards
Bo Liu (刘博)
Cell#: +86-18986160629
 Email: bo.liu@xxxxxxxxxxxxxx
深圳前海深蕾半导体有限公司
湖北省武汉市东湖高新技术开发区关山大道355号铭丰大厦
16楼1601-1603室
 Room 1601-1603,mTower, No. 355 Guanshan Avenue,
 East Lake High-tech Development Zone, Wuhan, Hubei Province.
 
-----邮件原件-----
发件人: bo liu <bo.liu@xxxxxxxxxxxxxx>
发送时间: 2023年12月27日 15:10
收件人: perex@xxxxxxxx; tiwai@xxxxxxxx
抄送: linux-sound@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; bo liu <bo.liu@xxxxxxxxxxxxxx>
主题: [PATCH 1/3] Fix headset auto detect fail in cx8070 and SN6140

CX8070 and SN6140 will get wrong headset type when use OMTP headset, then the headset mic will not work.

Signed-off-by: bo liu <bo.liu@xxxxxxxxxxxxxx>
---
sound/pci/hda/patch_conexant.c | 75 +++++++++++++++++++++++++++++++++-
1 file changed, 74 insertions(+), 1 deletion(-)

diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index a889cccdd607..2d58595bfbdd 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -166,6 +166,7 @@ static void cxt_init_gpio_led(struct hda_codec *codec)

static int cx_auto_init(struct hda_codec *codec) {
+ unsigned int mic_persent;
struct conexant_spec *spec = codec->spec;
snd_hda_gen_init(codec);
if (!spec->dynamic_eapd)
@@ -174,6 +175,23 @@ static int cx_auto_init(struct hda_codec *codec)
cxt_init_gpio_led(codec);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);

+ switch (codec->core.vendor_id) {
+ case 0x14f11f86:
+ case 0x14f11f87:
+ /* fix some headset recognize fail issue */
+ snd_hda_codec_write(codec, 0x1c, 0, 0x320, 0x010);
+ snd_hda_codec_write(codec, 0x1c, 0, 0x3b0, 0xe10);
+ snd_hda_codec_write(codec, 0x1c, 0, 0x4f0, 0x0eb);
+ /* fix reboot headset recognize fail issue */
+ mic_persent = snd_hda_codec_read(codec, 0x19, 0, 0xf09, 0x0);
+ if (mic_persent&0x80000000) {
+ snd_hda_codec_write(codec, 0x19, 0, 0x707, 0x24);
+ } else {
+ snd_hda_codec_write(codec, 0x19, 0, 0x707, 0x20);
+ }
+ break;
+ }
+
return 0;
}

@@ -191,6 +209,60 @@ static void cx_auto_free(struct hda_codec *codec)
cx_auto_shutdown(codec);
snd_hda_gen_free(codec);
}
+
+static int headset_present_flag;
+static void cx_jack_unsol_event(struct hda_codec *codec, unsigned int
+res) {
+ unsigned int val,phone_present,mic_persent,phone_tag,mic_tag;
+ unsigned int count=0;
+
+ switch (codec->core.vendor_id) {
+ case 0x14f11f86:
+ case 0x14f11f87:
+ /* check hp&mic tag to process headset pulgin&plugout */
+ phone_tag = snd_hda_codec_read(codec, 0x16, 0, 0xf08, 0x0);
+ mic_tag = snd_hda_codec_read(codec, 0x19, 0, 0xf08, 0x0);
+ if((phone_tag&(res>>26)) || (mic_tag&(res>>26))) {
+ //msleep(600);
+ phone_present = snd_hda_codec_read(codec, 0x16, 0, 0xf09, 0x0);
+ if(!(phone_present&0x80000000)) {/* headphone plugout */
+ headset_present_flag = 0;
+ snd_hda_codec_write(codec, 0x19, 0, 0x707, 0x20);
+ break;
+ }
+ if (headset_present_flag == 0) {
+ headset_present_flag = 1;
+ } else if(headset_present_flag == 1) {
+ mic_persent = snd_hda_codec_read(codec, 0x19, 0, 0xf09, 0x0);
+ if ((phone_present&0x80000000)&&(mic_persent&0x80000000)) {/* headset is present */
+ /* wait headset detect done */
+ do {
+ val = snd_hda_codec_read(codec, 0x1c, 0, 0xca0, 0x0);
+ if(val&0x080) {
+ break;
+ }
+ msleep(10);
+ count += 1;
+ } while(count > 5);
+ 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, 0x707, 0x24);
+ } else if(val&0x400) {
+ codec_dbg(codec, "headset plugin, type is OMTP\n");
+ snd_hda_codec_write(codec, 0x19, 0, 0x707, 0x24);
+ } else {
+ codec_dbg(codec, "headphone plugin\n");
+ }
+ headset_present_flag = 2;
+ }
+ }
+ }
+ break;
+ }
+
+ snd_hda_jack_unsol_event(codec, res);
+}

#ifdef CONFIG_PM
static int cx_auto_suspend(struct hda_codec *codec) @@ -205,7 +277,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 +1114,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
codec->spec = spec;
codec->patch_ops = cx_auto_patch_ops;

+ headset_present_flag = 0;
cx_auto_parse_eapd(codec);
spec->gen.own_eapd_ctl = 1;

--
2.34.1