blob: aa081019542b5cf55262a427a89bed9a864b0421 [file] [log] [blame]
developerd0c89452024-10-11 16:53:27 +08001From 2d4b4838473a1a02b793b9ba214f03640419f5ba Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Wed, 1 Mar 2023 12:12:51 +0800
developerd0c89452024-10-11 16:53:27 +08004Subject: [PATCH 017/223] mtk: mt76: mt7996: add normal mode pre-calibration
developer05f3b2b2024-08-19 19:17:34 +08005 support
developer66e89bc2024-04-23 14:50:01 +08006
7Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
8---
9 mt76_connac_mcu.h | 1 +
10 mt7996/eeprom.c | 4 ++
11 mt7996/eeprom.h | 2 +
12 mt7996/init.c | 6 ++
13 mt7996/main.c | 6 ++
14 mt7996/mcu.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++
15 mt7996/mt7996.h | 3 +
16 7 files changed, 188 insertions(+)
17
18diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
developerd0c89452024-10-11 16:53:27 +080019index c7fa7b26..a7d7ecce 100644
developer66e89bc2024-04-23 14:50:01 +080020--- a/mt76_connac_mcu.h
21+++ b/mt76_connac_mcu.h
developerd0c89452024-10-11 16:53:27 +080022@@ -1294,6 +1294,7 @@ enum {
developer66e89bc2024-04-23 14:50:01 +080023 MCU_UNI_CMD_PP = 0x38,
24 MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
25 MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
26+ MCU_UNI_CMD_PRECAL_RESULT = 0x47,
27 MCU_UNI_CMD_RRO = 0x57,
28 MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
29 MCU_UNI_CMD_PER_STA_INFO = 0x6d,
30diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
developerd0c89452024-10-11 16:53:27 +080031index 31b8fd1a..5ff52577 100644
developer66e89bc2024-04-23 14:50:01 +080032--- a/mt7996/eeprom.c
33+++ b/mt7996/eeprom.c
developerd0c89452024-10-11 16:53:27 +080034@@ -489,6 +489,10 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
35 if (ret < 0)
36 return ret;
developer66e89bc2024-04-23 14:50:01 +080037
38+ ret = mt7996_eeprom_load_precal(dev);
39+ if (ret)
40+ return ret;
41+
42 ret = mt7996_eeprom_parse_hw_cap(dev, &dev->phy);
43 if (ret < 0)
44 return ret;
45diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
developerd0c89452024-10-11 16:53:27 +080046index c1cad4f9..b3b9b854 100644
developer66e89bc2024-04-23 14:50:01 +080047--- a/mt7996/eeprom.h
48+++ b/mt7996/eeprom.h
49@@ -25,6 +25,8 @@ enum mt7996_eeprom_field {
50 MT_EE_TX0_POWER_6G = 0x1310,
51
52 __MT_EE_MAX = 0x1dff,
53+ /* 0x1e10 ~ 0x2d644 used to save group cal data */
54+ MT_EE_PRECAL = 0x1e10,
55 };
56
57 #define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0)
58diff --git a/mt7996/init.c b/mt7996/init.c
developerd0c89452024-10-11 16:53:27 +080059index dc736a2d..a34e034d 100644
developer66e89bc2024-04-23 14:50:01 +080060--- a/mt7996/init.c
61+++ b/mt7996/init.c
developerd0c89452024-10-11 16:53:27 +080062@@ -1003,6 +1003,12 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
developer66e89bc2024-04-23 14:50:01 +080063 if (ret < 0)
64 return ret;
65
66+ if (dev->flash_mode) {
67+ ret = mt7996_mcu_apply_group_cal(dev);
68+ if (ret)
69+ return ret;
70+ }
71+
72 /* Beacon and mgmt frames should occupy wcid 0 */
73 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
74 if (idx)
75diff --git a/mt7996/main.c b/mt7996/main.c
developerd0c89452024-10-11 16:53:27 +080076index b7ae6e1a..9ff9ae0e 100644
developer66e89bc2024-04-23 14:50:01 +080077--- a/mt7996/main.c
78+++ b/mt7996/main.c
developerd0c89452024-10-11 16:53:27 +080079@@ -310,6 +310,12 @@ int mt7996_set_channel(struct mt76_phy *mphy)
80 struct mt7996_phy *phy = mphy->priv;
81 int ret;
developer66e89bc2024-04-23 14:50:01 +080082
83+ if (dev->flash_mode) {
84+ ret = mt7996_mcu_apply_tx_dpd(phy);
85+ if (ret)
86+ goto out;
87+ }
88+
89 if (mt76_testmode_enabled(phy->mt76) || phy->mt76->test.bf_en) {
90 mt7996_tm_update_channel(phy);
91 goto out;
92diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developerd0c89452024-10-11 16:53:27 +080093index 08534fec..b15075ab 100644
developer66e89bc2024-04-23 14:50:01 +080094--- a/mt7996/mcu.c
95+++ b/mt7996/mcu.c
developerd0c89452024-10-11 16:53:27 +080096@@ -3650,6 +3650,172 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
developer66e89bc2024-04-23 14:50:01 +080097 return 0;
98 }
99
100+static int mt7996_mcu_set_pre_cal(struct mt7996_dev *dev, u32 idx,
101+ u8 *cal, u32 len, u32 cal_id)
102+{
103+#define PRECAL_CMD_PRE_CAL_RESULT 0x0
104+ struct {
105+ /* fixed field */
106+ u8 action;
107+ u8 dest;
108+ u8 attribute;
109+ u8 tag_num;
110+
111+ __le16 tag;
112+ __le16 len;
113+
114+ __le32 cal_id;
115+ s8 precal;
116+ u8 band;
117+ u8 rsv[2];
118+ __le32 idx;
119+ __le32 cal_len;
120+ } req = {
121+ .tag = cpu_to_le16(PRECAL_CMD_PRE_CAL_RESULT),
122+ .len = cpu_to_le16(sizeof(req) - 4 + len),
123+ .cal_id = cpu_to_le32(cal_id),
124+ .idx = cpu_to_le32(idx),
125+ .cal_len = cpu_to_le32(len),
126+ };
127+ struct sk_buff *skb;
128+
129+ if (!len)
130+ return 0;
131+
132+ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req) + len);
133+ if (!skb)
134+ return -ENOMEM;
135+
136+ skb_put_data(skb, &req, sizeof(req));
137+ skb_put_data(skb, cal, len);
138+
139+ return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WM_UNI_CMD(PRECAL_RESULT), false);
140+}
141+
142+int mt7996_mcu_apply_group_cal(struct mt7996_dev *dev)
143+{
144+ u8 *cal = dev->cal, *eeprom = dev->mt76.eeprom.data;
145+ u32 idx = 0, total_idx = MT_EE_CAL_GROUP_SIZE / MT_EE_CAL_UNIT;
146+ u32 offs = MT_EE_DO_PRE_CAL;
147+ int ret = 0;
148+
149+ if (!(eeprom[offs] & MT_EE_WIFI_CAL_GROUP))
150+ return 0;
151+
152+ for (idx = 0; idx < total_idx; idx++, cal += MT_EE_CAL_UNIT) {
153+ ret = mt7996_mcu_set_pre_cal(dev, idx, cal, MT_EE_CAL_UNIT, RF_PRE_CAL);
154+ if (ret)
155+ goto out;
156+ }
157+
158+ ret = mt7996_mcu_set_pre_cal(dev, total_idx, cal,
159+ MT_EE_CAL_GROUP_SIZE % MT_EE_CAL_UNIT, RF_PRE_CAL);
160+
161+out:
162+ return ret;
163+}
164+
165+int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy)
166+{
167+ struct mt7996_dev *dev = phy->dev;
168+ struct mt76_phy *mphy = phy->mt76;
169+ struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
170+ enum nl80211_band band = chandef->chan->band;
171+ enum nl80211_chan_width bw = chandef->width;
172+ const struct ieee80211_channel *chan_list;
173+ u32 cal_id, chan_list_size, base_offset = 0, offs = MT_EE_DO_PRE_CAL;
174+ u32 dpd_size_2g, dpd_size_5g, per_chan_size = DPD_PER_CH_BW20_SIZE;
175+ u16 channel = ieee80211_frequency_to_channel(chandef->center_freq1);
176+ u8 dpd_mask, *cal = dev->cal, *eeprom = dev->mt76.eeprom.data;
177+ int idx, i, ret;
178+
179+ dpd_size_2g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_2GHZ);
180+ dpd_size_5g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_5GHZ);
181+
182+ switch (band) {
183+ case NL80211_BAND_2GHZ:
184+ dpd_mask = MT_EE_WIFI_CAL_DPD_2G;
185+ /* channel 14 don't need DPD cal */
186+ if (channel >= 1 && channel <= 4)
187+ channel = 3;
188+ else if (channel >= 5 && channel <= 9)
189+ channel = 7;
190+ else if (channel >= 10 && channel <= 13)
191+ channel = 11;
192+ else
193+ return 0;
194+ cal_id = RF_DPD_FLAT_CAL;
195+ chan_list = dpd_2g_ch_list_bw20;
196+ chan_list_size = dpd_2g_bw20_ch_num;
197+ break;
198+ case NL80211_BAND_5GHZ:
199+ dpd_mask = MT_EE_WIFI_CAL_DPD_5G;
200+ cal_id = RF_DPD_FLAT_5G_CAL;
201+ chan_list = mphy->sband_5g.sband.channels;
202+ chan_list_size = mphy->sband_5g.sband.n_channels;
203+ base_offset += dpd_size_2g;
204+ if (bw == NL80211_CHAN_WIDTH_160) {
205+ base_offset += mphy->sband_5g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
206+ per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
207+ cal_id = RF_DPD_FLAT_5G_MEM_CAL;
208+ chan_list = dpd_5g_ch_list_bw160;
209+ chan_list_size = dpd_5g_bw160_ch_num;
210+ } else if (bw > NL80211_CHAN_WIDTH_20) {
211+ /* apply (center channel - 2)'s dpd cal data for bw 40/80 channels */
212+ channel -= 2;
213+ }
214+ break;
215+ case NL80211_BAND_6GHZ:
216+ dpd_mask = MT_EE_WIFI_CAL_DPD_6G;
217+ cal_id = RF_DPD_FLAT_6G_CAL;
218+ chan_list = mphy->sband_6g.sband.channels;
219+ chan_list_size = mphy->sband_6g.sband.n_channels;
220+ base_offset += dpd_size_2g + dpd_size_5g;
221+ if (bw == NL80211_CHAN_WIDTH_160) {
222+ base_offset += mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
223+ per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
224+ cal_id = RF_DPD_FLAT_6G_MEM_CAL;
225+ chan_list = dpd_6g_ch_list_bw160;
226+ chan_list_size = dpd_6g_bw160_ch_num;
227+ } else if (bw == NL80211_CHAN_WIDTH_320) {
228+ base_offset += mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE +
229+ dpd_6g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
230+ per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
231+ cal_id = RF_DPD_FLAT_6G_MEM_CAL;
232+ chan_list = dpd_6g_ch_list_bw320;
233+ chan_list_size = dpd_6g_bw320_ch_num;
234+ } else if (bw > NL80211_CHAN_WIDTH_20) {
235+ /* apply (center channel - 2)'s dpd cal data for bw 40/80 channels */
236+ channel -= 2;
237+ }
238+ break;
239+ default:
240+ dpd_mask = 0;
241+ break;
242+ }
243+
244+ if (!(eeprom[offs] & dpd_mask))
245+ return 0;
246+
247+ for (idx = 0; idx < chan_list_size; idx++)
248+ if (channel == chan_list[idx].hw_value)
249+ break;
250+ if (idx == chan_list_size)
251+ return -EINVAL;
252+
253+ cal += MT_EE_CAL_GROUP_SIZE + base_offset + idx * per_chan_size;
254+
255+ for (i = 0; i < per_chan_size / MT_EE_CAL_UNIT; i++) {
256+ ret = mt7996_mcu_set_pre_cal(dev, i, cal, MT_EE_CAL_UNIT, cal_id);
257+ if (ret)
258+ return ret;
259+
260+ cal += MT_EE_CAL_UNIT;
261+ }
262+
263+ return ret;
264+}
265+
266 int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)
267 {
268 #define NIC_CAP 3
269diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +0800270index 54b81c1e..8770839c 100644
developer66e89bc2024-04-23 14:50:01 +0800271--- a/mt7996/mt7996.h
272+++ b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +0800273@@ -629,6 +629,9 @@ void mt7996_mcu_exit(struct mt7996_dev *dev);
developer66e89bc2024-04-23 14:50:01 +0800274 int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
275 int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
276 int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
277+int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
278+int mt7996_mcu_apply_group_cal(struct mt7996_dev *dev);
279+int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy);
280 #ifdef CONFIG_NL80211_TESTMODE
281 void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
282 #endif
283--
developerd0c89452024-10-11 16:53:27 +08002842.45.2
developer66e89bc2024-04-23 14:50:01 +0800285