[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