[PATCH 1/2] Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support
Sean Wang
sean.wang at kernel.org
Sat Mar 7 08:03:02 PST 2026
Hi Javier,
On Thu, Mar 5, 2026 at 10:33 AM Javier Tia <floss at jetm.me> wrote:
>
> The MediaTek MT7927 (Filogic 380) combo WiFi 7 + BT 5.4 module uses
> hardware variant 0x6639 for its Bluetooth subsystem. Without this patch,
> the chip fails with "Unsupported hardware variant (00006639)" or hangs
> during firmware download.
>
> Three changes are needed to support MT6639:
>
> 1. Firmware naming: MT6639 uses firmware version prefix "2_1" instead of
> "1_1" used by MT7925 and other variants. The firmware path is
> mediatek/mt6639/BT_RAM_CODE_MT6639_2_1_hdr.bin.
>
> 2. Section filtering: The MT6639 firmware binary contains 9 sections, but
> only sections with (dlmodecrctype & 0xff) == 0x01 are Bluetooth-related.
> Sending the remaining WiFi/other sections causes an irreversible BT
> subsystem hang requiring a full power cycle. This matches the Windows
> driver behavior observed via USB captures.
>
> 3. Firmware persistence: MT6639 firmware persists across BT soft power
> cycles (WMT_FUNC_CTRL=0 does not clear firmware). Skip re-download on
> subsequent setups to avoid a ~2.6s delay on each BT power toggle.
>
> Also add 0x6639 to the reset register (CONNV3) and firmware setup switch
> cases alongside the existing 0x7925 handling.
>
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=221096
> Link: https://github.com/openwrt/mt76/issues/927
> Assisted-by: Claude Code <noreply at anthropic.com> [claude-opus-4-6]
> Signed-off-by: Javier Tia <floss at jetm.me>
> ---
> drivers/bluetooth/btmtk.c | 32 ++++++++++++++++++++++++++++++--
> drivers/bluetooth/btmtk.h | 1 +
> 2 files changed, 31 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
> index 2507d587f28a..3821fde9e361 100644
> --- a/drivers/bluetooth/btmtk.c
> +++ b/drivers/bluetooth/btmtk.c
> @@ -112,7 +112,11 @@ static void btmtk_coredump_notify(struct hci_dev *hdev, int state)
> void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver,
> u32 fw_flavor)
> {
> - if (dev_id == 0x7925)
> + if (dev_id == 0x6639)
> + snprintf(buf, size,
> + "mediatek/mt%04x/BT_RAM_CODE_MT%04x_2_%x_hdr.bin",
> + dev_id & 0xffff, dev_id & 0xffff, (fw_ver & 0xff) + 1);
> + else if (dev_id == 0x7925)
> snprintf(buf, size,
> "mediatek/mt%04x/BT_RAM_CODE_MT%04x_1_%x_hdr.bin",
> dev_id & 0xffff, dev_id & 0xffff, (fw_ver & 0xff) + 1);
> @@ -130,6 +134,7 @@ EXPORT_SYMBOL_GPL(btmtk_fw_get_filename);
> int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
> wmt_cmd_sync_func_t wmt_cmd_sync)
> {
> + struct btmtk_data *data = hci_get_priv(hdev);
> struct btmtk_hci_wmt_params wmt_params;
> struct btmtk_patch_header *hdr;
> struct btmtk_global_desc *globaldesc = NULL;
> @@ -166,6 +171,14 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
> section_offset = le32_to_cpu(sectionmap->secoffset);
> dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize);
>
> + /* MT6639: only download sections where dlmode byte0 == 0x01,
> + * matching the Windows driver behavior which skips WiFi/other
> + * sections that would cause the chip to hang.
> + */
BT and WiFi use separate firmware.
I’m not sure why those WiFi sections are included in the binary.
Another concern is whether it is appropriate to upload the firmware
used in Windows to the linux-firmware repository,
The firmware files are probably intended for dedicated OEMs.
> + if (data->dev_id == 0x6639 && dl_size > 0 &&
> + (le32_to_cpu(sectionmap->bin_info_spec.dlmodecrctype) & 0xff) != 0x01)
> + continue;
> +
> if (dl_size > 0) {
> retry = 20;
> while (retry > 0) {
> @@ -852,7 +865,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
> if (err < 0)
> return err;
> msleep(100);
> - } else if (dev_id == 0x7925) {
> + } else if (dev_id == 0x7925 || dev_id == 0x6639) {
> err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
> if (err < 0)
> return err;
> @@ -1339,9 +1352,20 @@ int btmtk_usb_setup(struct hci_dev *hdev)
> case 0x7925:
> case 0x7961:
> case 0x7902:
> + case 0x6639:
> btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id,
> fw_version, fw_flavor);
>
> + /* MT6639: firmware persists across BT soft power cycles
> + * (shutdown only sends WMT_FUNC_CTRL=0). Skip re-download
> + * on subsequent setups to avoid ~2.6s delay.
> + */
This is common logic for the other mediatek chips. It only takes
longer on the first power-on.
> + if (dev_id == 0x6639 &&
> + test_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags)) {
> + bt_dev_info(hdev, "MT6639: firmware already loaded, skipping download");
> + goto skip_fw_setup_79xx;
> + }
> +
> err = btmtk_setup_firmware_79xx(hdev, fw_bin_name,
> btmtk_usb_hci_wmt_sync);
> if (err < 0) {
> @@ -1352,6 +1376,10 @@ int btmtk_usb_setup(struct hci_dev *hdev)
> return err;
> }
>
> + if (dev_id == 0x6639)
> + set_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags);
If the firmware download is properly handled in
btmtk_setup_firmware_79xx, we don't need the extra bit.
> +
> +skip_fw_setup_79xx:
> /* It's Device EndPoint Reset Option Register */
> err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT,
> MTK_EP_RST_IN_OUT_OPT);
> diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
> index adaf385626ee..6645bcadb523 100644
> --- a/drivers/bluetooth/btmtk.h
> +++ b/drivers/bluetooth/btmtk.h
> @@ -8,6 +8,7 @@
> #define FIRMWARE_MT7902 "mediatek/BT_RAM_CODE_MT7902_1_1_hdr.bin"
> #define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
> #define FIRMWARE_MT7925 "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin"
> +#define FIRMWARE_MT7927 "mediatek/mt6639/BT_RAM_CODE_MT6639_2_1_hdr.bin"
>
> #define HCI_EV_WMT 0xe4
> #define HCI_WMT_MAX_EVENT_SIZE 64
> --
> 2.53.0
>
More information about the Linux-mediatek
mailing list