Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtw88: 8723d: Add power tracking

When chip's temperature is changed, RF characters are changed. To keep the
characters to be consistent, 8723d uses thermal meter to assist in
calibrating LCK, IQK, crystal and TX power.

A base thermal value is programmed in efuse, all calibration data in
MP process is based on this thermal value. So we calucate the delta of
thermal value between the base value, and use this delta to reference XTAL
and TX power offset tables to know how much we need to adjust.

For IQK and LCK, driver checks if delta of thermal value is over 8, then
they are triggered.

For crystal adjustment, when delta of thermal value is changed, we check
XTAL tables to get offset of XTAL value. If thermal value is larger than
base value, positive table (_p as suffix) is used. Otherwise, we use
negative table (_n as suffix). Then, we add offset to XTAL default value
programmed in efuse, and write sum value to register.

To compensate TX power, there are two hierarchical tables. First level use
delta of thermal value to access eight tables to yield delta of TX power
index. Then, plus base TX power index to get index of BB swing table
(second level tables) where register value is induced.

BB swing table can't deal with all cases, if index of BB swing table is
over the size of the table. In this case, TX AGC is used to compensate the
remnant part. Assume 'upper' is the upper bound of BB swing table, and
'target' is the desired index. Then, we can illustrate them as

compensation method BB swing TX AGC
------------------- -------- --------------
target > upper upper target - upper
target < 0 0 target
otherwise target 0

For debug purpose, add a column 'rem' to tx_pwr_tbl entry, and it looks
like

path rate pwr base (byr lmt ) rem
A CCK_1M 32(0x20) 34 -2 ( 0 -2) 0

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200512102621.5148-4-yhchuang@realtek.com

authored by

Ping-Ke Shih and committed by
Kalle Valo
608d2a08 1d229e88

