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