MLME_LINKED,
 };
 
-#define FCXONESLOT_VER 1
 struct btc_fbtc_1slot {
        u8 fver;
        u8 sid; /* slot id */
        struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
 } __packed;
 
+struct rtw89_btc_btf_set_slot_table_v7 {
+       u8 type;
+       u8 ver;
+       u8 len;
+       struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
+} __packed;
+
 struct rtw89_btc_btf_set_mon_reg {
        u8 fver;
        u8 reg_num;
                break;
        case BTC_RPT_TYPE_SLOT:
                pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
-               pfinfo = &pfwinfo->rpt_fbtc_slots.finfo;
-               pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo);
+               if (ver->fcxslots == 1) {
+                       pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
+                       pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1);
+               } else if (ver->fcxslots == 7) {
+                       pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
+                       pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7);
+               } else {
+                       goto err;
+               }
                pcinfo->req_fver = ver->fcxslots;
                break;
        case BTC_RPT_TYPE_CYSTA:
                        goto err;
                break;
        case BTC_RPT_TYPE_SLOT:
-               rtw89_debug(rtwdev, RTW89_DBG_BTC,
-                           "[BTC], %s(): check %d %zu\n",
-                           __func__, BTC_DCNT_SLOT_NONSYNC,
-                           sizeof(dm->slot_now));
-               _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
-                            memcmp(dm->slot_now,
-                                   pfwinfo->rpt_fbtc_slots.finfo.slot,
-                                   sizeof(dm->slot_now)));
+               if (ver->fcxslots == 7) {
+                       rtw89_debug(rtwdev, RTW89_DBG_BTC,
+                                   "[BTC], %s(): check %d %zu\n",
+                                   __func__, BTC_DCNT_SLOT_NONSYNC,
+                                   sizeof(dm->slot_now.v7));
+                       _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
+                                    memcmp(dm->slot_now.v7,
+                                           pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
+                                           sizeof(dm->slot_now.v7)));
+               } else if (ver->fcxslots == 1) {
+                       rtw89_debug(rtwdev, RTW89_DBG_BTC,
+                                   "[BTC], %s(): check %d %zu\n",
+                                   __func__, BTC_DCNT_SLOT_NONSYNC,
+                                   sizeof(dm->slot_now.v1));
+                       _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
+                                    memcmp(dm->slot_now.v1,
+                                           pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
+                                           sizeof(dm->slot_now.v1)));
+               }
                break;
        case BTC_RPT_TYPE_CYSTA:
                if (ver->fcxcysta == 2) {
 
                        /* Check diff time between WL slot and W1/E2G slot */
                        if (dm->tdma_now.type == CXTDMA_OFF &&
-                           dm->tdma_now.ext_ctrl == CXECTL_EXT)
-                               wl_slot_set = le16_to_cpu(dm->slot_now[CXST_E2G].dur);
-                       else
-                               wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
+                           dm->tdma_now.ext_ctrl == CXECTL_EXT) {
+                               if (ver->fcxslots == 1)
+                                       wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
+                               else if (ver->fcxslots == 7)
+                                       wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
+                       } else {
+                               if (ver->fcxslots == 1)
+                                       wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
+                               else if (ver->fcxslots == 7)
+                                       wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
+                       }
 
                        if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
                                diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
 
                        /* Check diff time between real WL slot and W1 slot */
                        if (dm->tdma_now.type == CXTDMA_OFF) {
-                               wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
+                               if (ver->fcxslots == 1)
+                                       wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
+                               else if (ver->fcxslots == 7)
+                                       wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
                                wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
                                if (wl_slot_real > wl_slot_set) {
                                        diff_t = wl_slot_real - wl_slot_set;
 
                        /* Check diff time between real WL slot and W1 slot */
                        if (dm->tdma_now.type == CXTDMA_OFF) {
-                               wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
+                               if (ver->fcxslots == 1)
+                                       wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
+                               else if (ver->fcxslots == 7)
+                                       wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
                                wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
                                if (wl_slot_real > wl_slot_set) {
                                        diff_t = wl_slot_real - wl_slot_set;
 
                        /* Check diff time between real WL slot and W1 slot */
                        if (dm->tdma_now.type == CXTDMA_OFF) {
-                               wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
+                               if (ver->fcxslots == 1)
+                                       wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
+                               else if (ver->fcxslots == 7)
+                                       wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
                                wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);
 
                                if (wl_slot_real > wl_slot_set)
                    dm->tdma.ext_ctrl);
 }
 
-static void _append_slot(struct rtw89_dev *rtwdev)
+static void _append_slot_v1(struct rtw89_dev *rtwdev)
 {
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_dm *dm = &btc->dm;
 
        for (i = 0; i < CXST_MAX; i++) {
                if (!btc->update_policy_force &&
-                   !memcmp(&dm->slot[i], &dm->slot_now[i],
-                           sizeof(dm->slot[i])))
+                   !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i],
+                           sizeof(dm->slot.v1[i])))
                        continue;
 
                len = btc->policy_len;
                tlv->type = CXPOLICY_SLOT;
                tlv->len = sizeof(*v);
 
-               v->fver = FCXONESLOT_VER;
+               v->fver = btc->ver->fcxslots;
                v->sid = i;
-               v->slot = dm->slot[i];
+               v->slot = dm->slot.v1[i];
 
                rtw89_debug(rtwdev, RTW89_DBG_BTC,
                            "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
-                           __func__, i, dm->slot[i].dur, dm->slot[i].cxtbl,
-                           dm->slot[i].cxtype);
+                           __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl,
+                           dm->slot.v1[i].cxtype);
                cnt++;
 
                btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v);
                            __func__, cnt);
 }
 
