* [PATCH v2 1/8] Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support
2026-03-25 23:30 [PATCH v2 0/8] Bluetooth: Add MediaTek MT7927 (MT6639) support Javier Tia
@ 2026-03-25 23:30 ` Javier Tia
2026-03-26 5:05 ` Sean Wang
0 siblings, 1 reply; 3+ messages in thread
From: Javier Tia @ 2026-03-25 23:30 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: linux-bluetooth, linux-kernel, linux-arm-kernel, linux-mediatek,
Ryan Gilbert
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@gmail.com>
Signed-off-by: Javier Tia <floss@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;
+ }
+
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"
#define HCI_EV_WMT 0xe4
#define HCI_WMT_MAX_EVENT_SIZE 64
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2 1/8] Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support
2026-03-25 23:30 ` [PATCH v2 1/8] Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support Javier Tia
@ 2026-03-26 5:05 ` Sean Wang
0 siblings, 0 replies; 3+ messages in thread
From: Sean Wang @ 2026-03-26 5:05 UTC (permalink / raw)
To: Javier Tia
Cc: Marcel Holtmann, Luiz Augusto von Dentz, Matthias Brugger,
AngeloGioacchino Del Regno, linux-bluetooth, linux-kernel,
linux-arm-kernel, linux-mediatek, Ryan Gilbert
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@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@gmail.com>
> Signed-off-by: Javier Tia <floss@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
>
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2 1/8] Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support
@ 2026-03-26 21:26 Javier Tia
0 siblings, 0 replies; 3+ messages in thread
From: Javier Tia @ 2026-03-26 21:26 UTC (permalink / raw)
To: Sean Wang
Cc: Marcel Holtmann, Luiz Augusto von Dentz, Matthias Brugger,
AngeloGioacchino Del Regno, linux-bluetooth, linux-kernel,
linux-arm-kernel, linux-mediatek, Ryan Gilbert
Hi Sean,
Thank you for the review. Both items are addressed in v3.
On Wed, Mar 26, 2026 Sean Wang wrote:
> 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.
Agreed. In v3, the zero-CHIPID fallback is scoped to a static
VID/PID table of known MT6639 USB devices. Only those specific
devices get forced to 0x6639 - any other device reading zero will
fall through to the default "unsupported hardware" path. This
follows the WiFi-side pattern where is_mt7927_hw is derived from
the PCI device table, not the chip register.
> I would prefer using the mediatek/mt7927/ folder naming here. mt7927
> is more widely recognized, and using it would avoid unnecessary
> confusion.
Done. The firmware path is now mediatek/mt7927/ in both the
FIRMWARE_MT7927 define and btmtk_fw_get_filename(). This matches
the WiFi firmware convention (mediatek/mt7927/WIFI_RAM_CODE_...).
The linux-firmware MR !946 has also been updated to use the
mt7927 directory.
v3 sent with these changes:
https://lore.kernel.org/linux-bluetooth/20260326-mt7927-bt-support-v3-0-fa7ebd424323@jetm.me/T/#t
Best,
Javier
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-03-26 22:13 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-26 21:26 [PATCH v2 1/8] Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support Javier Tia
-- strict thread matches above, loose matches on Subject: below --
2026-03-25 23:30 [PATCH v2 0/8] Bluetooth: Add MediaTek MT7927 (MT6639) support Javier Tia
2026-03-25 23:30 ` [PATCH v2 1/8] Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support Javier Tia
2026-03-26 5:05 ` Sean Wang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox