linux
linux copied to clipboard
[BUG] Huawei MateBook D15 headphone and speaker not work
@plbossart A few months ago I bought a Huawei Matebook D15 and the sound only works through HDMI. I have followed this guide https://github.com/thesofproject/linux/wiki/ES8336-support And I have compiled this branch https://github.com/thesofproject/linux/tree/es8336-v5.19 http://alsa-project.org/db/?f=77cd3bc0e0fa1b6a398e76f454fc11f017b10b4c
You are not using the SOF driver!
snd_intel_dspcfg: dsp_driver=1 dyndbg= p
please remove this option, and read the wiki: https://github.com/thesofproject/linux/wiki/ES8336-support
@plbossart I load the SOF driver and there is no sound card. http://alsa-project.org/db/?f=7b41c67fbe773bd8a70ecdb3946a3b264bc2a7d7
The last line of the dmesg log shows you have started probing the machine driver
[ 21.210242] sof-essx8336 sof-essx8336: quirk mask 0x20
If you don't see a card created it means that that probe failed somewhere. Not sure what happens, you have dynamic debug enabled but nothing is shown.
You will have to trace manually where the issue happens, likely by adding some dev_info statements in sound/soc/intel/boards/sof_es8336.c
you may also want to try and enable dynamic debug for the ASoC core, this will be very verbose but let you know why the card registration failed
options snd-soc-core dyndbg=+pmf
@plbossart I add some dev_info:
priv->gpio_speakers = gpiod_get_optional(codec_dev, "speakers-enable", GPIOD_OUT_LOW);
if (IS_ERR(priv->gpio_speakers)) {
ret = dev_err_probe(dev, PTR_ERR(priv->gpio_speakers),
"could not get speakers-enable GPIO\n");
dev_info(dev, "could not get speakers-enable GPIO\n");
goto err_put_codec;
}
[ 52.247139] sof-essx8336 sof-essx8336: quirk mask 0x20 [ 52.247141] sof-essx8336 sof-essx8336: quirk SSP0 [ 52.247142] sof-essx8336 sof-essx8336: quirk DMIC enabled [ 52.247168] sof-essx8336 sof-essx8336: could not get speakers-enable GPIO
http://alsa-project.org/db/?f=5adfb126cedacfecb5bc021097816853ebeb769b
That's not good news @tvelazquez, the problem is likely a BIOS issue or something. That's super hard to debug remotely. You are getting an error for an optional gpio, not sure what happens.
Try to add dynamic debug in https://elixir.bootlin.com/linux/latest/source/drivers/gpio/gpiolib.c and see what the results are.
You could also bypass this and just set priv->gpio_speakers = NULL and see what happens.
@plbossart dynamic debug enabled for gpiolib and add priv->gpio_speakers = NULL;
[ 9.281388] sof-essx8336 sof-essx8336: quirk mask 0x20 [ 9.281390] sof-essx8336 sof-essx8336: quirk SSP0 [ 9.281391] sof-essx8336 sof-essx8336: quirk DMIC enabled [ 9.281413] gpiolib:gpiod_get_index: i2c i2c-ESSX8336:00: GPIO lookup for consumer speakers-enable [ 9.281414] gpiolib:gpiod_get_index: i2c i2c-ESSX8336:00: using ACPI for GPIO lookup [ 9.281428] gpiolib:gpiod_get_index: i2c i2c-ESSX8336:00: No GPIO consumer speakers-enable found [ 9.281428] gpiolib:gpiod_get_index: i2c i2c-ESSX8336:00: GPIO lookup for consumer headphone-enable [ 9.281429] gpiolib:gpiod_get_index: i2c i2c-ESSX8336:00: using ACPI for GPIO lookup [ 9.281430] gpiolib:gpiod_get_index: i2c i2c-ESSX8336:00: using lookup tables for GPIO lookup [ 9.281431] gpiolib:gpiod_get_index: i2c i2c-ESSX8336:00: No GPIO consumer headphone-enable found [ 9.281433] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link SSP0-Codec [ 9.281433] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link dmic01 [ 9.281434] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link dmic16k [ 9.281435] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link iDisp1 [ 9.281435] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link iDisp2 [ 9.281436] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link iDisp3 [ 9.281437] snd_soc_core:snd_soc_add_pcm_runtime: sof-essx8336 sof-essx8336: ASoC: binding SSP0-Codec [ 9.281438] snd_soc_core:soc_dai_link_sanity_check: sof-essx8336 sof-essx8336: ASoC: codec component i2c-ESSX8336:00 not found for link SSP0-Codec [ 9.281440] sof-essx8336 sof-essx8336: snd_soc_register_card failed: -517
[ 9.281437] snd_soc_core:snd_soc_add_pcm_runtime: sof-essx8336 sof-essx8336: ASoC: binding SSP0-Codec [ 9.281438] snd_soc_core:soc_dai_link_sanity_check: sof-essx8336 sof-essx8336: ASoC: codec component i2c-ESSX8336:00 not found for link SSP0-Codec
that's a completely different issue to the initial gpio issue. This hints at a configuration issue where maybe the codec is not probed.
I don't have any bandwidth to help in the next two weeks, sorry.
@plbossart What dumps do you need to do the analysis? acpidump? I would like to provide you with all the information you need. Thanks.
@tvelazquez make sure snd-soc-es8316 is probed and provide the information shown in /sys/kernel/debug/asoc/components
@plbossart added some printk at es8316_probe() and es8316_i2c_probe() but dmesg doesn't show it.
/sys/kernel/debug/asoc/components: 0000:00:1f.3 ehdaudio0D2 dmic-codec snd-soc-dummy snd-soc-dummy
@tvelazquez can you share the DSDT and also verify that this codec driver is part of the build? Wondering if there is some sort of I2C configuration issue.
@plbossart here you have the DSDT https://github.com/tvelazquez/thesofproject/raw/main/dsdt.dat https://github.com/tvelazquez/thesofproject/raw/main/dsdt.dsl
I don't see anything blantantly wrong in the DSDT @tvelazquez but it's also on the rather convoluted side.
I don't see why e.g. there are two addresses for this codec Name (SBUF, ResourceTemplate () { I2cSerialBusV2 (0x0010, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\_SB.PC00.I2C2", 0x00, ResourceConsumer, , Exclusive, ) I2cSerialBusV2 (0x0011, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\_SB.PC00.I2C2", 0x00, ResourceConsumer, , Exclusive, )
I think only the second one is valid, that's what I see for other devices.
I am afraid you'll have to look into other ways to debug why the driver is not probed, or ask @yangxiaohua2009
@tvelazquez Do you know how to change ACPI in Linux? Please remove the second I2C address.
You can verify it by install i2c-tools and dump the i2c by
sudo i2cdump -f -y 1 0x10
1 is your bus number, may be 0-10.
0x10 is your chip i2c address, 0x10 or 0x11.
@andy-shev would you happen to know if there's a way to ignore one of the two addresses in ACPI? see above the DSDT contains two addresses for the same codec, this looks wrong?
@plbossart Thanks for your analysis and support!
@yangxiaohua2009 I have never changed the ACPI and I have to study how to do it. The same i2cdump output for all combinations of bus number 0 to 10 and i2c addresses 0x10 or 0x11.
No size specified (using byte-data access) 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 00: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 70: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 80: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 90: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX a0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX b0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX c0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX d0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX e0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX f0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX
@andy-shev would you happen to know if there's a way to ignore one of the two addresses in ACPI? see above the DSDT contains two addresses for the same codec, this looks wrong?
Why do you think it's a single codec there? We already have an example of two or more codecs in the same device node in ACPI (see serial-multi-instantiate.c for the details). I.o.w. without schematic and datasheet to the codec itself it's hard to say if it's wrong table or driver or something else (might be a multi-functional device, e.g. camera sensor + motion coil + ... but for the audio case).
@andy-shev we've never seen a form-factor device with e.g. two headset codecs and jacks. This sort of low-cost devices only rely on one codec, that's a safe assumption. Put differently, all the existing devices with this ES8336 rely on a single codec so there's no precedent with two.
@andy-shev we've never seen a form-factor device with e.g. two headset codecs and jacks. This sort of low-cost devices only rely on one codec, that's a safe assumption. Put differently, all the existing devices with this ES8336 rely on a single codec so there's no precedent with two.
What about multifunction device then? Is it possible to find a schematic of the board?
@plbossart lt's a longer story behind the two I2C address. We recommand less than two reflow soldering, but the OEM reflow soldering four times. The high temperature causes detachment between bonding wire and the lead frame, making CE pin (I2C address pin) float, so the I2C address becomes float. It may be either 0x10 or 0x11. When they found the problem, tens of thousands has been made so it's impossible to modify the hardware. They then came up with the idea that they can set up two I2C addresses in the ACPI so that the driver can get two I2C addresses. Since at least one of them can work, the CODEC can now work well.
The problem was solved later with new chips, and the problematic chips recalled. As a conclusion, the two I2C addresses is just a way to solve I2C failure and only for the specific model, no need to pay special attention for it.
Thanks for the explanations @yangxiaohua2009.
"the codec works well" might be a true statement for the Windows drivers, it's not true for LInux, as measured by es8316_probe() and es8316_i2c_probe() not being invoked (see results from @tvelazquez above), likely due to an earlier error handling in the ACPI or I2C subsystems.
@jwrdegoede, read above, very interesting case! It also might affect serial-multi-instantiate.c.
@jwrdegoede, read above, very interesting case! It also might affect serial-multi-instantiate.c.
Ugh, this is just so ugly (the 1 codec which will have 1 of 2 possible addresses thing).
So the only way I can come up with to solve this would be to
- Add the ACPI HID for the codec to ignore_serial_bus_idsignore_serial_bus_ids in drivers/acpi/scan.c: acpi_device_enumeration_by_parent()
- Write a new driver binding to the ACPI HID, which checks both addresses and instantiates a codec device for the working one. While passing through the firmware-node as fwnode for the instantiated i2c-client.
Note doing things this way will break ACPI HID based driver <-> device matching. So this will require the codec driver to get an old fashioned i2c_client_id added to it for the binding to still work.
An even uglier alternative would be would be to modify drivers/i2c/i2c-core-acpi.c
to recognize this ACPI HID and then if there is more then 1 i2c address to do some simple i2c connectivity check and then pick the address based on that check.
That even uglier approach is probably easier, so it might be a good way to at least get things to work for @tvelazquez . Although if @plbossart has at least 1 similar device, then implementing the addition to ignore_serial_bus_ids + special driver should not be that much work and it should be testable on a device with just 1 i2cresource in the ACPI table.
A 3th option would be to just use a DSDT overlay and drop the first I2Cresource. But that is not really a generic fix for other users impacted by the same issue.
@jwrdegoede, thanks for your ideas! From hw perspective my understanding is that the floating pin can take any state at any time (especially taking into account temperature differences as cold start), the robust solution is to try two addresses for each transaction, and it sounds to me like a dirty hack in I2C core would be needed. But the more I think about this the more I tend to tell users that this hardware is broken for any sane software.
I tend to agree with @andy-shev, what are the odds that the address used on startup remains functional during a typical 'day use' scenario. In addition I don't have ANY device to test, so can't really help.
@andy-shev you are right about the floating pin being able to take any value, but this is likely a dual-purpose bootstrap + other-purpose pin. So at power-on-reset it gets read once (the bootstrap) to determine the i2c address and that then gets latched and after that the pin switches to its other purpose which is unused in this design.
So the address can be different every boot, but it is stable after boot.
I believe that if each transfer would potentially need a different address that things then would not even work under Windows.
@plbossart ah I assumed you had at least one alderlake device with an es83x6 in there. Yeah without hardware developing a fix is going to be very hard.
Still no luck unfortunately, can't get any sound input/output to work.
@yangxiaohua2009 I compiled https://github.com/thesofproject/linux/tree/es8336-v6.0 and removed the second I2C address, but same results.
[ 0.008024] ACPI: DSDT ACPI table found in initrd [kernel/firmware/acpi/dsdt.aml][0x3b562] [ 0.008074] ACPI: Table Upgrade: override [DSDT-HUAWEI- TGL-ULT] [ 0.008075] ACPI: DSDT 0x0000000075BA2000 Physical table override, new table: 0x0000000072AB2000 [ 0.008076] ACPI: DSDT 0x0000000072AB2000 03B562 (v02 HUAWEI TGL-ULT 00000003 INTL 20220331) [ 21.064509] sof-essx8336 sof-essx8336: quirk mask 0x20 [ 21.064510] sof-essx8336 sof-essx8336: quirk SSP0 [ 21.064510] sof-essx8336 sof-essx8336: quirk DMIC enabled [ 21.064556] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link SSP0-Codec [ 21.064557] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link dmic01 [ 21.064558] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link dmic16k [ 21.064558] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link iDisp1 [ 21.064559] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link iDisp2 [ 21.064559] snd_soc_core:soc_check_tplg_fes: sof-essx8336 sof-essx8336: info: override BE DAI link iDisp3 [ 21.064560] snd_soc_core:snd_soc_add_pcm_runtime: sof-essx8336 sof-essx8336: ASoC: binding SSP0-Codec [ 21.064561] snd_soc_core:soc_dai_link_sanity_check: sof-essx8336 sof-essx8336: ASoC: codec component i2c-ESSX8336:00 not found for link SSP0-Codec [ 21.064563] sof-essx8336 sof-essx8336: snd_soc_register_card failed: -517 [ 21.064660] platform sof-essx8336: deferred probe pending [ 21.064667] i2c i2c-GXTP7863:00: deferred probe pending
It seems that now i2cdump works:
# i2cdump -f -y 1 0x10
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 03 03 00 20 11 00 11 00 00 01 00 00 f8 3f 00 00 ??. ?.?..?..??..
10: 01 fc 28 00 00 33 00 00 88 06 22 03 0f 00 80 80 ??(..3..??"??.??
20: 00 00 c0 00 01 08 10 c0 00 1c 00 b0 32 03 00 11 ..?.????.?.?2?.?
30: 10 00 00 c0 c0 1f f7 fd ff 1f f7 fd ff 1f f7 fd ?..?????.???.???
40: ff 1f f7 fd ff 1f f7 fd ff 1f f7 fd ff 00 00 00 .???.???.???....
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
80: 03 03 00 20 11 00 11 00 00 01 00 00 f8 3f 00 00 ??. ?.?..?..??..
90: 01 fc 28 00 00 33 00 00 88 06 22 03 0f 00 80 80 ??(..3..??"??.??
a0: 00 00 c0 00 01 08 10 c0 00 1c 00 b0 32 03 00 11 ..?.????.?.?2?.?
b0: 10 00 00 c0 c0 1f f7 fd ff 1f f7 fd ff 1f f7 fd ?..?????.???.???
c0: ff 1f f7 fd ff 1f f7 fd ff 1f f7 fd ff 00 00 00 .???.???.???....
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Why is this issue closed?