+422 -5
+5 -4
drivers/net/wireless/realtek/rtw88/debug.c
··· 531 531 u8 ch = hal->current_channel; 532 532 u8 regd = rtwdev->regd.txpwr_regd; 533 533 534 - seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s)\n", 535 - "path", "rate", "pwr", "", "base", "", "byr", "lmt"); 534 + seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s) %-4s\n", 535 + "path", "rate", "pwr", "", "base", "", "byr", "lmt", "rem"); 536 536 537 537 mutex_lock(&hal->tx_power_mutex); 538 538 for (path = RF_PATH_A; path <= RF_PATH_B; path++) { ··· 554 554 555 555 seq_printf(m, "%4c ", path + 'A'); 556 556 rtw_print_rate(m, rate); 557 - seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d)\n", 557 + seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d) %4d\n", 558 558 hal->tx_pwr_tbl[path][rate], 559 559 hal->tx_pwr_tbl[path][rate], 560 560 pwr_param.pwr_base, 561 561 min_t(s8, pwr_param.pwr_offset, 562 562 pwr_param.pwr_limit), 563 - pwr_param.pwr_offset, pwr_param.pwr_limit); 563 + pwr_param.pwr_offset, pwr_param.pwr_limit, 564 + pwr_param.pwr_remnant); 564 565 } 565 566 } 566 567
+4
drivers/net/wireless/realtek/rtw88/main.h
··· 1056 1056 const u8 *pwrtrk_2g_cckb_p; 1057 1057 const u8 *pwrtrk_2g_ccka_n; 1058 1058 const u8 *pwrtrk_2g_ccka_p; 1059 + const s8 *pwrtrk_xtal_n; 1060 + const s8 *pwrtrk_xtal_p; 1059 1061 }; 1060 1062 1061 1063 enum rtw_wlan_cpu { ··· 1449 1447 bool pwr_trk_triggered; 1450 1448 bool pwr_trk_init_trigger; 1451 1449 struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX]; 1450 + s8 txagc_remnant_cck; 1451 + s8 txagc_remnant_ofdm; 1452 1452 1453 1453 /* backup dack results for each path and I/Q */ 1454 1454 u32 dack_adck[RTW_RF_PATH_MAX];
+5 -1
drivers/net/wireless/realtek/rtw88/phy.c
··· 1785 1785 u8 ch, u8 regd, struct rtw_power_params *pwr_param) 1786 1786 { 1787 1787 struct rtw_hal *hal = &rtwdev->hal; 1788 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 1788 1789 struct rtw_txpwr_idx *pwr_idx; 1789 1790 u8 group, band; 1790 1791 u8 *base = &pwr_param->pwr_base; 1791 1792 s8 *offset = &pwr_param->pwr_offset; 1792 1793 s8 *limit = &pwr_param->pwr_limit; 1794 + s8 *remnant = &pwr_param->pwr_remnant; 1793 1795 1794 1796 pwr_idx = &rtwdev->efuse.txpwr_idx_table[path]; 1795 1797 group = rtw_get_channel_group(ch); ··· 1813 1811 1814 1812 *limit = rtw_phy_get_tx_power_limit(rtwdev, band, bw, path, 1815 1813 rate, ch, regd); 1814 + *remnant = (rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck : 1815 + dm_info->txagc_remnant_ofdm); 1816 1816 } 1817 1817 1818 1818 u8 ··· 1834 1830 if (rtwdev->chip->en_dis_dpd) 1835 1831 offset += rtw_phy_get_dis_dpd_by_rate_diff(rtwdev, rate); 1836 1832 1837 - tx_power += offset; 1833 + tx_power += offset + pwr_param.pwr_remnant; 1838 1834 1839 1835 if (tx_power > rtwdev->chip->max_power_index) 1840 1836 tx_power = rtwdev->chip->max_power_index;
+1
drivers/net/wireless/realtek/rtw88/phy.h
··· 141 141 u8 pwr_base; 142 142 s8 pwr_offset; 143 143 s8 pwr_limit; 144 + s8 pwr_remnant; 144 145 }; 145 146 146 147 void
+400
drivers/net/wireless/realtek/rtw88/rtw8723d.c
··· 92 92 rtw_write8(rtwdev, REG_TXPAUSE, 0x00); 93 93 } 94 94 95 + static const u32 rtw8723d_ofdm_swing_table[] = { 96 + 0x0b40002d, 0x0c000030, 0x0cc00033, 0x0d800036, 0x0e400039, 0x0f00003c, 97 + 0x10000040, 0x11000044, 0x12000048, 0x1300004c, 0x14400051, 0x15800056, 98 + 0x16c0005b, 0x18000060, 0x19800066, 0x1b00006c, 0x1c800072, 0x1e400079, 99 + 0x20000080, 0x22000088, 0x24000090, 0x26000098, 0x288000a2, 0x2ac000ab, 100 + 0x2d4000b5, 0x300000c0, 0x32c000cb, 0x35c000d7, 0x390000e4, 0x3c8000f2, 101 + 0x40000100, 0x43c0010f, 0x47c0011f, 0x4c000130, 0x50800142, 0x55400155, 102 + 0x5a400169, 0x5fc0017f, 0x65400195, 0x6b8001ae, 0x71c001c7, 0x788001e2, 103 + 0x7f8001fe, 104 + }; 105 + 106 + static const u32 rtw8723d_cck_swing_table[] = { 107 + 0x0CD, 0x0D9, 0x0E6, 0x0F3, 0x102, 0x111, 0x121, 0x132, 0x144, 0x158, 108 + 0x16C, 0x182, 0x198, 0x1B1, 0x1CA, 0x1E5, 0x202, 0x221, 0x241, 0x263, 109 + 0x287, 0x2AE, 0x2D6, 0x301, 0x32F, 0x35F, 0x392, 0x3C9, 0x402, 0x43F, 110 + 0x47F, 0x4C3, 0x50C, 0x558, 0x5A9, 0x5FF, 0x65A, 0x6BA, 0x720, 0x78C, 111 + 0x7FF, 112 + }; 113 + 114 + #define RTW_OFDM_SWING_TABLE_SIZE ARRAY_SIZE(rtw8723d_ofdm_swing_table) 115 + #define RTW_CCK_SWING_TABLE_SIZE ARRAY_SIZE(rtw8723d_cck_swing_table) 116 + 117 + static void rtw8723d_pwrtrack_init(struct rtw_dev *rtwdev) 118 + { 119 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 120 + u8 path; 121 + 122 + dm_info->default_ofdm_index = RTW_DEF_OFDM_SWING_INDEX; 123 + 124 + for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) { 125 + ewma_thermal_init(&dm_info->avg_thermal[path]); 126 + dm_info->delta_power_index[path] = 0; 127 + } 128 + dm_info->pwr_trk_triggered = false; 129 + dm_info->pwr_trk_init_trigger = true; 130 + dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k; 131 + dm_info->txagc_remnant_cck = 0; 132 + dm_info->txagc_remnant_ofdm = 0; 133 + } 134 + 95 135 static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev) 96 136 { 97 137 u8 xtal_cap; ··· 198 158 199 159 rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50); 200 160 rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x20); 161 + 162 + rtw8723d_pwrtrack_init(rtwdev); 201 163 } 202 164 203 165 static void rtw8723de_efuse_parsing(struct rtw_efuse *efuse, ··· 1492 1450 rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] finished\n"); 1493 1451 } 1494 1452 1453 + static u8 rtw8723d_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev) 1454 + { 1455 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 1456 + u8 tx_rate = dm_info->tx_rate; 1457 + u8 limit_ofdm = 30; 1458 + 1459 + switch (tx_rate) { 1460 + case DESC_RATE1M...DESC_RATE5_5M: 1461 + case DESC_RATE11M: 1462 + break; 1463 + case DESC_RATE6M...DESC_RATE48M: 1464 + limit_ofdm = 36; 1465 + break; 1466 + case DESC_RATE54M: 1467 + limit_ofdm = 34; 1468 + break; 1469 + case DESC_RATEMCS0...DESC_RATEMCS2: 1470 + limit_ofdm = 38; 1471 + break; 1472 + case DESC_RATEMCS3...DESC_RATEMCS4: 1473 + limit_ofdm = 36; 1474 + break; 1475 + case DESC_RATEMCS5...DESC_RATEMCS7: 1476 + limit_ofdm = 34; 1477 + break; 1478 + default: 1479 + rtw_warn(rtwdev, "pwrtrack unhandled tx_rate 0x%x\n", tx_rate); 1480 + break; 1481 + } 1482 + 1483 + return limit_ofdm; 1484 + } 1485 + 1486 + static void rtw8723d_set_iqk_matrix_by_result(struct rtw_dev *rtwdev, 1487 + u32 ofdm_swing, u8 rf_path) 1488 + { 1489 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 1490 + s32 ele_A, ele_D, ele_C; 1491 + s32 ele_A_ext, ele_C_ext, ele_D_ext; 1492 + s32 iqk_result_x; 1493 + s32 iqk_result_y; 1494 + s32 value32; 1495 + 1496 + switch (rf_path) { 1497 + default: 1498 + case RF_PATH_A: 1499 + iqk_result_x = dm_info->iqk.result.s1_x; 1500 + iqk_result_y = dm_info->iqk.result.s1_y; 1501 + break; 1502 + case RF_PATH_B: 1503 + iqk_result_x = dm_info->iqk.result.s0_x; 1504 + iqk_result_y = dm_info->iqk.result.s0_y; 1505 + break; 1506 + } 1507 + 1508 + /* new element D */ 1509 + ele_D = OFDM_SWING_D(ofdm_swing); 1510 + iqk_mult(iqk_result_x, ele_D, &ele_D_ext); 1511 + /* new element A */ 1512 + iqk_result_x = iqkxy_to_s32(iqk_result_x); 1513 + ele_A = iqk_mult(iqk_result_x, ele_D, &ele_A_ext); 1514 + /* new element C */ 1515 + iqk_result_y = iqkxy_to_s32(iqk_result_y); 1516 + ele_C = iqk_mult(iqk_result_y, ele_D, &ele_C_ext); 1517 + 1518 + switch (rf_path) { 1519 + case RF_PATH_A: 1520 + default: 1521 + /* write new elements A, C, D, and element B is always 0 */ 1522 + value32 = BIT_SET_TXIQ_ELM_ACD(ele_A, ele_C, ele_D); 1523 + rtw_write32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, value32); 1524 + value32 = BIT_SET_TXIQ_ELM_C1(ele_C); 1525 + rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS, 1526 + value32); 1527 + value32 = rtw_read32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD); 1528 + value32 &= ~BIT_MASK_OFDM0_EXTS; 1529 + value32 |= BIT_SET_OFDM0_EXTS(ele_A_ext, ele_C_ext, ele_D_ext); 1530 + rtw_write32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, value32); 1531 + break; 1532 + 1533 + case RF_PATH_B: 1534 + /* write new elements A, C, D, and element B is always 0 */ 1535 + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0, ele_D); 1536 + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, ele_C); 1537 + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, ele_A); 1538 + 1539 + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_EXT_S0, 1540 + ele_D_ext); 1541 + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, 1542 + ele_A_ext); 1543 + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, 1544 + ele_C_ext); 1545 + break; 1546 + } 1547 + } 1548 + 1549 + static void rtw8723d_set_iqk_matrix(struct rtw_dev *rtwdev, s8 ofdm_index, 1550 + u8 rf_path) 1551 + { 1552 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 1553 + s32 value32; 1554 + u32 ofdm_swing; 1555 + 1556 + if (ofdm_index >= RTW_OFDM_SWING_TABLE_SIZE) 1557 + ofdm_index = RTW_OFDM_SWING_TABLE_SIZE - 1; 1558 + else if (ofdm_index < 0) 1559 + ofdm_index = 0; 1560 + 1561 + ofdm_swing = rtw8723d_ofdm_swing_table[ofdm_index]; 1562 + 1563 + if (dm_info->iqk.done) { 1564 + rtw8723d_set_iqk_matrix_by_result(rtwdev, ofdm_swing, rf_path); 1565 + return; 1566 + } 1567 + 1568 + switch (rf_path) { 1569 + case RF_PATH_A: 1570 + default: 1571 + rtw_write32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, ofdm_swing); 1572 + rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS, 1573 + 0x00); 1574 + value32 = rtw_read32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD); 1575 + value32 &= ~BIT_MASK_OFDM0_EXTS; 1576 + rtw_write32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, value32); 1577 + break; 1578 + 1579 + case RF_PATH_B: 1580 + /* image S1:c80 to S0:Cd0 and Cd4 */ 1581 + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, 1582 + OFDM_SWING_A(ofdm_swing)); 1583 + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_B_S0, 1584 + OFDM_SWING_B(ofdm_swing)); 1585 + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, 1586 + OFDM_SWING_C(ofdm_swing)); 1587 + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0, 1588 + OFDM_SWING_D(ofdm_swing)); 1589 + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_EXT_S0, 0x0); 1590 + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, 0x0); 1591 + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, 0x0); 1592 + break; 1593 + } 1594 + } 1595 + 1596 + static void rtw8723d_pwrtrack_set_ofdm_pwr(struct rtw_dev *rtwdev, s8 swing_idx, 1597 + s8 txagc_idx) 1598 + { 1599 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 1600 + 1601 + dm_info->txagc_remnant_ofdm = txagc_idx; 1602 + 1603 + rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A); 1604 + rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_B); 1605 + } 1606 + 1607 + static void rtw8723d_pwrtrack_set_cck_pwr(struct rtw_dev *rtwdev, s8 swing_idx, 1608 + s8 txagc_idx) 1609 + { 1610 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 1611 + 1612 + dm_info->txagc_remnant_cck = txagc_idx; 1613 + 1614 + rtw_write32_mask(rtwdev, 0xab4, 0x000007FF, 1615 + rtw8723d_cck_swing_table[swing_idx]); 1616 + } 1617 + 1618 + static void rtw8723d_pwrtrack_set(struct rtw_dev *rtwdev, u8 path) 1619 + { 1620 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 1621 + struct rtw_hal *hal = &rtwdev->hal; 1622 + u8 limit_ofdm; 1623 + u8 limit_cck = 40; 1624 + s8 final_ofdm_swing_index; 1625 + s8 final_cck_swing_index; 1626 + 1627 + limit_ofdm = rtw8723d_pwrtrack_get_limit_ofdm(rtwdev); 1628 + 1629 + final_ofdm_swing_index = RTW_DEF_OFDM_SWING_INDEX + 1630 + dm_info->delta_power_index[path]; 1631 + final_cck_swing_index = RTW_DEF_CCK_SWING_INDEX + 1632 + dm_info->delta_power_index[path]; 1633 + 1634 + if (final_ofdm_swing_index > limit_ofdm) 1635 + rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, limit_ofdm, 1636 + final_ofdm_swing_index - limit_ofdm); 1637 + else if (final_ofdm_swing_index < 0) 1638 + rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, 0, 1639 + final_ofdm_swing_index); 1640 + else 1641 + rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, final_ofdm_swing_index, 0); 1642 + 1643 + if (final_cck_swing_index > limit_cck) 1644 + rtw8723d_pwrtrack_set_cck_pwr(rtwdev, limit_cck, 1645 + final_cck_swing_index - limit_cck); 1646 + else if (final_cck_swing_index < 0) 1647 + rtw8723d_pwrtrack_set_cck_pwr(rtwdev, 0, 1648 + final_cck_swing_index); 1649 + else 1650 + rtw8723d_pwrtrack_set_cck_pwr(rtwdev, final_cck_swing_index, 0); 1651 + 1652 + rtw_phy_set_tx_power_level(rtwdev, hal->current_channel); 1653 + } 1654 + 1655 + static void rtw8723d_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path, 1656 + u8 delta) 1657 + { 1658 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 1659 + const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl; 1660 + const s8 *pwrtrk_xtal; 1661 + s8 xtal_cap; 1662 + 1663 + if (dm_info->thermal_avg[therm_path] > 1664 + rtwdev->efuse.thermal_meter[therm_path]) 1665 + pwrtrk_xtal = tbl->pwrtrk_xtal_p; 1666 + else 1667 + pwrtrk_xtal = tbl->pwrtrk_xtal_n; 1668 + 1669 + xtal_cap = rtwdev->efuse.crystal_cap & 0x3F; 1670 + xtal_cap = clamp_t(s8, xtal_cap + pwrtrk_xtal[delta], 0, 0x3F); 1671 + rtw_write32_mask(rtwdev, REG_AFE_CTRL3, BIT_MASK_XTAL, 1672 + xtal_cap | (xtal_cap << 6)); 1673 + } 1674 + 1675 + static void rtw8723d_phy_pwrtrack(struct rtw_dev *rtwdev) 1676 + { 1677 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 1678 + struct rtw_swing_table swing_table; 1679 + u8 thermal_value, delta, path; 1680 + bool do_iqk = false; 1681 + 1682 + rtw_phy_config_swing_table(rtwdev, &swing_table); 1683 + 1684 + if (rtwdev->efuse.thermal_meter[0] == 0xff) 1685 + return; 1686 + 1687 + thermal_value = rtw_read_rf(rtwdev, RF_PATH_A, RF_T_METER, 0xfc00); 1688 + 1689 + rtw_phy_pwrtrack_avg(rtwdev, thermal_value, RF_PATH_A); 1690 + 1691 + do_iqk = rtw_phy_pwrtrack_need_iqk(rtwdev); 1692 + 1693 + if (do_iqk) 1694 + rtw8723d_lck(rtwdev); 1695 + 1696 + if (dm_info->pwr_trk_init_trigger) 1697 + dm_info->pwr_trk_init_trigger = false; 1698 + else if (!rtw_phy_pwrtrack_thermal_changed(rtwdev, thermal_value, 1699 + RF_PATH_A)) 1700 + goto iqk; 1701 + 1702 + delta = rtw_phy_pwrtrack_get_delta(rtwdev, RF_PATH_A); 1703 + 1704 + delta = min_t(u8, delta, RTW_PWR_TRK_TBL_SZ - 1); 1705 + 1706 + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { 1707 + s8 delta_cur, delta_last; 1708 + 1709 + delta_last = dm_info->delta_power_index[path]; 1710 + delta_cur = rtw_phy_pwrtrack_get_pwridx(rtwdev, &swing_table, 1711 + path, RF_PATH_A, delta); 1712 + if (delta_last == delta_cur) 1713 + continue; 1714 + 1715 + dm_info->delta_power_index[path] = delta_cur; 1716 + rtw8723d_pwrtrack_set(rtwdev, path); 1717 + } 1718 + 1719 + rtw8723d_pwrtrack_set_xtal(rtwdev, RF_PATH_A, delta); 1720 + 1721 + iqk: 1722 + if (do_iqk) 1723 + rtw8723d_phy_calibration(rtwdev); 1724 + } 1725 + 1726 + void rtw8723d_pwr_track(struct rtw_dev *rtwdev) 1727 + { 1728 + struct rtw_efuse *efuse = &rtwdev->efuse; 1729 + struct rtw_dm_info *dm_info = &rtwdev->dm_info; 1730 + 1731 + if (efuse->power_track_type != 0) 1732 + return; 1733 + 1734 + if (!dm_info->pwr_trk_triggered) { 1735 + rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER, 1736 + GENMASK(17, 16), 0x03); 1737 + dm_info->pwr_trk_triggered = true; 1738 + return; 1739 + } 1740 + 1741 + rtw8723d_phy_pwrtrack(rtwdev); 1742 + dm_info->pwr_trk_triggered = false; 1743 + } 1744 + 1495 1745 static struct rtw_chip_ops rtw8723d_ops = { 1496 1746 .phy_set_param = rtw8723d_phy_set_param, 1497 1747 .read_efuse = rtw8723d_read_efuse, ··· 1798 1464 .efuse_grant = rtw8723d_efuse_grant, 1799 1465 .false_alarm_statistics = rtw8723d_false_alarm_statistics, 1800 1466 .phy_calibration = rtw8723d_phy_calibration, 1467 + .pwr_track = rtw8723d_pwr_track, 1801 1468 .config_bfee = NULL, 1802 1469 .set_gid_table = NULL, 1803 1470 .cfg_csi_rate = NULL, ··· 2272 1937 .txpwr_lmt_tbl = &rtw8723d_txpwr_lmt_tbl,}, 2273 1938 }; 2274 1939 1940 + static const u8 rtw8723d_pwrtrk_2gb_n[] = { 1941 + 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 1942 + 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10 1943 + }; 1944 + 1945 + static const u8 rtw8723d_pwrtrk_2gb_p[] = { 1946 + 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 1947 + 7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10 1948 + }; 1949 + 1950 + static const u8 rtw8723d_pwrtrk_2ga_n[] = { 1951 + 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 1952 + 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10 1953 + }; 1954 + 1955 + static const u8 rtw8723d_pwrtrk_2ga_p[] = { 1956 + 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 1957 + 7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10 1958 + }; 1959 + 1960 + static const u8 rtw8723d_pwrtrk_2g_cck_b_n[] = { 1961 + 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 1962 + 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11 1963 + }; 1964 + 1965 + static const u8 rtw8723d_pwrtrk_2g_cck_b_p[] = { 1966 + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 1967 + 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11 1968 + }; 1969 + 1970 + static const u8 rtw8723d_pwrtrk_2g_cck_a_n[] = { 1971 + 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 1972 + 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11 1973 + }; 1974 + 1975 + static const u8 rtw8723d_pwrtrk_2g_cck_a_p[] = { 1976 + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 1977 + 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11 1978 + }; 1979 + 1980 + static const s8 rtw8723d_pwrtrk_xtal_n[] = { 1981 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1982 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 1983 + }; 1984 + 1985 + static const s8 rtw8723d_pwrtrk_xtal_p[] = { 1986 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1987 + 0, -10, -12, -14, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16 1988 + }; 1989 + 1990 + static const struct rtw_pwr_track_tbl rtw8723d_rtw_pwr_track_tbl = { 1991 + .pwrtrk_2gb_n = rtw8723d_pwrtrk_2gb_n, 1992 + .pwrtrk_2gb_p = rtw8723d_pwrtrk_2gb_p, 1993 + .pwrtrk_2ga_n = rtw8723d_pwrtrk_2ga_n, 1994 + .pwrtrk_2ga_p = rtw8723d_pwrtrk_2ga_p, 1995 + .pwrtrk_2g_cckb_n = rtw8723d_pwrtrk_2g_cck_b_n, 1996 + .pwrtrk_2g_cckb_p = rtw8723d_pwrtrk_2g_cck_b_p, 1997 + .pwrtrk_2g_ccka_n = rtw8723d_pwrtrk_2g_cck_a_n, 1998 + .pwrtrk_2g_ccka_p = rtw8723d_pwrtrk_2g_cck_a_p, 1999 + .pwrtrk_xtal_p = rtw8723d_pwrtrk_xtal_p, 2000 + .pwrtrk_xtal_n = rtw8723d_pwrtrk_xtal_n, 2001 + }; 2002 + 2275 2003 struct rtw_chip_info rtw8723d_hw_spec = { 2276 2004 .ops = &rtw8723d_ops, 2277 2005 .id = RTW_CHIP_TYPE_8723D, ··· 2377 1979 .rfe_defs = rtw8723d_rfe_defs, 2378 1980 .rfe_defs_size = ARRAY_SIZE(rtw8723d_rfe_defs), 2379 1981 .rx_ldpc = false, 1982 + .pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl, 1983 + .iqk_threshold = 8, 2380 1984 }; 2381 1985 EXPORT_SYMBOL(rtw8723d_hw_spec); 2382 1986
+7
drivers/net/wireless/realtek/rtw88/rtw8723d.h
··· 112 112 return (t >> 8); /* Q.16 --> Q.8 */ 113 113 } 114 114 115 + #define OFDM_SWING_A(swing) FIELD_GET(GENMASK(9, 0), swing) 116 + #define OFDM_SWING_B(swing) FIELD_GET(GENMASK(15, 10), swing) 117 + #define OFDM_SWING_C(swing) FIELD_GET(GENMASK(21, 16), swing) 118 + #define OFDM_SWING_D(swing) FIELD_GET(GENMASK(31, 22), swing) 119 + #define RTW_DEF_OFDM_SWING_INDEX 28 120 + #define RTW_DEF_CCK_SWING_INDEX 28 121 + 115 122 #define MAX_TOLERANCE 5 116 123 #define IQK_TX_X_ERR 0x142 117 124 #define IQK_TX_Y_ERR 0x42