+static void _append_slot_v7(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_btc_btf_tlv_v7 *tlv = NULL;
+       struct rtw89_btc *btc = &rtwdev->btc;
+       struct rtw89_btc_dm *dm = &btc->dm;
+       u8 i, cnt = 0;
+       u16 len;
+
+       for (i = 0; i < CXST_MAX; i++) {
+               if (!btc->update_policy_force &&
+                   !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i],
+                           sizeof(dm->slot.v7[i])))
+                       continue;
+
+               len = btc->policy_len;
+
+               if (!tlv) {
+                       if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) {
+                               rtw89_debug(rtwdev, RTW89_DBG_BTC,
+                                           "[BTC], %s(): buff overflow!\n", __func__);
+                               break;
+                       }
+
+                       tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
+                       tlv->type = CXPOLICY_SLOT;
+                       tlv->ver = btc->ver->fcxslots;
+                       tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7;
+                       len += BTC_TLV_HDR_LEN_V7;
+               }
+
+               if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) {
+                       rtw89_debug(rtwdev, RTW89_DBG_BTC,
+                                   "[BTC], %s(): buff overflow!\n", __func__);
+                       break;
+               }
+
+               btc->policy[len] = i; /* slot-id */
+               memcpy(&btc->policy[len + 1], &dm->slot.v7[i],
+                      sizeof(dm->slot.v7[0]));
+               len += tlv->len;
+
+               rtw89_debug(rtwdev, RTW89_DBG_BTC,
+                           "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n",
+                           __func__, btc->policy_len, i, dm->slot.v7[i].dur,
+                           dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl);
+               cnt++;
+               btc->policy_len = len; /* update total length */
+       }
+
+       if (cnt > 0)
+               rtw89_debug(rtwdev, RTW89_DBG_BTC,
+                           "[BTC], %s: slot update (cnt=%d, len=%d)!!\n",
+                           __func__, cnt, btc->policy_len);
+}
+
+static void _append_slot(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_btc *btc = &rtwdev->btc;
+
+       if (btc->ver->fcxslots == 7)
+               _append_slot_v7(rtwdev);
+       else
+               _append_slot_v1(rtwdev);
+}
+
 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
 {
        struct rtw89_btc *btc = &rtwdev->btc;
        return bit_map;
 }
 
+static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_btc *btc = &rtwdev->btc;
+       const struct rtw89_btc_ver *ver = btc->ver;
+       struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL;
+       struct rtw89_btc_btf_set_slot_table *tbl;
+       struct rtw89_btc_dm *dm = &btc->dm;
+       u16 n, len;
+
+       if (ver->fcxslots == 7) {
+               len = sizeof(*tlv_v7) + sizeof(dm->slot.v7);
+               tlv_v7 = kmalloc(len, GFP_KERNEL);
+               if (!tlv_v7)
+                       return;
+
+               tlv_v7->type = SET_SLOT_TABLE;
+               tlv_v7->ver = ver->fcxslots;
+               tlv_v7->len = sizeof(dm->slot.v7);
+               memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7));
+
+               _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len);
+
+               kfree(tlv_v7);
+       } else {
+               n = struct_size(tbl, tbls, CXST_MAX);
+               tbl = kmalloc(n, GFP_KERNEL);
+               if (!tbl)
+                       return;
+
+               tbl->fver = BTF_SET_SLOT_TABLE_VER;
+               tbl->tbl_num = CXST_MAX;
+               memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX));
+
+               _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
+
+               kfree(tbl);
+       }
+}
+
 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
                                u32 rpt_map, bool rpt_state)
 {
                fwinfo->rpt_en_map = val;
 }
 
-static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev, u8 num,
-                                  struct rtw89_btc_fbtc_slot *s)
-{
-       struct rtw89_btc_btf_set_slot_table *tbl;
-       u16 n;
-
-       n = struct_size(tbl, tbls, num);
-       tbl = kmalloc(n, GFP_KERNEL);
-       if (!tbl)
-               return;
-
-       tbl->fver = BTF_SET_SLOT_TABLE_VER;
-       tbl->tbl_num = num;
-       memcpy(tbl->tbls, s, flex_array_size(tbl, tbls, num));
-
-       _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
-
-       kfree(tbl);
-}
-
 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
 {
        const struct rtw89_chip_info *chip = rtwdev->chip;
                           btc->policy, btc->policy_len);
        if (!ret) {
                memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
-               memcpy(&dm->slot_now, &dm->slot, sizeof(dm->slot_now));
+               if (btc->ver->fcxslots == 7)
+                       memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7));
+               else
+                       memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1));
        }
 
        if (btc->update_policy_force)
 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
 
