Skip to content

Getting better range and quality from the WCN6855 Bluetooth chipset

Jens Glathe edited this page Oct 6, 2024 · 1 revision

What this is about

The WCN6855 chipset from Qualcomm is supported on linux with the btqca driver, so you usually get it to run. linux-firmware ships with corresponding firmware. The firmware works, but the available range (and some features regarding audio quality) are varying. With a wide margin. This is due to specific firmware (and probably calibration data) by board revision and SoC type. We try to find these on the Windows partition and provide them to Linux. With the appropriate patch the btqca driver can generate the right firmware name from board id and other parameters and load the "better fitting" firmware. If it's not available, the originally intended firmware is used.

Where to find the missing firmware

On windows these firmware files are part of the driver package and should be located in Windows/System32/DriverStore/FileRepository/ on the Windows partition.

image

As you can see, there's lots of odd named directories in there. The firmware we are looking for is HSP (Headset Profile), and its from Qualcomm, and its Bluetooth, communicating via UART. Depending on the model, not all of these are part of the directory name. So the search might take a few tries to be successful, but looking for qcb* and selecting the newest with at least 10 files in it should do it.

On Windows Dev Kit 2023 it's this:

image

On HP Omnibook X14 it's this:

image

This is the whole Windows driver package. A look into the provided .inf file might be useful to confirm its really a Bluetooth driver, like "Qualcomm(R) Bluetooth UART Transport Driver". From this we need only the hpnv* files, all of them. They should be copied to a firmware path on the linux root partition.

Assuming you're with your terminal in the path where the hpnv* files are, its these commands:

sudo mkdir -p /lib/firmware/updates/qca
sudo cp hpnv* /lib/firmware/updates/qca/

After copying the files over it should look like this:

image

Why this target path?

Linux tries to load firmware from different locations, in a certain order. An example from dmesg:

bluetooth hci0: loading /lib/firmware/updates/6.12.0-061200rc1-x1e-generic/qca/hpbtfw21.tlv failed for no such file or directory.
bluetooth hci0: loading /lib/firmware/updates/qca/hpbtfw21.tlv failed for no such file or directory.
bluetooth hci0: loading /lib/firmware/6.12.0-061200rc1-x1e-generic/qca/hpbtfw21.tlv failed for no such file or directory.
bluetooth hci0: loading /lib/firmware/qca/hpbtfw21.tlv failed for no such file or directory.
bluetooth hci0: loading /lib/firmware/updates/6.12.0-061200rc1-x1e-generic/qca/hpbtfw21.tlv.zst failed for no such file or directory.
bluetooth hci0: loading /lib/firmware/updates/qca/hpbtfw21.tlv.zst failed for no such file or directory.
bluetooth hci0: loading /lib/firmware/6.12.0-061200rc1-x1e-generic/qca/hpbtfw21.tlv.zst failed for no such file or directory.
bluetooth hci0: Loading firmware from /lib/firmware/qca/hpbtfw21.tlv.zst

The order is:

1. firmware/updates/kernel-specific/
2. firmware/updates/
3. firmware/kernel-specific/
4. firmware/

and then again with compressed files. linux-firmware is installed in firmware/, and will be scanned last. If we decide to use firmware/updates, we ensure that our files come first in the search order, and will not be overwritten by updates to linux-firmware.

Check if the specific firmware is loaded

After copying the firmware files and rebooting, we can check if the appropriate firmware was loaded:

jglathe@volterra:~$ sudo dmesg|grep Bluetooth
...
[    9.329392] Bluetooth: hci0: setting up wcn6855
[    9.447444] Bluetooth: hci0: QCA Product ID   :0x00000013
[    9.447452] Bluetooth: hci0: QCA SOC Version  :0x400c1211
[    9.447454] Bluetooth: hci0: QCA ROM Version  :0x00000201
[    9.447456] Bluetooth: hci0: QCA Patch Version:0x000038e6
[    9.455221] Bluetooth: hci0: QCA controller version 0x12110201
[    9.455230] Bluetooth: hci0: QCA Downloading qca/hpbtfw21.tlv
[   10.099353] Bluetooth: hci0: QCA Downloading qca/hpnv21g.bin
[   10.259683] Bluetooth: hci0: QCA setup on UART is completed
...

The mask for the "g" suffix in the name is 0x1200 which is the case here. The board ID on this machine is actually 0 (not shown), but that's why the default hpnv21g.bin is loaded.

Upstreaming considerations

The patch has been sent to the kernel mailing list as PATCH RFC. Let's see what happens, since it is using firmware that is not in linux-firmware. The patch is also present in this repository and will be in builds since 6.12-rc1.