blob: 8188823dc272a0093d05ff94400614196cab367e [file] [log] [blame]
developer1f55fcf2024-10-17 14:52:33 +08001From e872be26c3041b9ab7983f24de034b13f376a34b Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: Allen Ye <allen.ye@mediatek.com>
3Date: Fri, 24 Mar 2023 23:35:30 +0800
developer1f55fcf2024-10-17 14:52:33 +08004Subject: [PATCH 019/193] mtk: mt76: mt7996: add txpower support
developer66e89bc2024-04-23 14:50:01 +08005
6Add single sku and default enable sku.
7
8mtk: wifi: mt76: mt7996: Porting wifi6 txpower fix to eagle
9
10Refactor txpower flow.
111. Fix wrong bbp CR address
122. Ignore RegDB power limit when we have single sku table. And dump more informaiton in debugfs.
133. Refactor get_txpower ops flow, we only consider CCK and OFDM power value as maximum.
144. Remove sku_disable due to SQC is over and default enable both sku tables.
15
16Fix wrong power value when user set limit close to path table limit.
17
developerd0c89452024-10-11 16:53:27 +080018Change-Id: I5738cd3730f041f1f42d582e2b62d39b70861376
developer66e89bc2024-04-23 14:50:01 +080019Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
20Signed-off-by: Allen Ye <allen.ye@mediatek.com>
21---
22 eeprom.c | 54 ++++++-
23 mt76.h | 9 ++
24 mt76_connac_mcu.c | 2 +-
25 mt7996/eeprom.c | 34 ++++
26 mt7996/eeprom.h | 42 +++++
27 mt7996/init.c | 16 +-
28 mt7996/main.c | 15 ++
developer05f3b2b2024-08-19 19:17:34 +080029 mt7996/mcu.c | 69 +++++++-
developer66e89bc2024-04-23 14:50:01 +080030 mt7996/mcu.h | 2 +
31 mt7996/mt7996.h | 4 +
developer05f3b2b2024-08-19 19:17:34 +080032 mt7996/mtk_debugfs.c | 363 +++++++++++++++++++++++++++++++++++++++++++
developer66e89bc2024-04-23 14:50:01 +080033 mt7996/mtk_mcu.c | 23 +++
34 mt7996/mtk_mcu.h | 92 +++++++++++
35 mt7996/regs.h | 27 ++--
developer05f3b2b2024-08-19 19:17:34 +080036 14 files changed, 725 insertions(+), 27 deletions(-)
developer66e89bc2024-04-23 14:50:01 +080037
38diff --git a/eeprom.c b/eeprom.c
developer1f55fcf2024-10-17 14:52:33 +080039index 6bd2cc1..85935de 100644
developer66e89bc2024-04-23 14:50:01 +080040--- a/eeprom.c
41+++ b/eeprom.c
developerd0c89452024-10-11 16:53:27 +080042@@ -320,9 +320,10 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data,
developer66e89bc2024-04-23 14:50:01 +080043 static void
44 mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
45 const __be32 *data, size_t len, s8 target_power,
46- s8 nss_delta, s8 *max_power)
47+ s8 nss_delta)
48 {
49 int i, cur;
50+ s8 max_power = -128;
51
52 if (!data)
53 return;
developerd0c89452024-10-11 16:53:27 +080054@@ -334,7 +335,7 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
developer66e89bc2024-04-23 14:50:01 +080055 break;
56
57 mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1,
58- target_power, nss_delta, max_power);
59+ target_power, nss_delta, &max_power);
60 if (--cur > 0)
61 continue;
62
developerd0c89452024-10-11 16:53:27 +080063@@ -350,6 +351,7 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
developer66e89bc2024-04-23 14:50:01 +080064 s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
65 struct ieee80211_channel *chan,
66 struct mt76_power_limits *dest,
67+ struct mt76_power_path_limits *dest_path,
68 s8 target_power)
69 {
70 struct mt76_dev *dev = phy->dev;
developerd0c89452024-10-11 16:53:27 +080071@@ -357,16 +359,20 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
developer66e89bc2024-04-23 14:50:01 +080072 const __be32 *val;
73 char name[16];
74 u32 mcs_rates = dev->drv->mcs_rates;
75- u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
76 char band;
77 size_t len;
78- s8 max_power = 0;
79+ s8 max_power = -127;
80+ s8 max_power_backoff = -127;
81 s8 txs_delta;
82+ int n_chains = hweight16(phy->chainmask);
83+ s8 target_power_combine = target_power + mt76_tx_power_nss_delta(n_chains);
84
85 if (!mcs_rates)
86- mcs_rates = 10;
87+ mcs_rates = 12;
88
89 memset(dest, target_power, sizeof(*dest));
90+ if (dest_path != NULL)
91+ memset(dest_path, 0, sizeof(*dest_path));
92
93 if (!IS_ENABLED(CONFIG_OF))
94 return target_power;
developerd0c89452024-10-11 16:53:27 +080095@@ -412,12 +418,44 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
developer66e89bc2024-04-23 14:50:01 +080096 val = mt76_get_of_array(np, "rates-mcs", &len, mcs_rates + 1);
97 mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
98 ARRAY_SIZE(dest->mcs), val, len,
99- target_power, txs_delta, &max_power);
100+ target_power, txs_delta);
101
102- val = mt76_get_of_array(np, "rates-ru", &len, ru_rates + 1);
103+ val = mt76_get_of_array(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1);
104 mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
105 ARRAY_SIZE(dest->ru), val, len,
106- target_power, txs_delta, &max_power);
107+ target_power, txs_delta);
108+
109+ val = mt76_get_of_array(np, "rates-eht", &len, ARRAY_SIZE(dest->eht[0]) + 1);
110+ mt76_apply_multi_array_limit(dest->eht[0], ARRAY_SIZE(dest->eht[0]),
111+ ARRAY_SIZE(dest->eht), val, len,
112+ target_power, txs_delta);
113+
114+ if (dest_path == NULL)
115+ return max_power;
116+
117+ max_power_backoff = max_power;
118+
119+ val = mt76_get_of_array(np, "paths-cck", &len, ARRAY_SIZE(dest_path->cck));
120+ mt76_apply_array_limit(dest_path->cck, ARRAY_SIZE(dest_path->cck), val,
121+ target_power_combine, txs_delta, &max_power_backoff);
122+
123+ val = mt76_get_of_array(np, "paths-ofdm", &len, ARRAY_SIZE(dest_path->ofdm));
124+ mt76_apply_array_limit(dest_path->ofdm, ARRAY_SIZE(dest_path->ofdm), val,
125+ target_power_combine, txs_delta, &max_power_backoff);
126+
127+ val = mt76_get_of_array(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest_path->ofdm_bf));
128+ mt76_apply_array_limit(dest_path->ofdm_bf, ARRAY_SIZE(dest_path->ofdm_bf), val,
129+ target_power_combine, txs_delta, &max_power_backoff);
130+
131+ val = mt76_get_of_array(np, "paths-ru", &len, ARRAY_SIZE(dest_path->ru[0]) + 1);
132+ mt76_apply_multi_array_limit(dest_path->ru[0], ARRAY_SIZE(dest_path->ru[0]),
133+ ARRAY_SIZE(dest_path->ru), val, len,
134+ target_power_combine, txs_delta);
135+
136+ val = mt76_get_of_array(np, "paths-ru-bf", &len, ARRAY_SIZE(dest_path->ru_bf[0]) + 1);
137+ mt76_apply_multi_array_limit(dest_path->ru_bf[0], ARRAY_SIZE(dest_path->ru_bf[0]),
138+ ARRAY_SIZE(dest_path->ru_bf), val, len,
139+ target_power_combine, txs_delta);
140
141 return max_power;
142 }
143diff --git a/mt76.h b/mt76.h
developer1f55fcf2024-10-17 14:52:33 +0800144index 8666ec2..ac2de85 100644
developer66e89bc2024-04-23 14:50:01 +0800145--- a/mt76.h
146+++ b/mt76.h
developerd0c89452024-10-11 16:53:27 +0800147@@ -1079,6 +1079,14 @@ struct mt76_power_limits {
developer66e89bc2024-04-23 14:50:01 +0800148 s8 eht[16][16];
149 };
150
151+struct mt76_power_path_limits {
152+ s8 cck[5];
153+ s8 ofdm[5];
154+ s8 ofdm_bf[4];
155+ s8 ru[16][15];
156+ s8 ru_bf[16][15];
157+};
158+
159 struct mt76_ethtool_worker_info {
160 u64 *data;
161 int idx;
developerd0c89452024-10-11 16:53:27 +0800162@@ -1694,6 +1702,7 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan);
developer66e89bc2024-04-23 14:50:01 +0800163 s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
164 struct ieee80211_channel *chan,
165 struct mt76_power_limits *dest,
166+ struct mt76_power_path_limits *dest_path,
167 s8 target_power);
168
developer05f3b2b2024-08-19 19:17:34 +0800169 static inline bool mt76_queue_is_rx(struct mt76_dev *dev, struct mt76_queue *q)
developer66e89bc2024-04-23 14:50:01 +0800170diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
developer1f55fcf2024-10-17 14:52:33 +0800171index 07f52dd..c714507 100644
developer66e89bc2024-04-23 14:50:01 +0800172--- a/mt76_connac_mcu.c
173+++ b/mt76_connac_mcu.c
developerd0c89452024-10-11 16:53:27 +0800174@@ -2160,7 +2160,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
developer66e89bc2024-04-23 14:50:01 +0800175 sar_power = mt76_get_sar_power(phy, &chan, reg_power);
176
177 mt76_get_rate_power_limits(phy, &chan, limits,
178- sar_power);
179+ NULL, sar_power);
180
181 tx_power_tlv.last_msg = ch_list[idx] == last_ch;
182 sku_tlbv.channel = ch_list[idx];
183diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
developer1f55fcf2024-10-17 14:52:33 +0800184index 5ff5257..b091e30 100644
developer66e89bc2024-04-23 14:50:01 +0800185--- a/mt7996/eeprom.c
186+++ b/mt7996/eeprom.c
developerd0c89452024-10-11 16:53:27 +0800187@@ -541,3 +541,37 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
developer66e89bc2024-04-23 14:50:01 +0800188
189 return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
190 }
191+
192+const u8 mt7996_sku_group_len[] = {
193+ [SKU_CCK] = 4,
194+ [SKU_OFDM] = 8,
195+ [SKU_HT20] = 8,
196+ [SKU_HT40] = 9,
197+ [SKU_VHT20] = 12,
198+ [SKU_VHT40] = 12,
199+ [SKU_VHT80] = 12,
200+ [SKU_VHT160] = 12,
201+ [SKU_HE26] = 12,
202+ [SKU_HE52] = 12,
203+ [SKU_HE106] = 12,
204+ [SKU_HE242] = 12,
205+ [SKU_HE484] = 12,
206+ [SKU_HE996] = 12,
207+ [SKU_HE2x996] = 12,
208+ [SKU_EHT26] = 16,
209+ [SKU_EHT52] = 16,
210+ [SKU_EHT106] = 16,
211+ [SKU_EHT242] = 16,
212+ [SKU_EHT484] = 16,
213+ [SKU_EHT996] = 16,
214+ [SKU_EHT2x996] = 16,
215+ [SKU_EHT4x996] = 16,
216+ [SKU_EHT26_52] = 16,
217+ [SKU_EHT26_106] = 16,
218+ [SKU_EHT484_242] = 16,
219+ [SKU_EHT996_484] = 16,
220+ [SKU_EHT996_484_242] = 16,
221+ [SKU_EHT2x996_484] = 16,
222+ [SKU_EHT3x996] = 16,
223+ [SKU_EHT3x996_484] = 16,
224+};
225diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
developer1f55fcf2024-10-17 14:52:33 +0800226index b3b9b85..f3a9618 100644
developer66e89bc2024-04-23 14:50:01 +0800227--- a/mt7996/eeprom.h
228+++ b/mt7996/eeprom.h
developerd0c89452024-10-11 16:53:27 +0800229@@ -127,4 +127,46 @@ mt7996_get_channel_group_6g(int channel)
developer66e89bc2024-04-23 14:50:01 +0800230 return DIV_ROUND_UP(channel - 29, 32);
231 }
232
233+enum mt7996_sku_rate_group {
234+ SKU_CCK,
235+ SKU_OFDM,
236+
237+ SKU_HT20,
238+ SKU_HT40,
239+
240+ SKU_VHT20,
241+ SKU_VHT40,
242+ SKU_VHT80,
243+ SKU_VHT160,
244+
245+ SKU_HE26,
246+ SKU_HE52,
247+ SKU_HE106,
248+ SKU_HE242,
249+ SKU_HE484,
250+ SKU_HE996,
251+ SKU_HE2x996,
252+
253+ SKU_EHT26,
254+ SKU_EHT52,
255+ SKU_EHT106,
256+ SKU_EHT242,
257+ SKU_EHT484,
258+ SKU_EHT996,
259+ SKU_EHT2x996,
260+ SKU_EHT4x996,
261+ SKU_EHT26_52,
262+ SKU_EHT26_106,
263+ SKU_EHT484_242,
264+ SKU_EHT996_484,
265+ SKU_EHT996_484_242,
266+ SKU_EHT2x996_484,
267+ SKU_EHT3x996,
268+ SKU_EHT3x996_484,
269+
270+ MAX_SKU_RATE_GROUP_NUM,
271+};
272+
273+extern const u8 mt7996_sku_group_len[MAX_SKU_RATE_GROUP_NUM];
274+
275 #endif
276diff --git a/mt7996/init.c b/mt7996/init.c
developer1f55fcf2024-10-17 14:52:33 +0800277index 32f3a47..2634cc5 100644
developer66e89bc2024-04-23 14:50:01 +0800278--- a/mt7996/init.c
279+++ b/mt7996/init.c
developer1f55fcf2024-10-17 14:52:33 +0800280@@ -294,7 +294,12 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy,
developer66e89bc2024-04-23 14:50:01 +0800281 int nss_delta = mt76_tx_power_nss_delta(nss);
282 int pwr_delta = mt7996_eeprom_get_power_delta(dev, sband->band);
283 struct mt76_power_limits limits;
284+ struct mt76_power_path_limits limits_path;
285+ struct device_node *np;
286
287+ phy->sku_limit_en = true;
288+ phy->sku_path_en = true;
289+ np = mt76_find_power_limits_node(&dev->mt76);
290 for (i = 0; i < sband->n_channels; i++) {
291 struct ieee80211_channel *chan = &sband->channels[i];
292 int target_power = mt7996_eeprom_get_target_power(dev, chan);
developer1f55fcf2024-10-17 14:52:33 +0800293@@ -302,11 +307,18 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy,
developer66e89bc2024-04-23 14:50:01 +0800294 target_power += pwr_delta;
295 target_power = mt76_get_rate_power_limits(phy->mt76, chan,
296 &limits,
297+ &limits_path,
298 target_power);
299+ if (!limits_path.ofdm[0])
300+ phy->sku_path_en = false;
301+
302 target_power += nss_delta;
303 target_power = DIV_ROUND_UP(target_power, 2);
304- chan->max_power = min_t(int, chan->max_reg_power,
305- target_power);
306+ if (!np)
307+ chan->max_power = min_t(int, chan->max_reg_power,
308+ target_power);
309+ else
310+ chan->max_power = target_power;
311 chan->orig_mpwr = target_power;
312 }
313 }
314diff --git a/mt7996/main.c b/mt7996/main.c
developer1f55fcf2024-10-17 14:52:33 +0800315index c13b346..d5b97f1 100644
developer66e89bc2024-04-23 14:50:01 +0800316--- a/mt7996/main.c
317+++ b/mt7996/main.c
318@@ -85,6 +85,21 @@ int mt7996_run(struct ieee80211_hw *hw)
319 if (ret)
320 goto out;
321
322+#ifdef CONFIG_MTK_DEBUG
323+ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL,
324+ dev->dbg.sku_disable ? 0 : phy->sku_limit_en);
325+
326+ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL,
327+ dev->dbg.sku_disable ? 0 : phy->sku_path_en);
328+#else
329+ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL,
330+ phy->sku_limit_en);
331+ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL,
332+ phy->sku_path_en);
333+#endif
334+ if (ret)
335+ goto out;
336+
337 set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
338
339 ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
340diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developer1f55fcf2024-10-17 14:52:33 +0800341index 753a8ac..d114e7f 100644
developer66e89bc2024-04-23 14:50:01 +0800342--- a/mt7996/mcu.c
343+++ b/mt7996/mcu.c
developerd0c89452024-10-11 16:53:27 +0800344@@ -4684,9 +4684,31 @@ int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id)
developer66e89bc2024-04-23 14:50:01 +0800345 sizeof(req), true);
346 }
347
348+static void
349+mt7996_update_max_txpower_cur(struct mt7996_phy *phy, int tx_power)
350+{
351+ struct mt76_phy *mphy = phy->mt76;
352+ struct ieee80211_channel *chan = mphy->main_chan;
353+ int e2p_power_limit = 0;
354+
355+ if (chan == NULL) {
356+ mphy->txpower_cur = tx_power;
357+ return;
358+ }
359+
360+ e2p_power_limit = mt7996_eeprom_get_target_power(phy->dev, chan);
361+ e2p_power_limit += mt7996_eeprom_get_power_delta(phy->dev, chan->band);
362+
363+ if (phy->sku_limit_en)
364+ mphy->txpower_cur = min_t(int, e2p_power_limit, tx_power);
365+ else
366+ mphy->txpower_cur = e2p_power_limit;
367+}
368+
369 int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
370 {
371 #define TX_POWER_LIMIT_TABLE_RATE 0
372+#define TX_POWER_LIMIT_TABLE_PATH 1
373 struct mt7996_dev *dev = phy->dev;
374 struct mt76_phy *mphy = phy->mt76;
375 struct ieee80211_hw *hw = mphy->hw;
developerd0c89452024-10-11 16:53:27 +0800376@@ -4706,13 +4728,22 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
developer66e89bc2024-04-23 14:50:01 +0800377 .band_idx = phy->mt76->band_idx,
378 };
379 struct mt76_power_limits la = {};
380+ struct mt76_power_path_limits la_path = {};
381 struct sk_buff *skb;
382- int i, tx_power;
383+ int i, ret, txpower_limit;
384+
385+ if (hw->conf.power_level == INT_MIN)
386+ hw->conf.power_level = 127;
387+ txpower_limit = mt7996_get_power_bound(phy, hw->conf.power_level);
388
389- tx_power = mt7996_get_power_bound(phy, hw->conf.power_level);
390- tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
391- &la, tx_power);
392- mphy->txpower_cur = tx_power;
393+ if (phy->sku_limit_en) {
394+ txpower_limit = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
395+ &la, &la_path, txpower_limit);
396+ mt7996_update_max_txpower_cur(phy, txpower_limit);
397+ } else {
398+ mt7996_update_max_txpower_cur(phy, txpower_limit);
399+ return 0;
400+ }
401
402 skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
403 sizeof(req) + MT7996_SKU_PATH_NUM);
developerd0c89452024-10-11 16:53:27 +0800404@@ -4742,6 +4773,34 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
developer66e89bc2024-04-23 14:50:01 +0800405 /* padding */
406 skb_put_zero(skb, MT7996_SKU_PATH_NUM - MT7996_SKU_RATE_NUM);
407
408+ ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
409+ MCU_WM_UNI_CMD(TXPOWER), true);
410+ if (ret)
411+ return ret;
412+
413+ /* only set per-path power table when it's configured */
414+ if (!phy->sku_path_en)
415+ return 0;
416+
417+ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
418+ sizeof(req) + MT7996_SKU_PATH_NUM);
419+ if (!skb)
420+ return -ENOMEM;
421+ req.power_limit_type = TX_POWER_LIMIT_TABLE_PATH;
422+
423+ skb_put_data(skb, &req, sizeof(req));
424+ skb_put_data(skb, &la_path.cck, sizeof(la_path.cck));
425+ skb_put_data(skb, &la_path.ofdm, sizeof(la_path.ofdm));
426+ skb_put_data(skb, &la_path.ofdm_bf, sizeof(la_path.ofdm_bf));
427+
428+ for (i = 0; i < 32; i++) {
429+ bool bf = i % 2;
430+ u8 idx = i / 2;
431+ s8 *buf = bf ? la_path.ru_bf[idx] : la_path.ru[idx];
432+
433+ skb_put_data(skb, buf, sizeof(la_path.ru[0]));
434+ }
435+
436 return mt76_mcu_skb_send_msg(&dev->mt76, skb,
437 MCU_WM_UNI_CMD(TXPOWER), true);
438 }
439diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer1f55fcf2024-10-17 14:52:33 +0800440index f889cb8..1ed05d7 100644
developer66e89bc2024-04-23 14:50:01 +0800441--- a/mt7996/mcu.h
442+++ b/mt7996/mcu.h
443@@ -911,6 +911,7 @@ struct tx_power_ctrl {
444 bool ate_mode_enable;
445 bool percentage_ctrl_enable;
446 bool bf_backoff_enable;
447+ u8 show_info_category;
448 u8 power_drop_level;
449 };
450 u8 band_idx;
451@@ -924,6 +925,7 @@ enum {
452 UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL = 3,
453 UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4,
454 UNI_TXPOWER_ATE_MODE_CTRL = 6,
455+ UNI_TXPOWER_SHOW_INFO = 7,
456 };
457
458 enum {
459diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer1f55fcf2024-10-17 14:52:33 +0800460index 6cb6c72..a1a30b3 100644
developer66e89bc2024-04-23 14:50:01 +0800461--- a/mt7996/mt7996.h
462+++ b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +0800463@@ -305,6 +305,9 @@ struct mt7996_phy {
developer66e89bc2024-04-23 14:50:01 +0800464
465 struct mt7996_scs_ctrl scs_ctrl;
466
467+ bool sku_limit_en;
468+ bool sku_path_en;
469+
470 #ifdef CONFIG_NL80211_TESTMODE
471 struct {
472 u32 *reg_backup;
developerd0c89452024-10-11 16:53:27 +0800473@@ -648,6 +651,7 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy);
developer66e89bc2024-04-23 14:50:01 +0800474 #ifdef CONFIG_NL80211_TESTMODE
475 void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
476 #endif
477+int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
478 int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
479 void mt7996_mcu_scs_sta_poll(struct work_struct *work);
480
481diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
developer1f55fcf2024-10-17 14:52:33 +0800482index 1807a74..ad89ecc 100644
developer66e89bc2024-04-23 14:50:01 +0800483--- a/mt7996/mtk_debugfs.c
484+++ b/mt7996/mtk_debugfs.c
developer05f3b2b2024-08-19 19:17:34 +0800485@@ -2439,6 +2439,364 @@ mt7996_scs_enable_set(void *data, u64 val)
developer66e89bc2024-04-23 14:50:01 +0800486 DEFINE_DEBUGFS_ATTRIBUTE(fops_scs_enable, NULL,
487 mt7996_scs_enable_set, "%lld\n");
488
489+static int
490+mt7996_txpower_level_set(void *data, u64 val)
491+{
492+ struct mt7996_phy *phy = data;
493+ int ret;
494+
495+ if (val > 100)
496+ return -EINVAL;
497+
498+ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_PERCENTAGE_CTRL, !!val);
499+ if (ret)
500+ return ret;
501+
502+ return mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_PERCENTAGE_DROP_CTRL, val);
503+}
504+
505+DEFINE_DEBUGFS_ATTRIBUTE(fops_txpower_level, NULL,
506+ mt7996_txpower_level_set, "%lld\n");
507+
508+static ssize_t
509+mt7996_get_txpower_info(struct file *file, char __user *user_buf,
510+ size_t count, loff_t *ppos)
511+{
512+ struct mt7996_phy *phy = file->private_data;
513+ struct mt7996_mcu_txpower_event *event;
514+ struct txpower_basic_info *basic_info;
515+ struct device_node *np;
516+ static const size_t size = 2048;
517+ int len = 0;
518+ ssize_t ret;
519+ char *buf;
520+
521+ buf = kzalloc(size, GFP_KERNEL);
522+ event = kzalloc(sizeof(*event), GFP_KERNEL);
523+ if (!buf || !event) {
524+ ret = -ENOMEM;
525+ goto out;
526+ }
527+
528+ ret = mt7996_mcu_get_tx_power_info(phy, BASIC_INFO, event);
529+ if (ret ||
530+ le32_to_cpu(event->basic_info.category) != UNI_TXPOWER_BASIC_INFO)
531+ goto out;
532+
533+ basic_info = &event->basic_info;
534+
535+ len += scnprintf(buf + len, size - len,
536+ "======================== BASIC INFO ========================\n");
537+ len += scnprintf(buf + len, size - len, " Band Index: %d, Channel Band: %d\n",
538+ basic_info->band_idx, basic_info->band);
539+ len += scnprintf(buf + len, size - len, " PA Type: %s\n",
540+ basic_info->is_epa ? "ePA" : "iPA");
541+ len += scnprintf(buf + len, size - len, " LNA Type: %s\n",
542+ basic_info->is_elna ? "eLNA" : "iLNA");
543+
544+ len += scnprintf(buf + len, size - len,
545+ "------------------------------------------------------------\n");
546+ len += scnprintf(buf + len, size - len, " SKU: %s\n",
547+ basic_info->sku_enable ? "enable" : "disable");
548+ len += scnprintf(buf + len, size - len, " Percentage Control: %s\n",
549+ basic_info->percentage_ctrl_enable ? "enable" : "disable");
550+ len += scnprintf(buf + len, size - len, " Power Drop: %d [dBm]\n",
551+ basic_info->power_drop_level >> 1);
552+ len += scnprintf(buf + len, size - len, " Backoff: %s\n",
553+ basic_info->bf_backoff_enable ? "enable" : "disable");
554+ len += scnprintf(buf + len, size - len, " TX Front-end Loss: %d, %d, %d, %d\n",
555+ basic_info->front_end_loss_tx[0], basic_info->front_end_loss_tx[1],
556+ basic_info->front_end_loss_tx[2], basic_info->front_end_loss_tx[3]);
557+ len += scnprintf(buf + len, size - len, " RX Front-end Loss: %d, %d, %d, %d\n",
558+ basic_info->front_end_loss_rx[0], basic_info->front_end_loss_rx[1],
559+ basic_info->front_end_loss_rx[2], basic_info->front_end_loss_rx[3]);
560+ len += scnprintf(buf + len, size - len,
561+ " MU TX Power Mode: %s\n",
562+ basic_info->mu_tx_power_manual_enable ? "manual" : "auto");
563+ len += scnprintf(buf + len, size - len,
564+ " MU TX Power (Auto / Manual): %d / %d [0.5 dBm]\n",
565+ basic_info->mu_tx_power_auto, basic_info->mu_tx_power_manual);
566+ len += scnprintf(buf + len, size - len,
567+ " Thermal Compensation: %s\n",
568+ basic_info->thermal_compensate_enable ? "enable" : "disable");
569+ len += scnprintf(buf + len, size - len,
570+ " Theraml Compensation Value: %d\n",
571+ basic_info->thermal_compensate_value);
572+ np = mt76_find_power_limits_node(phy->mt76->dev);
573+ len += scnprintf(buf + len, size - len,
574+ " RegDB: %s\n",
575+ !np ? "enable" : "disable");
576+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
577+
578+out:
579+ kfree(buf);
580+ kfree(event);
581+ return ret;
582+}
583+
584+static const struct file_operations mt7996_txpower_info_fops = {
585+ .read = mt7996_get_txpower_info,
586+ .open = simple_open,
587+ .owner = THIS_MODULE,
588+ .llseek = default_llseek,
589+};
590+
591+#define mt7996_txpower_puts(rate, _len) \
592+({ \
593+ len += scnprintf(buf + len, size - len, "%-*s:", _len, #rate " (TMAC)"); \
594+ for (i = 0; i < mt7996_sku_group_len[SKU_##rate]; i++, offs++) \
595+ len += scnprintf(buf + len, size - len, " %6d", \
596+ event->phy_rate_info.frame_power[offs][band_idx]); \
597+ len += scnprintf(buf + len, size - len, "\n"); \
598+})
599+
600+static ssize_t
601+mt7996_get_txpower_sku(struct file *file, char __user *user_buf,
602+ size_t count, loff_t *ppos)
603+{
604+ struct mt7996_phy *phy = file->private_data;
605+ struct mt7996_dev *dev = phy->dev;
606+ struct mt7996_mcu_txpower_event *event;
607+ struct ieee80211_channel *chan = phy->mt76->chandef.chan;
608+ struct ieee80211_supported_band sband;
609+ u8 band_idx = phy->mt76->band_idx;
610+ static const size_t size = 5120;
611+ int i, offs = 0, len = 0;
612+ u32 target_power = 0;
613+ int n_chains = hweight16(phy->mt76->chainmask);
614+ int nss_delta = mt76_tx_power_nss_delta(n_chains);
615+ int pwr_delta;
616+ ssize_t ret;
617+ char *buf;
618+ u32 reg;
619+
620+ buf = kzalloc(size, GFP_KERNEL);
621+ event = kzalloc(sizeof(*event), GFP_KERNEL);
622+ if (!buf || !event) {
623+ ret = -ENOMEM;
624+ goto out;
625+ }
626+
627+ ret = mt7996_mcu_get_tx_power_info(phy, PHY_RATE_INFO, event);
628+ if (ret ||
629+ le32_to_cpu(event->phy_rate_info.category) != UNI_TXPOWER_PHY_RATE_INFO)
630+ goto out;
631+
632+ len += scnprintf(buf + len, size - len,
633+ "\nPhy %d TX Power Table (Channel %d)\n",
634+ band_idx, phy->mt76->chandef.chan->hw_value);
635+ len += scnprintf(buf + len, size - len, "%-21s %6s %6s %6s %6s\n",
636+ " ", "1m", "2m", "5m", "11m");
637+ mt7996_txpower_puts(CCK, 21);
638+
639+ len += scnprintf(buf + len, size - len,
640+ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s\n",
641+ " ", "6m", "9m", "12m", "18m", "24m", "36m", "48m",
642+ "54m");
643+ mt7996_txpower_puts(OFDM, 21);
644+
645+ len += scnprintf(buf + len, size - len,
646+ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s\n",
647+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4",
648+ "mcs5", "mcs6", "mcs7");
649+ mt7996_txpower_puts(HT20, 21);
650+
651+ len += scnprintf(buf + len, size - len,
652+ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
653+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
654+ "mcs6", "mcs7", "mcs32");
655+ mt7996_txpower_puts(HT40, 21);
656+
657+ len += scnprintf(buf + len, size - len,
658+ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
659+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
660+ "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
661+ mt7996_txpower_puts(VHT20, 21);
662+ mt7996_txpower_puts(VHT40, 21);
663+ mt7996_txpower_puts(VHT80, 21);
664+ mt7996_txpower_puts(VHT160, 21);
665+ mt7996_txpower_puts(HE26, 21);
666+ mt7996_txpower_puts(HE52, 21);
667+ mt7996_txpower_puts(HE106, 21);
668+ len += scnprintf(buf + len, size - len, "BW20/");
669+ mt7996_txpower_puts(HE242, 16);
670+ len += scnprintf(buf + len, size - len, "BW40/");
671+ mt7996_txpower_puts(HE484, 16);
672+ len += scnprintf(buf + len, size - len, "BW80/");
673+ mt7996_txpower_puts(HE996, 16);
674+ len += scnprintf(buf + len, size - len, "BW160/");
675+ mt7996_txpower_puts(HE2x996, 15);
676+
677+ len += scnprintf(buf + len, size - len,
678+ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s ",
679+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", "mcs6", "mcs7");
680+ len += scnprintf(buf + len, size - len,
681+ "%6s %6s %6s %6s %6s %6s %6s %6s\n",
682+ "mcs8", "mcs9", "mcs10", "mcs11", "mcs12", "mcs13", "mcs14", "mcs15");
683+ mt7996_txpower_puts(EHT26, 21);
684+ mt7996_txpower_puts(EHT52, 21);
685+ mt7996_txpower_puts(EHT106, 21);
686+ len += scnprintf(buf + len, size - len, "BW20/");
687+ mt7996_txpower_puts(EHT242, 16);
688+ len += scnprintf(buf + len, size - len, "BW40/");
689+ mt7996_txpower_puts(EHT484, 16);
690+ len += scnprintf(buf + len, size - len, "BW80/");
691+ mt7996_txpower_puts(EHT996, 16);
692+ len += scnprintf(buf + len, size - len, "BW160/");
693+ mt7996_txpower_puts(EHT2x996, 15);
694+ len += scnprintf(buf + len, size - len, "BW320/");
695+ mt7996_txpower_puts(EHT4x996, 15);
696+ mt7996_txpower_puts(EHT26_52, 21);
697+ mt7996_txpower_puts(EHT26_106, 21);
698+ mt7996_txpower_puts(EHT484_242, 21);
699+ mt7996_txpower_puts(EHT996_484, 21);
700+ mt7996_txpower_puts(EHT996_484_242, 21);
701+ mt7996_txpower_puts(EHT2x996_484, 21);
702+ mt7996_txpower_puts(EHT3x996, 21);
703+ mt7996_txpower_puts(EHT3x996_484, 21);
704+
705+ len += scnprintf(buf + len, size - len, "\nePA Gain: %d\n",
706+ event->phy_rate_info.epa_gain);
707+ len += scnprintf(buf + len, size - len, "Max Power Bound: %d\n",
708+ event->phy_rate_info.max_power_bound);
709+ len += scnprintf(buf + len, size - len, "Min Power Bound: %d\n",
710+ event->phy_rate_info.min_power_bound);
711+
712+ reg = MT_WF_PHYDFE_TSSI_TXCTRL01(band_idx);
713+ len += scnprintf(buf + len, size - len,
714+ "\nBBP TX Power (target power from TMAC) : %6ld [0.5 dBm]\n",
715+ mt76_get_field(dev, reg, MT_WF_PHYDFE_TSSI_TXCTRL_POWER_TMAC));
716+ len += scnprintf(buf + len, size - len,
717+ "RegDB maximum power:\t%d [dBm]\n",
718+ chan->max_reg_power);
719+
720+ if (chan->band == NL80211_BAND_2GHZ)
721+ sband = phy->mt76->sband_2g.sband;
722+ else if (chan->band == NL80211_BAND_5GHZ)
723+ sband = phy->mt76->sband_5g.sband;
724+ else if (chan->band == NL80211_BAND_6GHZ)
725+ sband = phy->mt76->sband_6g.sband;
726+
727+ pwr_delta = mt7996_eeprom_get_power_delta(dev, sband.band);
728+
729+ target_power = max_t(u32, target_power, mt7996_eeprom_get_target_power(dev, chan));
730+ target_power += pwr_delta + nss_delta;
731+ target_power = DIV_ROUND_UP(target_power, 2);
732+ len += scnprintf(buf + len, size - len,
733+ "eeprom maximum power:\t%d [dBm]\n",
734+ target_power);
735+
736+ len += scnprintf(buf + len, size - len,
737+ "nss_delta:\t%d [0.5 dBm]\n",
738+ nss_delta);
739+
740+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
741+
742+out:
743+ kfree(buf);
744+ kfree(event);
745+ return ret;
746+}
747+
748+static const struct file_operations mt7996_txpower_sku_fops = {
749+ .read = mt7996_get_txpower_sku,
750+ .open = simple_open,
751+ .owner = THIS_MODULE,
752+ .llseek = default_llseek,
753+};
754+
755+#define mt7996_txpower_path_puts(rate, arr_length) \
756+({ \
757+ len += scnprintf(buf + len, size - len, "%23s:", #rate " (TMAC)"); \
758+ for (i = 0; i < arr_length; i++, offs++) \
759+ len += scnprintf(buf + len, size - len, " %4d", \
760+ event->backoff_table_info.frame_power[offs]); \
761+ len += scnprintf(buf + len, size - len, "\n"); \
762+})
763+
764+static ssize_t
765+mt7996_get_txpower_path(struct file *file, char __user *user_buf,
766+ size_t count, loff_t *ppos)
767+{
768+ struct mt7996_phy *phy = file->private_data;
769+ struct mt7996_mcu_txpower_event *event;
770+ static const size_t size = 5120;
771+ int i, offs = 0, len = 0;
772+ ssize_t ret;
773+ char *buf;
774+
775+ buf = kzalloc(size, GFP_KERNEL);
776+ event = kzalloc(sizeof(*event), GFP_KERNEL);
777+ if (!buf || !event) {
778+ ret = -ENOMEM;
779+ goto out;
780+ }
781+
782+ ret = mt7996_mcu_get_tx_power_info(phy, BACKOFF_TABLE_INFO, event);
783+ if (ret ||
784+ le32_to_cpu(event->phy_rate_info.category) != UNI_TXPOWER_BACKOFF_TABLE_SHOW_INFO)
785+ goto out;
786+
787+ len += scnprintf(buf + len, size - len, "\n%*c", 25, ' ');
788+ len += scnprintf(buf + len, size - len, "1T1S/2T1S/3T1S/4T1S/5T1S/2T2S/3T2S/4T2S/5T2S/"
789+ "3T3S/4T3S/5T3S/4T4S/5T4S/5T5S\n");
790+
791+ mt7996_txpower_path_puts(CCK, 5);
792+ mt7996_txpower_path_puts(OFDM, 5);
793+ mt7996_txpower_path_puts(BF-OFDM, 4);
794+
795+ mt7996_txpower_path_puts(RU26, 15);
796+ mt7996_txpower_path_puts(BF-RU26, 15);
797+ mt7996_txpower_path_puts(RU52, 15);
798+ mt7996_txpower_path_puts(BF-RU52, 15);
799+ mt7996_txpower_path_puts(RU26_52, 15);
800+ mt7996_txpower_path_puts(BF-RU26_52, 15);
801+ mt7996_txpower_path_puts(RU106, 15);
802+ mt7996_txpower_path_puts(BF-RU106, 15);
803+ mt7996_txpower_path_puts(RU106_52, 15);
804+ mt7996_txpower_path_puts(BF-RU106_52, 15);
805+
806+ mt7996_txpower_path_puts(BW20/RU242, 15);
807+ mt7996_txpower_path_puts(BF-BW20/RU242, 15);
808+ mt7996_txpower_path_puts(BW40/RU484, 15);
809+ mt7996_txpower_path_puts(BF-BW40/RU484, 15);
810+ mt7996_txpower_path_puts(RU242_484, 15);
811+ mt7996_txpower_path_puts(BF-RU242_484, 15);
812+ mt7996_txpower_path_puts(BW80/RU996, 15);
813+ mt7996_txpower_path_puts(BF-BW80/RU996, 15);
814+ mt7996_txpower_path_puts(RU484_996, 15);
815+ mt7996_txpower_path_puts(BF-RU484_996, 15);
816+ mt7996_txpower_path_puts(RU242_484_996, 15);
817+ mt7996_txpower_path_puts(BF-RU242_484_996, 15);
818+ mt7996_txpower_path_puts(BW160/RU996x2, 15);
819+ mt7996_txpower_path_puts(BF-BW160/RU996x2, 15);
820+ mt7996_txpower_path_puts(RU484_996x2, 15);
821+ mt7996_txpower_path_puts(BF-RU484_996x2, 15);
822+ mt7996_txpower_path_puts(RU996x3, 15);
823+ mt7996_txpower_path_puts(BF-RU996x3, 15);
824+ mt7996_txpower_path_puts(RU484_996x3, 15);
825+ mt7996_txpower_path_puts(BF-RU484_996x3, 15);
826+ mt7996_txpower_path_puts(BW320/RU996x4, 15);
827+ mt7996_txpower_path_puts(BF-BW320/RU996x4, 15);
828+
829+ len += scnprintf(buf + len, size - len, "\nBackoff table: %s\n",
830+ event->backoff_table_info.backoff_en ? "enable" : "disable");
831+
832+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
833+
834+out:
835+ kfree(buf);
836+ kfree(event);
837+ return ret;
838+}
839+
840+static const struct file_operations mt7996_txpower_path_fops = {
841+ .read = mt7996_get_txpower_path,
842+ .open = simple_open,
843+ .owner = THIS_MODULE,
844+ .llseek = default_llseek,
845+};
846+
847 int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
848 {
849 struct mt7996_dev *dev = phy->dev;
developer05f3b2b2024-08-19 19:17:34 +0800850@@ -2503,6 +2861,11 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
developer66e89bc2024-04-23 14:50:01 +0800851 debugfs_create_devm_seqfile(dev->mt76.dev, "tr_info", dir,
852 mt7996_trinfo_read);
developer05f3b2b2024-08-19 19:17:34 +0800853
developer66e89bc2024-04-23 14:50:01 +0800854+ debugfs_create_file("txpower_level", 0600, dir, phy, &fops_txpower_level);
855+ debugfs_create_file("txpower_info", 0600, dir, phy, &mt7996_txpower_info_fops);
856+ debugfs_create_file("txpower_sku", 0600, dir, phy, &mt7996_txpower_sku_fops);
857+ debugfs_create_file("txpower_path", 0600, dir, phy, &mt7996_txpower_path_fops);
developer05f3b2b2024-08-19 19:17:34 +0800858+
developer66e89bc2024-04-23 14:50:01 +0800859 debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
860 mt7996_wtbl_read);
developer05f3b2b2024-08-19 19:17:34 +0800861
developer66e89bc2024-04-23 14:50:01 +0800862diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
developer1f55fcf2024-10-17 14:52:33 +0800863index c16b25a..e56ddd8 100644
developer66e89bc2024-04-23 14:50:01 +0800864--- a/mt7996/mtk_mcu.c
865+++ b/mt7996/mtk_mcu.c
866@@ -12,8 +12,31 @@
867
868 #ifdef CONFIG_MTK_DEBUG
869
870+int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event)
871+{
872+ struct mt7996_dev *dev = phy->dev;
873+ struct tx_power_ctrl req = {
874+ .tag = cpu_to_le16(UNI_TXPOWER_SHOW_INFO),
875+ .len = cpu_to_le16(sizeof(req) - 4),
876+ .power_ctrl_id = UNI_TXPOWER_SHOW_INFO,
877+ .show_info_category = category,
878+ .band_idx = phy->mt76->band_idx,
879+ };
880+ struct sk_buff *skb;
881+ int ret;
882
883+ ret = mt76_mcu_send_and_get_msg(&dev->mt76,
884+ MCU_WM_UNI_CMD_QUERY(TXPOWER),
885+ &req, sizeof(req), true, &skb);
886+ if (ret)
887+ return ret;
888
889+ memcpy(event, skb->data, sizeof(struct mt7996_mcu_txpower_event));
890+
891+ dev_kfree_skb(skb);
892+
893+ return 0;
894+}
895
896 int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val)
897 {
898diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
developer1f55fcf2024-10-17 14:52:33 +0800899index 7f4d4e0..c30418c 100644
developer66e89bc2024-04-23 14:50:01 +0800900--- a/mt7996/mtk_mcu.h
901+++ b/mt7996/mtk_mcu.h
902@@ -14,6 +14,98 @@ enum {
903 UNI_CMD_MURU_DBG_INFO = 0x18,
904 };
905
906+struct txpower_basic_info {
907+ u8 category;
908+ u8 rsv1;
909+
910+ /* basic info */
911+ u8 band_idx;
912+ u8 band;
913+
914+ /* board type info */
915+ bool is_epa;
916+ bool is_elna;
917+
918+ /* power percentage info */
919+ bool percentage_ctrl_enable;
920+ s8 power_drop_level;
921+
922+ /* frond-end loss TX info */
923+ s8 front_end_loss_tx[4];
924+
925+ /* frond-end loss RX info */
926+ s8 front_end_loss_rx[4];
927+
928+ /* thermal info */
929+ bool thermal_compensate_enable;
930+ s8 thermal_compensate_value;
931+ u8 rsv2;
932+
933+ /* TX power max/min limit info */
934+ s8 max_power_bound;
935+ s8 min_power_bound;
936+
937+ /* power limit info */
938+ bool sku_enable;
939+ bool bf_backoff_enable;
940+
941+ /* MU TX power info */
942+ bool mu_tx_power_manual_enable;
943+ s8 mu_tx_power_auto;
944+ s8 mu_tx_power_manual;
945+ u8 rsv3;
946+};
947+
948+struct txpower_phy_rate_info {
949+ u8 category;
950+ u8 band_idx;
951+ u8 band;
952+ u8 epa_gain;
953+
954+ /* rate power info [dBm] */
955+ s8 frame_power[MT7996_SKU_RATE_NUM][__MT_MAX_BAND];
956+
957+ /* TX power max/min limit info */
958+ s8 max_power_bound;
959+ s8 min_power_bound;
960+ u8 rsv1;
961+};
962+
963+struct txpower_backoff_table_info {
964+ u8 category;
965+ u8 band_idx;
966+ u8 band;
967+ u8 backoff_en;
968+
969+ s8 frame_power[MT7996_SKU_PATH_NUM];
970+ u8 rsv[3];
971+};
972+
973+struct mt7996_mcu_txpower_event {
974+ u8 _rsv[4];
975+
976+ __le16 tag;
977+ __le16 len;
978+
979+ union {
980+ struct txpower_basic_info basic_info;
981+ struct txpower_phy_rate_info phy_rate_info;
982+ struct txpower_backoff_table_info backoff_table_info;
983+ };
984+};
985+
986+enum txpower_category {
987+ BASIC_INFO,
988+ BACKOFF_TABLE_INFO,
989+ PHY_RATE_INFO,
990+};
991+
992+enum txpower_event {
993+ UNI_TXPOWER_BASIC_INFO = 0,
994+ UNI_TXPOWER_BACKOFF_TABLE_SHOW_INFO = 3,
995+ UNI_TXPOWER_PHY_RATE_INFO = 5,
996+};
997+
998 #endif
999
1000 #endif
1001diff --git a/mt7996/regs.h b/mt7996/regs.h
developer1f55fcf2024-10-17 14:52:33 +08001002index 3450a2f..539e799 100644
developer66e89bc2024-04-23 14:50:01 +08001003--- a/mt7996/regs.h
1004+++ b/mt7996/regs.h
developerd0c89452024-10-11 16:53:27 +08001005@@ -695,24 +695,29 @@ enum offs_rev {
developer66e89bc2024-04-23 14:50:01 +08001006 ((_wf) << 16) + (ofs))
1007 #define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000)
1008
1009-/* PHYRX CTRL */
1010-#define MT_WF_PHYRX_BAND_BASE 0x83080000
1011-#define MT_WF_PHYRX_BAND(_band, ofs) (MT_WF_PHYRX_BAND_BASE + \
1012+/* PHYDFE CTRL */
1013+#define MT_WF_PHYDFE_TSSI_TXCTRL01(_band) MT_WF_PHYRX_CSD(_band, 0, 0xc718)
1014+#define MT_WF_PHYDFE_TSSI_TXCTRL_POWER_TMAC GENMASK(31, 24)
1015+
1016+/* PHY CTRL */
1017+#define MT_WF_PHY_BAND_BASE 0x83080000
1018+#define MT_WF_PHY_BAND(_band, ofs) (MT_WF_PHY_BAND_BASE + \
1019 ((_band) << 20) + (ofs))
1020
1021-#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHYRX_BAND(_band, 0x1054)
1022-#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHYRX_BAND(_band, 0x1058)
1023-#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHYRX_BAND(_band, 0x105c)
1024-#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHYRX_BAND(_band, 0x1060)
1025-#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHYRX_BAND(_band, 0x1064)
1026-#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHYRX_BAND(_band, 0x1068)
1027+#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHY_BAND(_band, 0x1054)
1028+#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHY_BAND(_band, 0x1058)
1029+#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHY_BAND(_band, 0x105c)
1030+#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHY_BAND(_band, 0x1060)
1031+#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHY_BAND(_band, 0x1064)
1032+#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHY_BAND(_band, 0x1068)
1033
1034-#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHYRX_BAND(_band, 0x2004)
1035+/* PHYRX CTRL */
1036+#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHY_BAND(_band, 0x2004)
1037 #define MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN GENMASK(2, 0)
1038 #define MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN GENMASK(11, 9)
1039
1040 /* PHYRX CSD BAND */
1041-#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHYRX_BAND(_band, 0x8230)
1042+#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHY_BAND(_band, 0x8230)
1043 #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18)
1044 #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29)
1045
1046--
developerd0c89452024-10-11 16:53:27 +080010472.45.2
developer66e89bc2024-04-23 14:50:01 +08001048