-#define _slot_set(btc, sid, dura, tbl, type) \
-       do { \
-               typeof(sid) _sid = (sid); \
-               typeof(btc) _btc = (btc); \
-               _btc->dm.slot[_sid].dur = cpu_to_le16(dura);\
-               _btc->dm.slot[_sid].cxtbl = cpu_to_le32(tbl); \
-               _btc->dm.slot[_sid].cxtype = cpu_to_le16(type); \
-       } while (0)
-
-#define _slot_set_dur(btc, sid, dura) (btc)->dm.slot[sid].dur = cpu_to_le16(dura)
-#define _slot_set_tbl(btc, sid, tbl) (btc)->dm.slot[sid].cxtbl = cpu_to_le32(tbl)
-#define _slot_set_type(btc, sid, type) (btc)->dm.slot[sid].cxtype = cpu_to_le16(type)
-
 struct btc_btinfo_lb2 {
        u8 connect: 1;
        u8 sco_busy: 1;
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_dm *dm = &btc->dm;
        struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
-       struct rtw89_btc_fbtc_slot *s = dm->slot;
+       struct rtw89_btc_fbtc_slot *s = dm->slot.v1;
        u8 type;
        u32 tbl_w1, tbl_b1, tbl_b4;
 
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_dm *dm = &btc->dm;
        struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
-       struct rtw89_btc_fbtc_slot *s = dm->slot;
        struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
        struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
        struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
        case BTC_CXP_USERDEF0:
                btc->update_policy_force = true;
                *t = t_def[CXTD_OFF];
-               s[CXST_OFF] = s_def[CXST_OFF];
+               _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
+                            s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
                _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
                break;
        case BTC_CXP_OFF: /* TDMA off */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
                *t = t_def[CXTD_OFF];
-               s[CXST_OFF] = s_def[CXST_OFF];
+               _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
+                            s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
 
                switch (policy_type) {
                case BTC_CXP_OFF_BT:
        case BTC_CXP_OFFB: /* TDMA off + beacon protect */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
                *t = t_def[CXTD_OFF_B2];
-               s[CXST_OFF] = s_def[CXST_OFF];
+               _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
+                            s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
 
                switch (policy_type) {
                case BTC_CXP_OFFB_BWB0:
 
                switch (policy_type) {
                case BTC_CXP_OFFE_DEF:
-                       s[CXST_E2G] = s_def[CXST_E2G];
-                       s[CXST_E5G] = s_def[CXST_E5G];
-                       s[CXST_EBT] = s_def[CXST_EBT];
-                       s[CXST_ENULL] = s_def[CXST_ENULL];
+                       _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
+                                    s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
+                       _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
+                                    s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
+                       _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
+                                    s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
+                       _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
+                                    s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
                        break;
                case BTC_CXP_OFFE_DEF2:
                        _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
-                       s[CXST_E5G] = s_def[CXST_E5G];
-                       s[CXST_EBT] = s_def[CXST_EBT];
-                       s[CXST_ENULL] = s_def[CXST_ENULL];
+                       _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
+                                    s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
+                       _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
+                                    s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
+                       _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
+                                    s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
                        break;
                default:
                        break;
                }
-               s[CXST_OFF] = s_def[CXST_OFF];
+               _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
+                            s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
                break;
        case BTC_CXP_FIX: /* TDMA Fix-Slot */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 
        _set_init_info(rtwdev);
        _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
-       rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot);
        btc_fw_set_monreg(rtwdev);
+       rtw89_btc_fw_set_slots(rtwdev);
        _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
        _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
 
 {
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_dm *dm = &btc->dm;
-       struct rtw89_btc_fbtc_slot *s;
+       u16 dur, cxtype;
+       u32 tbl;
        u8 i = 0;
 
        for (i = 0; i < CXST_MAX; i++) {
-               s = &dm->slot_now[i];
+               if (btc->ver->fcxslots == 1) {
+                       dur = le16_to_cpu(dm->slot_now.v1[i].dur);
+                       tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
+                       cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
+               } else if (btc->ver->fcxslots == 7) {
+                       dur = le16_to_cpu(dm->slot_now.v7[i].dur);
+                       tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
+                       cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
+               } else {
+                       return;
+               }
+
                if (i % 5 == 0)
                        seq_printf(m,
                                   " %-15s : %5s[%03d/0x%x/%d]",
                                   "[slot_list]",
                                   id_to_slot((u32)i),
-                                  s->dur, s->cxtbl, s->cxtype);
+                                  dur, tbl, cxtype);
                else
                        seq_printf(m,
                                   ", %5s[%03d/0x%x/%d]",
                                   id_to_slot((u32)i),
-                                  s->dur, s->cxtbl, s->cxtype);
+                                  dur, tbl, cxtype);
+
                if (i % 5 == 4)
                        seq_puts(m, "\n");
        }