[PATCH v2 1/8] Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support

Sean Wang sean.wang at kernel.org
Wed Mar 25 22:05:11 PDT 2026


Hi, Javier

This is already a clear improvement over the previous version, but I
think there are still a few areas that could be refined further.

On Wed, Mar 25, 2026 at 6:33 PM 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. CHIPID workaround: On some boards the BT USB MMIO register reads
>    0x0000 for dev_id, causing the driver to skip the 0x6639 init path.
>    Force dev_id to 0x6639 when it reads zero, matching the equivalent
>    WiFi-side workaround that forces chip=0x7927.
>
> 2. 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.
>
> 3. 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.
>
> 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
> Reported-by: Ryan Gilbert <xelnaga at gmail.com>
> Signed-off-by: Javier Tia <floss at jetm.me>
> ---
>  drivers/bluetooth/btmtk.c | 23 +++++++++++++++++++++--
>  drivers/bluetooth/btmtk.h |  1 +
>  2 files changed, 22 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
> index 2507d587f28a..13c6e45deede 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.
> +                */
> +               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;
> @@ -1322,6 +1335,11 @@ int btmtk_usb_setup(struct hci_dev *hdev)
>                 fw_flavor = (fw_flavor & 0x00000080) >> 7;
>         }
>
> +       if (!dev_id) {
> +               bt_dev_info(hdev, "MT6639: raw CHIPID=0x0000, forcing chip=0x6639");
> +               dev_id = 0x6639;
> +       }

Using raw CHIPID=0x0000 to unconditionally force 0x6639 seems fragile.
If another device later hits the same missing-ID condition, it would
also be misdetected as MT6639. Normally this kind of quirk could be
carried in .driver_data, but since btusb.c is shared, I'm not sure
that is the right fit here either. This should probably be handled
through a more device-specific fallback instead of mapping all zero
CHIPID cases to 0x6639.

> +
>         btmtk_data->dev_id = dev_id;
>
>         err = btmtk_register_coredump(hdev, btmtk_data->drv_name, fw_version);
> @@ -1339,6 +1357,7 @@ 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);
>
> 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"

Sorry I did not respond to this earlier.
I would prefer using the mediatek/mt7927/ folder naming here. mt7927
is more widely recognized, and using it would avoid unnecessary
confusion.

>
>  #define HCI_EV_WMT 0xe4
>  #define HCI_WMT_MAX_EVENT_SIZE         64
>
> --
> 2.53.0
>
>



More information about the Linux-mediatek mailing list