/* It is for mt79xx iso data transmission setting */
#define MTK_ISO_THRESHOLD 264
+/* Known MT6639 (MT7927) Bluetooth USB devices.
+ * Used to scope the zero-CHIPID workaround to real MT6639 hardware,
+ * since some boards return 0x0000 from the MMIO chip ID register.
+ */
+static const struct {
+ u16 vendor;
+ u16 product;
+} btmtk_mt6639_devs[] = {
+ { 0x0489, 0xe13a }, /* ASUS ROG Crosshair X870E Hero */
+ { 0x0489, 0xe0fa }, /* Lenovo Legion Pro 7 16ARX9 */
+ { 0x0489, 0xe10f }, /* Gigabyte Z790 AORUS MASTER X */
+ { 0x0489, 0xe110 }, /* MSI X870E Ace Max */
+ { 0x0489, 0xe116 }, /* TP-Link Archer TBE550E */
+ { 0x13d3, 0x3588 }, /* ASUS ROG STRIX X870E-E */
+};
+
struct btmtk_patch_header {
u8 datetime[16];
u8 platform[4];
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/mt7927/BT_RAM_CODE_MT%04x_2_%x_hdr.bin",
+ 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);
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)
+ wmt_cmd_sync_func_t wmt_cmd_sync,
+ u32 dev_id)
{
struct btmtk_hci_wmt_params wmt_params;
struct btmtk_patch_header *hdr;
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 (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) {
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;
}
err = btmtk_usb_id_get(hdev, 0x70010200, &val);
- if (err < 0 || !val)
+ if (err < 0 || (!val && dev_id != 0x6639))
bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
return err;
fw_flavor = (fw_flavor & 0x00000080) >> 7;
}
+ if (!dev_id) {
+ u16 vid = le16_to_cpu(btmtk_data->udev->descriptor.idVendor);
+ u16 pid = le16_to_cpu(btmtk_data->udev->descriptor.idProduct);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(btmtk_mt6639_devs); i++) {
+ if (vid == btmtk_mt6639_devs[i].vendor &&
+ pid == btmtk_mt6639_devs[i].product) {
+ dev_id = 0x6639;
+ break;
+ }
+ }
+
+ if (dev_id)
+ bt_dev_info(hdev, "MT6639: CHIPID=0x0000 with VID=%04x PID=%04x, using 0x6639",
+ vid, pid);
+ }
+
btmtk_data->dev_id = dev_id;
err = btmtk_register_coredump(hdev, btmtk_data->drv_name, fw_version);
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);
err = btmtk_setup_firmware_79xx(hdev, fw_bin_name,
- btmtk_usb_hci_wmt_sync);
+ btmtk_usb_hci_wmt_sync,
+ dev_id);
if (err < 0) {
/* retry once if setup firmware error */
if (!test_and_set_bit(BTMTK_FIRMWARE_DL_RETRY, &btmtk_data->flags))
MODULE_FIRMWARE(FIRMWARE_MT7922);
MODULE_FIRMWARE(FIRMWARE_MT7961);
MODULE_FIRMWARE(FIRMWARE_MT7925);
+MODULE_FIRMWARE(FIRMWARE_MT7927);
#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/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin"
#define HCI_EV_WMT 0xe4
#define HCI_WMT_MAX_EVENT_SIZE 64
int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
- wmt_cmd_sync_func_t wmt_cmd_sync);
+ wmt_cmd_sync_func_t wmt_cmd_sync,
+ u32 dev_id);
int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
wmt_cmd_sync_func_t wmt_cmd_sync);
static inline int btmtk_setup_firmware_79xx(struct hci_dev *hdev,
const char *fwname,
- wmt_cmd_sync_func_t wmt_cmd_sync)
+ wmt_cmd_sync_func_t wmt_cmd_sync,
+ u32 dev_id)
{
return -EOPNOTSUPP;
}