18e93258fSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 28e93258fSBjoern A. Zeeb /* Copyright(c) 2019-2020 Realtek Corporation 38e93258fSBjoern A. Zeeb */ 48e93258fSBjoern A. Zeeb 5e2340276SBjoern A. Zeeb #include "acpi.h" 68e93258fSBjoern A. Zeeb #include "debug.h" 78e93258fSBjoern A. Zeeb #include "ps.h" 8e2340276SBjoern A. Zeeb #include "util.h" 98e93258fSBjoern A. Zeeb 108e93258fSBjoern A. Zeeb #define COUNTRY_REGD(_alpha2, _txpwr_regd...) \ 118e93258fSBjoern A. Zeeb {.alpha2 = (_alpha2), \ 128e93258fSBjoern A. Zeeb .txpwr_regd = {_txpwr_regd}, \ 138e93258fSBjoern A. Zeeb } 148e93258fSBjoern A. Zeeb 15e2340276SBjoern A. Zeeb static const struct rtw89_regd rtw89_ww_regd = 16*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("00", RTW89_WW, RTW89_WW, RTW89_WW); 178e93258fSBjoern A. Zeeb 18e2340276SBjoern A. Zeeb static const struct rtw89_regd rtw89_regd_map[] = { 19*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC), 20e2340276SBjoern A. Zeeb COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_FCC), 218e93258fSBjoern A. Zeeb COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC), 228e93258fSBjoern A. Zeeb COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE), 23e2340276SBjoern A. Zeeb COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_FCC), 248e93258fSBjoern A. Zeeb COUNTRY_REGD("CR", RTW89_FCC, RTW89_FCC, RTW89_FCC), 258e93258fSBjoern A. Zeeb COUNTRY_REGD("EC", RTW89_FCC, RTW89_FCC, RTW89_NA), 26e2340276SBjoern A. Zeeb COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_FCC), 27e2340276SBjoern A. Zeeb COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_FCC), 288e93258fSBjoern A. Zeeb COUNTRY_REGD("HN", RTW89_FCC, RTW89_FCC, RTW89_FCC), 29*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC), 308e93258fSBjoern A. Zeeb COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA), 318e93258fSBjoern A. Zeeb COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA), 328e93258fSBjoern A. Zeeb COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA), 33e2340276SBjoern A. Zeeb COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_FCC), 348e93258fSBjoern A. Zeeb COUNTRY_REGD("US", RTW89_FCC, RTW89_FCC, RTW89_FCC), 358e93258fSBjoern A. Zeeb COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA), 368e93258fSBjoern A. Zeeb COUNTRY_REGD("VE", RTW89_FCC, RTW89_FCC, RTW89_NA), 378e93258fSBjoern A. Zeeb COUNTRY_REGD("PR", RTW89_FCC, RTW89_FCC, RTW89_NA), 388e93258fSBjoern A. Zeeb COUNTRY_REGD("DO", RTW89_FCC, RTW89_FCC, RTW89_NA), 398e93258fSBjoern A. Zeeb COUNTRY_REGD("AT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 408e93258fSBjoern A. Zeeb COUNTRY_REGD("BE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 418e93258fSBjoern A. Zeeb COUNTRY_REGD("CY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 428e93258fSBjoern A. Zeeb COUNTRY_REGD("CZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 438e93258fSBjoern A. Zeeb COUNTRY_REGD("DK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 448e93258fSBjoern A. Zeeb COUNTRY_REGD("EE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 458e93258fSBjoern A. Zeeb COUNTRY_REGD("FI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 468e93258fSBjoern A. Zeeb COUNTRY_REGD("FR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 478e93258fSBjoern A. Zeeb COUNTRY_REGD("DE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 488e93258fSBjoern A. Zeeb COUNTRY_REGD("GR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 498e93258fSBjoern A. Zeeb COUNTRY_REGD("HU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 508e93258fSBjoern A. Zeeb COUNTRY_REGD("IS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 518e93258fSBjoern A. Zeeb COUNTRY_REGD("IE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 528e93258fSBjoern A. Zeeb COUNTRY_REGD("IT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 538e93258fSBjoern A. Zeeb COUNTRY_REGD("LV", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 548e93258fSBjoern A. Zeeb COUNTRY_REGD("LI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 558e93258fSBjoern A. Zeeb COUNTRY_REGD("LT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 568e93258fSBjoern A. Zeeb COUNTRY_REGD("LU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 578e93258fSBjoern A. Zeeb COUNTRY_REGD("MT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 588e93258fSBjoern A. Zeeb COUNTRY_REGD("MC", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 598e93258fSBjoern A. Zeeb COUNTRY_REGD("NL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 608e93258fSBjoern A. Zeeb COUNTRY_REGD("NO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 618e93258fSBjoern A. Zeeb COUNTRY_REGD("PL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 628e93258fSBjoern A. Zeeb COUNTRY_REGD("PT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 638e93258fSBjoern A. Zeeb COUNTRY_REGD("SK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 648e93258fSBjoern A. Zeeb COUNTRY_REGD("SI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 658e93258fSBjoern A. Zeeb COUNTRY_REGD("ES", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 668e93258fSBjoern A. Zeeb COUNTRY_REGD("SE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 678e93258fSBjoern A. Zeeb COUNTRY_REGD("CH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 688e93258fSBjoern A. Zeeb COUNTRY_REGD("GB", RTW89_UK, RTW89_UK, RTW89_UK), 698e93258fSBjoern A. Zeeb COUNTRY_REGD("AL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 70e2340276SBjoern A. Zeeb COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 71e2340276SBjoern A. Zeeb COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 728e93258fSBjoern A. Zeeb COUNTRY_REGD("BA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 73e2340276SBjoern A. Zeeb COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 74e2340276SBjoern A. Zeeb COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 758e93258fSBjoern A. Zeeb COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 76e2340276SBjoern A. Zeeb COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 778e93258fSBjoern A. Zeeb COUNTRY_REGD("IQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 78e2340276SBjoern A. Zeeb COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 79e2340276SBjoern A. Zeeb COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 808e93258fSBjoern A. Zeeb COUNTRY_REGD("KZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 81e2340276SBjoern A. Zeeb COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 82e2340276SBjoern A. Zeeb COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 83e2340276SBjoern A. Zeeb COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 84*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 858e93258fSBjoern A. Zeeb COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 868e93258fSBjoern A. Zeeb COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 87e2340276SBjoern A. Zeeb COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 888e93258fSBjoern A. Zeeb COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 898e93258fSBjoern A. Zeeb COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 908e93258fSBjoern A. Zeeb COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 918e93258fSBjoern A. Zeeb COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 928e93258fSBjoern A. Zeeb COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR), 93e2340276SBjoern A. Zeeb COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 948e93258fSBjoern A. Zeeb COUNTRY_REGD("RU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 95e2340276SBjoern A. Zeeb COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 968e93258fSBjoern A. Zeeb COUNTRY_REGD("SN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 97e2340276SBjoern A. Zeeb COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 988e93258fSBjoern A. Zeeb COUNTRY_REGD("ME", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 99*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 100e2340276SBjoern A. Zeeb COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1018e93258fSBjoern A. Zeeb COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE), 1028e93258fSBjoern A. Zeeb COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1038e93258fSBjoern A. Zeeb COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1048e93258fSBjoern A. Zeeb COUNTRY_REGD("ZW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1058e93258fSBjoern A. Zeeb COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1068e93258fSBjoern A. Zeeb COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1078e93258fSBjoern A. Zeeb COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN), 108e2340276SBjoern A. Zeeb COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1098e93258fSBjoern A. Zeeb COUNTRY_REGD("IN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1108e93258fSBjoern A. Zeeb COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1118e93258fSBjoern A. Zeeb COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC), 112e2340276SBjoern A. Zeeb COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1138e93258fSBjoern A. Zeeb COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1148e93258fSBjoern A. Zeeb COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 115*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1168e93258fSBjoern A. Zeeb COUNTRY_REGD("LK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 117*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_ETSI), 118*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_THAILAND), 1198e93258fSBjoern A. Zeeb COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 120e2340276SBjoern A. Zeeb COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA), 121e2340276SBjoern A. Zeeb COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA), 122e2340276SBjoern A. Zeeb COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1238e93258fSBjoern A. Zeeb COUNTRY_REGD("CA", RTW89_IC, RTW89_IC, RTW89_IC), 124e2340276SBjoern A. Zeeb COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_MKK), 125e2340276SBjoern A. Zeeb COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_FCC), 126e2340276SBjoern A. Zeeb COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_FCC), 1278e93258fSBjoern A. Zeeb COUNTRY_REGD("TT", RTW89_FCC, RTW89_FCC, RTW89_NA), 1288e93258fSBjoern A. Zeeb COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1298e93258fSBjoern A. Zeeb COUNTRY_REGD("AF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 130e2340276SBjoern A. Zeeb COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1318e93258fSBjoern A. Zeeb COUNTRY_REGD("AS", RTW89_FCC, RTW89_FCC, RTW89_NA), 1328e93258fSBjoern A. Zeeb COUNTRY_REGD("AD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1338e93258fSBjoern A. Zeeb COUNTRY_REGD("AO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 134e2340276SBjoern A. Zeeb COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1358e93258fSBjoern A. Zeeb COUNTRY_REGD("AQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 136e2340276SBjoern A. Zeeb COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_FCC), 137e2340276SBjoern A. Zeeb COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 138e2340276SBjoern A. Zeeb COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_FCC), 139e2340276SBjoern A. Zeeb COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_FCC), 140e2340276SBjoern A. Zeeb COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_FCC), 1418e93258fSBjoern A. Zeeb COUNTRY_REGD("BY", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1428e93258fSBjoern A. Zeeb COUNTRY_REGD("BZ", RTW89_FCC, RTW89_FCC, RTW89_NA), 1438e93258fSBjoern A. Zeeb COUNTRY_REGD("BJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 144e2340276SBjoern A. Zeeb COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_FCC), 1458e93258fSBjoern A. Zeeb COUNTRY_REGD("BT", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 146e2340276SBjoern A. Zeeb COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1478e93258fSBjoern A. Zeeb COUNTRY_REGD("BV", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1488e93258fSBjoern A. Zeeb COUNTRY_REGD("IO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 149e2340276SBjoern A. Zeeb COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_FCC), 1508e93258fSBjoern A. Zeeb COUNTRY_REGD("BN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 151*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1528e93258fSBjoern A. Zeeb COUNTRY_REGD("MM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 153e2340276SBjoern A. Zeeb COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1548e93258fSBjoern A. Zeeb COUNTRY_REGD("CM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1558e93258fSBjoern A. Zeeb COUNTRY_REGD("CV", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 156e2340276SBjoern A. Zeeb COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_FCC), 1578e93258fSBjoern A. Zeeb COUNTRY_REGD("CF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 158e2340276SBjoern A. Zeeb COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1598e93258fSBjoern A. Zeeb COUNTRY_REGD("CX", RTW89_ACMA, RTW89_ACMA, RTW89_NA), 160e2340276SBjoern A. Zeeb COUNTRY_REGD("CC", RTW89_ACMA, RTW89_ACMA, RTW89_NA), 161e2340276SBjoern A. Zeeb COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1628e93258fSBjoern A. Zeeb COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1638e93258fSBjoern A. Zeeb COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1648e93258fSBjoern A. Zeeb COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1658e93258fSBjoern A. Zeeb COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 166e2340276SBjoern A. Zeeb COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 167*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_NA), 168e2340276SBjoern A. Zeeb COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1698e93258fSBjoern A. Zeeb COUNTRY_REGD("ER", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1708e93258fSBjoern A. Zeeb COUNTRY_REGD("ET", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1718e93258fSBjoern A. Zeeb COUNTRY_REGD("FK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1728e93258fSBjoern A. Zeeb COUNTRY_REGD("FO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1738e93258fSBjoern A. Zeeb COUNTRY_REGD("FJ", RTW89_FCC, RTW89_FCC, RTW89_NA), 1748e93258fSBjoern A. Zeeb COUNTRY_REGD("GF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1758e93258fSBjoern A. Zeeb COUNTRY_REGD("PF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1768e93258fSBjoern A. Zeeb COUNTRY_REGD("TF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1778e93258fSBjoern A. Zeeb COUNTRY_REGD("GA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 178e2340276SBjoern A. Zeeb COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1798e93258fSBjoern A. Zeeb COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1808e93258fSBjoern A. Zeeb COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1818e93258fSBjoern A. Zeeb COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 182e2340276SBjoern A. Zeeb COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC), 1838e93258fSBjoern A. Zeeb COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1848e93258fSBjoern A. Zeeb COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_NA), 1858e93258fSBjoern A. Zeeb COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 186e2340276SBjoern A. Zeeb COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1878e93258fSBjoern A. Zeeb COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 188*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_NA), 189*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_FCC), 1908e93258fSBjoern A. Zeeb COUNTRY_REGD("HM", RTW89_ACMA, RTW89_ACMA, RTW89_NA), 1918e93258fSBjoern A. Zeeb COUNTRY_REGD("VA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1928e93258fSBjoern A. Zeeb COUNTRY_REGD("IM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1938e93258fSBjoern A. Zeeb COUNTRY_REGD("JE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1948e93258fSBjoern A. Zeeb COUNTRY_REGD("KI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 195*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("XK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 196*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("LA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 1978e93258fSBjoern A. Zeeb COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1988e93258fSBjoern A. Zeeb COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 1998e93258fSBjoern A. Zeeb COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 200e2340276SBjoern A. Zeeb COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 2018e93258fSBjoern A. Zeeb COUNTRY_REGD("MW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2028e93258fSBjoern A. Zeeb COUNTRY_REGD("MV", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2038e93258fSBjoern A. Zeeb COUNTRY_REGD("ML", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2048e93258fSBjoern A. Zeeb COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_NA), 2058e93258fSBjoern A. Zeeb COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2068e93258fSBjoern A. Zeeb COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 207e2340276SBjoern A. Zeeb COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 2088e93258fSBjoern A. Zeeb COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2098e93258fSBjoern A. Zeeb COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_NA), 210e2340276SBjoern A. Zeeb COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 211*6d67aabdSBjoern A. Zeeb COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 2128e93258fSBjoern A. Zeeb COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2138e93258fSBjoern A. Zeeb COUNTRY_REGD("NR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2148e93258fSBjoern A. Zeeb COUNTRY_REGD("NP", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2158e93258fSBjoern A. Zeeb COUNTRY_REGD("NC", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2168e93258fSBjoern A. Zeeb COUNTRY_REGD("NE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2178e93258fSBjoern A. Zeeb COUNTRY_REGD("NU", RTW89_ACMA, RTW89_ACMA, RTW89_NA), 2188e93258fSBjoern A. Zeeb COUNTRY_REGD("NF", RTW89_ACMA, RTW89_ACMA, RTW89_NA), 2198e93258fSBjoern A. Zeeb COUNTRY_REGD("MP", RTW89_FCC, RTW89_FCC, RTW89_NA), 2208e93258fSBjoern A. Zeeb COUNTRY_REGD("PW", RTW89_FCC, RTW89_FCC, RTW89_NA), 2218e93258fSBjoern A. Zeeb COUNTRY_REGD("RE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2228e93258fSBjoern A. Zeeb COUNTRY_REGD("RW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2238e93258fSBjoern A. Zeeb COUNTRY_REGD("SH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 224e2340276SBjoern A. Zeeb COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_FCC), 225e2340276SBjoern A. Zeeb COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_FCC), 2268e93258fSBjoern A. Zeeb COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_NA), 2278e93258fSBjoern A. Zeeb COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_NA), 2288e93258fSBjoern A. Zeeb COUNTRY_REGD("PM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2298e93258fSBjoern A. Zeeb COUNTRY_REGD("VC", RTW89_FCC, RTW89_FCC, RTW89_NA), 2308e93258fSBjoern A. Zeeb COUNTRY_REGD("WS", RTW89_FCC, RTW89_FCC, RTW89_NA), 2318e93258fSBjoern A. Zeeb COUNTRY_REGD("SM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 232e2340276SBjoern A. Zeeb COUNTRY_REGD("ST", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2338e93258fSBjoern A. Zeeb COUNTRY_REGD("SC", RTW89_FCC, RTW89_FCC, RTW89_NA), 234e2340276SBjoern A. Zeeb COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 2358e93258fSBjoern A. Zeeb COUNTRY_REGD("SB", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2368e93258fSBjoern A. Zeeb COUNTRY_REGD("SO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2378e93258fSBjoern A. Zeeb COUNTRY_REGD("GS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 238e2340276SBjoern A. Zeeb COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_FCC), 2398e93258fSBjoern A. Zeeb COUNTRY_REGD("SJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2408e93258fSBjoern A. Zeeb COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 241e2340276SBjoern A. Zeeb COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 2428e93258fSBjoern A. Zeeb COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 243e2340276SBjoern A. Zeeb COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 2448e93258fSBjoern A. Zeeb COUNTRY_REGD("TK", RTW89_ACMA, RTW89_ACMA, RTW89_NA), 2458e93258fSBjoern A. Zeeb COUNTRY_REGD("TO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2468e93258fSBjoern A. Zeeb COUNTRY_REGD("TM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2478e93258fSBjoern A. Zeeb COUNTRY_REGD("TC", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2488e93258fSBjoern A. Zeeb COUNTRY_REGD("TV", RTW89_ETSI, RTW89_NA, RTW89_NA), 2498e93258fSBjoern A. Zeeb COUNTRY_REGD("UG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2508e93258fSBjoern A. Zeeb COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_NA), 251e2340276SBjoern A. Zeeb COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), 2528e93258fSBjoern A. Zeeb COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2538e93258fSBjoern A. Zeeb COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2548e93258fSBjoern A. Zeeb COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2558e93258fSBjoern A. Zeeb COUNTRY_REGD("ZM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2568e93258fSBjoern A. Zeeb COUNTRY_REGD("IR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2578e93258fSBjoern A. Zeeb COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), 2588e93258fSBjoern A. Zeeb }; 2598e93258fSBjoern A. Zeeb 260*6d67aabdSBjoern A. Zeeb static const char rtw89_alpha2_list_eu[][3] = { 261*6d67aabdSBjoern A. Zeeb "AT", 262*6d67aabdSBjoern A. Zeeb "BE", 263*6d67aabdSBjoern A. Zeeb "CY", 264*6d67aabdSBjoern A. Zeeb "CZ", 265*6d67aabdSBjoern A. Zeeb "DK", 266*6d67aabdSBjoern A. Zeeb "EE", 267*6d67aabdSBjoern A. Zeeb "FI", 268*6d67aabdSBjoern A. Zeeb "FR", 269*6d67aabdSBjoern A. Zeeb "DE", 270*6d67aabdSBjoern A. Zeeb "GR", 271*6d67aabdSBjoern A. Zeeb "HU", 272*6d67aabdSBjoern A. Zeeb "IS", 273*6d67aabdSBjoern A. Zeeb "IE", 274*6d67aabdSBjoern A. Zeeb "IT", 275*6d67aabdSBjoern A. Zeeb "LV", 276*6d67aabdSBjoern A. Zeeb "LI", 277*6d67aabdSBjoern A. Zeeb "LT", 278*6d67aabdSBjoern A. Zeeb "LU", 279*6d67aabdSBjoern A. Zeeb "MT", 280*6d67aabdSBjoern A. Zeeb "MC", 281*6d67aabdSBjoern A. Zeeb "NL", 282*6d67aabdSBjoern A. Zeeb "NO", 283*6d67aabdSBjoern A. Zeeb "PL", 284*6d67aabdSBjoern A. Zeeb "PT", 285*6d67aabdSBjoern A. Zeeb "SK", 286*6d67aabdSBjoern A. Zeeb "SI", 287*6d67aabdSBjoern A. Zeeb "ES", 288*6d67aabdSBjoern A. Zeeb "SE", 289*6d67aabdSBjoern A. Zeeb "CH", 290*6d67aabdSBjoern A. Zeeb "BG", 291*6d67aabdSBjoern A. Zeeb "HR", 292*6d67aabdSBjoern A. Zeeb "RO", 293*6d67aabdSBjoern A. Zeeb }; 294*6d67aabdSBjoern A. Zeeb 295*6d67aabdSBjoern A. Zeeb static const struct rtw89_regd *rtw89_regd_find_reg_by_name(const char *alpha2) 2968e93258fSBjoern A. Zeeb { 2978e93258fSBjoern A. Zeeb u32 i; 2988e93258fSBjoern A. Zeeb 2998e93258fSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(rtw89_regd_map); i++) { 3008e93258fSBjoern A. Zeeb if (!memcmp(rtw89_regd_map[i].alpha2, alpha2, 2)) 3018e93258fSBjoern A. Zeeb return &rtw89_regd_map[i]; 3028e93258fSBjoern A. Zeeb } 3038e93258fSBjoern A. Zeeb 3048e93258fSBjoern A. Zeeb return &rtw89_ww_regd; 3058e93258fSBjoern A. Zeeb } 3068e93258fSBjoern A. Zeeb 307e2340276SBjoern A. Zeeb static bool rtw89_regd_is_ww(const struct rtw89_regd *regd) 3088e93258fSBjoern A. Zeeb { 3098e93258fSBjoern A. Zeeb return regd == &rtw89_ww_regd; 3108e93258fSBjoern A. Zeeb } 3118e93258fSBjoern A. Zeeb 312*6d67aabdSBjoern A. Zeeb static u8 rtw89_regd_get_index(const struct rtw89_regd *regd) 313*6d67aabdSBjoern A. Zeeb { 314*6d67aabdSBjoern A. Zeeb BUILD_BUG_ON(ARRAY_SIZE(rtw89_regd_map) > RTW89_REGD_MAX_COUNTRY_NUM); 315*6d67aabdSBjoern A. Zeeb 316*6d67aabdSBjoern A. Zeeb if (rtw89_regd_is_ww(regd)) 317*6d67aabdSBjoern A. Zeeb return RTW89_REGD_MAX_COUNTRY_NUM; 318*6d67aabdSBjoern A. Zeeb 319*6d67aabdSBjoern A. Zeeb return regd - rtw89_regd_map; 320*6d67aabdSBjoern A. Zeeb } 321*6d67aabdSBjoern A. Zeeb 322*6d67aabdSBjoern A. Zeeb static u8 rtw89_regd_get_index_by_name(const char *alpha2) 323*6d67aabdSBjoern A. Zeeb { 324*6d67aabdSBjoern A. Zeeb const struct rtw89_regd *regd; 325*6d67aabdSBjoern A. Zeeb 326*6d67aabdSBjoern A. Zeeb regd = rtw89_regd_find_reg_by_name(alpha2); 327*6d67aabdSBjoern A. Zeeb return rtw89_regd_get_index(regd); 328*6d67aabdSBjoern A. Zeeb } 329*6d67aabdSBjoern A. Zeeb 3308e93258fSBjoern A. Zeeb #define rtw89_debug_regd(_dev, _regd, _desc, _argv...) \ 3318e93258fSBjoern A. Zeeb do { \ 3328e93258fSBjoern A. Zeeb typeof(_regd) __r = _regd; \ 3338e93258fSBjoern A. Zeeb rtw89_debug(_dev, RTW89_DBG_REGD, _desc \ 3348e93258fSBjoern A. Zeeb ": %c%c: mapping txregd to {2g: %d, 5g: %d, 6g: %d}\n", \ 3358e93258fSBjoern A. Zeeb ##_argv, __r->alpha2[0], __r->alpha2[1], \ 3368e93258fSBjoern A. Zeeb __r->txpwr_regd[RTW89_BAND_2G], \ 3378e93258fSBjoern A. Zeeb __r->txpwr_regd[RTW89_BAND_5G], \ 3388e93258fSBjoern A. Zeeb __r->txpwr_regd[RTW89_BAND_6G]); \ 3398e93258fSBjoern A. Zeeb } while (0) 3408e93258fSBjoern A. Zeeb 341e2340276SBjoern A. Zeeb static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev, 342e2340276SBjoern A. Zeeb struct wiphy *wiphy) 343e2340276SBjoern A. Zeeb { 344*6d67aabdSBjoern A. Zeeb struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; 345e2340276SBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 346e2340276SBjoern A. Zeeb struct ieee80211_supported_band *sband; 347*6d67aabdSBjoern A. Zeeb struct rtw89_acpi_dsm_result res = {}; 348*6d67aabdSBjoern A. Zeeb bool enable_by_fcc; 349*6d67aabdSBjoern A. Zeeb bool enable_by_ic; 350e2340276SBjoern A. Zeeb int ret; 351e2340276SBjoern A. Zeeb u8 val; 352*6d67aabdSBjoern A. Zeeb int i; 353e2340276SBjoern A. Zeeb 354e2340276SBjoern A. Zeeb sband = wiphy->bands[NL80211_BAND_5GHZ]; 355e2340276SBjoern A. Zeeb if (!sband) 356e2340276SBjoern A. Zeeb return; 357e2340276SBjoern A. Zeeb 358*6d67aabdSBjoern A. Zeeb if (!chip->support_unii4) { 359*6d67aabdSBjoern A. Zeeb sband->n_channels -= RTW89_5GHZ_UNII4_CHANNEL_NUM; 360*6d67aabdSBjoern A. Zeeb return; 361*6d67aabdSBjoern A. Zeeb } 362*6d67aabdSBjoern A. Zeeb 363*6d67aabdSBjoern A. Zeeb bitmap_fill(regulatory->block_unii4, RTW89_REGD_MAX_COUNTRY_NUM); 364*6d67aabdSBjoern A. Zeeb 365*6d67aabdSBjoern A. Zeeb ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_UNII4_SUP, &res); 366*6d67aabdSBjoern A. Zeeb if (ret) { 367*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 368*6d67aabdSBjoern A. Zeeb "acpi: cannot eval unii 4: %d\n", ret); 369*6d67aabdSBjoern A. Zeeb enable_by_fcc = true; 370*6d67aabdSBjoern A. Zeeb enable_by_ic = false; 371*6d67aabdSBjoern A. Zeeb goto bottom; 372*6d67aabdSBjoern A. Zeeb } 373*6d67aabdSBjoern A. Zeeb 374*6d67aabdSBjoern A. Zeeb val = res.u.value; 375*6d67aabdSBjoern A. Zeeb enable_by_fcc = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_FCC); 376*6d67aabdSBjoern A. Zeeb enable_by_ic = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_IC); 377*6d67aabdSBjoern A. Zeeb 378*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 379*6d67aabdSBjoern A. Zeeb "acpi: eval if allow unii-4: 0x%x\n", val); 380*6d67aabdSBjoern A. Zeeb 381*6d67aabdSBjoern A. Zeeb bottom: 382*6d67aabdSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(rtw89_regd_map); i++) { 383*6d67aabdSBjoern A. Zeeb const struct rtw89_regd *regd = &rtw89_regd_map[i]; 384*6d67aabdSBjoern A. Zeeb 385*6d67aabdSBjoern A. Zeeb switch (regd->txpwr_regd[RTW89_BAND_5G]) { 386*6d67aabdSBjoern A. Zeeb case RTW89_FCC: 387*6d67aabdSBjoern A. Zeeb if (enable_by_fcc) 388*6d67aabdSBjoern A. Zeeb clear_bit(i, regulatory->block_unii4); 389*6d67aabdSBjoern A. Zeeb break; 390*6d67aabdSBjoern A. Zeeb case RTW89_IC: 391*6d67aabdSBjoern A. Zeeb if (enable_by_ic) 392*6d67aabdSBjoern A. Zeeb clear_bit(i, regulatory->block_unii4); 393*6d67aabdSBjoern A. Zeeb break; 394*6d67aabdSBjoern A. Zeeb default: 395*6d67aabdSBjoern A. Zeeb break; 396*6d67aabdSBjoern A. Zeeb } 397*6d67aabdSBjoern A. Zeeb } 398*6d67aabdSBjoern A. Zeeb } 399*6d67aabdSBjoern A. Zeeb 400*6d67aabdSBjoern A. Zeeb static void __rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev, bool block, 401*6d67aabdSBjoern A. Zeeb const char *alpha2) 402*6d67aabdSBjoern A. Zeeb { 403*6d67aabdSBjoern A. Zeeb struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; 404*6d67aabdSBjoern A. Zeeb u8 index; 405*6d67aabdSBjoern A. Zeeb 406*6d67aabdSBjoern A. Zeeb index = rtw89_regd_get_index_by_name(alpha2); 407*6d67aabdSBjoern A. Zeeb if (index == RTW89_REGD_MAX_COUNTRY_NUM) { 408*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, "%s: unknown alpha2 %c%c\n", 409*6d67aabdSBjoern A. Zeeb __func__, alpha2[0], alpha2[1]); 410*6d67aabdSBjoern A. Zeeb return; 411*6d67aabdSBjoern A. Zeeb } 412*6d67aabdSBjoern A. Zeeb 413*6d67aabdSBjoern A. Zeeb if (block) 414*6d67aabdSBjoern A. Zeeb set_bit(index, regulatory->block_6ghz); 415*6d67aabdSBjoern A. Zeeb else 416*6d67aabdSBjoern A. Zeeb clear_bit(index, regulatory->block_6ghz); 417*6d67aabdSBjoern A. Zeeb } 418*6d67aabdSBjoern A. Zeeb 419*6d67aabdSBjoern A. Zeeb static void rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev) 420*6d67aabdSBjoern A. Zeeb { 421*6d67aabdSBjoern A. Zeeb struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; 422*6d67aabdSBjoern A. Zeeb const struct rtw89_acpi_country_code *country; 423*6d67aabdSBjoern A. Zeeb const struct rtw89_acpi_policy_6ghz *ptr; 424*6d67aabdSBjoern A. Zeeb struct rtw89_acpi_dsm_result res = {}; 425*6d67aabdSBjoern A. Zeeb bool to_block; 426*6d67aabdSBjoern A. Zeeb int i, j; 427*6d67aabdSBjoern A. Zeeb int ret; 428*6d67aabdSBjoern A. Zeeb 429*6d67aabdSBjoern A. Zeeb ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_BP, &res); 430*6d67aabdSBjoern A. Zeeb if (ret) { 431*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 432*6d67aabdSBjoern A. Zeeb "acpi: cannot eval policy 6ghz: %d\n", ret); 433*6d67aabdSBjoern A. Zeeb return; 434*6d67aabdSBjoern A. Zeeb } 435*6d67aabdSBjoern A. Zeeb 436*6d67aabdSBjoern A. Zeeb ptr = res.u.policy_6ghz; 437*6d67aabdSBjoern A. Zeeb 438*6d67aabdSBjoern A. Zeeb switch (ptr->policy_mode) { 439*6d67aabdSBjoern A. Zeeb case RTW89_ACPI_POLICY_BLOCK: 440*6d67aabdSBjoern A. Zeeb to_block = true; 441*6d67aabdSBjoern A. Zeeb break; 442*6d67aabdSBjoern A. Zeeb case RTW89_ACPI_POLICY_ALLOW: 443*6d67aabdSBjoern A. Zeeb to_block = false; 444*6d67aabdSBjoern A. Zeeb /* only below list is allowed; block all first */ 445*6d67aabdSBjoern A. Zeeb bitmap_fill(regulatory->block_6ghz, RTW89_REGD_MAX_COUNTRY_NUM); 446*6d67aabdSBjoern A. Zeeb break; 447*6d67aabdSBjoern A. Zeeb default: 448*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 449*6d67aabdSBjoern A. Zeeb "%s: unknown policy mode: %d\n", __func__, 450*6d67aabdSBjoern A. Zeeb ptr->policy_mode); 451*6d67aabdSBjoern A. Zeeb goto out; 452*6d67aabdSBjoern A. Zeeb } 453*6d67aabdSBjoern A. Zeeb 454*6d67aabdSBjoern A. Zeeb for (i = 0; i < ptr->country_count; i++) { 455*6d67aabdSBjoern A. Zeeb country = &ptr->country_list[i]; 456*6d67aabdSBjoern A. Zeeb if (memcmp("EU", country->alpha2, 2) != 0) { 457*6d67aabdSBjoern A. Zeeb __rtw89_regd_setup_policy_6ghz(rtwdev, to_block, 458*6d67aabdSBjoern A. Zeeb country->alpha2); 459*6d67aabdSBjoern A. Zeeb continue; 460*6d67aabdSBjoern A. Zeeb } 461*6d67aabdSBjoern A. Zeeb 462*6d67aabdSBjoern A. Zeeb for (j = 0; j < ARRAY_SIZE(rtw89_alpha2_list_eu); j++) 463*6d67aabdSBjoern A. Zeeb __rtw89_regd_setup_policy_6ghz(rtwdev, to_block, 464*6d67aabdSBjoern A. Zeeb rtw89_alpha2_list_eu[j]); 465*6d67aabdSBjoern A. Zeeb } 466*6d67aabdSBjoern A. Zeeb 467*6d67aabdSBjoern A. Zeeb out: 468*6d67aabdSBjoern A. Zeeb kfree(ptr); 469*6d67aabdSBjoern A. Zeeb } 470*6d67aabdSBjoern A. Zeeb 471*6d67aabdSBjoern A. Zeeb static void rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev *rtwdev) 472*6d67aabdSBjoern A. Zeeb { 473*6d67aabdSBjoern A. Zeeb struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; 474*6d67aabdSBjoern A. Zeeb const struct rtw89_acpi_policy_6ghz_sp *ptr; 475*6d67aabdSBjoern A. Zeeb struct rtw89_acpi_dsm_result res = {}; 476*6d67aabdSBjoern A. Zeeb bool enable_by_us; 477*6d67aabdSBjoern A. Zeeb int ret; 478*6d67aabdSBjoern A. Zeeb int i; 479*6d67aabdSBjoern A. Zeeb 480*6d67aabdSBjoern A. Zeeb ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP, &res); 481*6d67aabdSBjoern A. Zeeb if (ret) { 482*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 483*6d67aabdSBjoern A. Zeeb "acpi: cannot eval policy 6ghz-sp: %d\n", ret); 484*6d67aabdSBjoern A. Zeeb return; 485*6d67aabdSBjoern A. Zeeb } 486*6d67aabdSBjoern A. Zeeb 487*6d67aabdSBjoern A. Zeeb ptr = res.u.policy_6ghz_sp; 488*6d67aabdSBjoern A. Zeeb 489*6d67aabdSBjoern A. Zeeb switch (ptr->override) { 490*6d67aabdSBjoern A. Zeeb default: 491*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 492*6d67aabdSBjoern A. Zeeb "%s: unknown override case: %d\n", __func__, 493*6d67aabdSBjoern A. Zeeb ptr->override); 494*6d67aabdSBjoern A. Zeeb fallthrough; 495*6d67aabdSBjoern A. Zeeb case 0: 496*6d67aabdSBjoern A. Zeeb goto out; 497*6d67aabdSBjoern A. Zeeb case 1: 498*6d67aabdSBjoern A. Zeeb break; 499*6d67aabdSBjoern A. Zeeb } 500*6d67aabdSBjoern A. Zeeb 501*6d67aabdSBjoern A. Zeeb bitmap_fill(regulatory->block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM); 502*6d67aabdSBjoern A. Zeeb 503*6d67aabdSBjoern A. Zeeb enable_by_us = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_US); 504*6d67aabdSBjoern A. Zeeb 505*6d67aabdSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(rtw89_regd_map); i++) { 506*6d67aabdSBjoern A. Zeeb const struct rtw89_regd *tmp = &rtw89_regd_map[i]; 507*6d67aabdSBjoern A. Zeeb 508*6d67aabdSBjoern A. Zeeb if (enable_by_us && memcmp(tmp->alpha2, "US", 2) == 0) 509*6d67aabdSBjoern A. Zeeb clear_bit(i, regulatory->block_6ghz_sp); 510*6d67aabdSBjoern A. Zeeb } 511*6d67aabdSBjoern A. Zeeb 512*6d67aabdSBjoern A. Zeeb out: 513*6d67aabdSBjoern A. Zeeb kfree(ptr); 514e2340276SBjoern A. Zeeb } 515e2340276SBjoern A. Zeeb 516e2340276SBjoern A. Zeeb static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy) 517e2340276SBjoern A. Zeeb { 518e2340276SBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 519e2340276SBjoern A. Zeeb bool chip_support_6ghz = chip->support_bands & BIT(NL80211_BAND_6GHZ); 520e2340276SBjoern A. Zeeb bool regd_allow_6ghz = chip_support_6ghz; 521e2340276SBjoern A. Zeeb struct ieee80211_supported_band *sband; 522*6d67aabdSBjoern A. Zeeb struct rtw89_acpi_dsm_result res = {}; 523e2340276SBjoern A. Zeeb int ret; 524e2340276SBjoern A. Zeeb u8 val; 525e2340276SBjoern A. Zeeb 526e2340276SBjoern A. Zeeb if (!chip_support_6ghz) 527e2340276SBjoern A. Zeeb goto bottom; 528e2340276SBjoern A. Zeeb 529*6d67aabdSBjoern A. Zeeb ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &res); 530e2340276SBjoern A. Zeeb if (ret) { 531e2340276SBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 532e2340276SBjoern A. Zeeb "acpi: cannot eval 6ghz: %d\n", ret); 533e2340276SBjoern A. Zeeb goto bottom; 534e2340276SBjoern A. Zeeb } 535e2340276SBjoern A. Zeeb 536*6d67aabdSBjoern A. Zeeb val = res.u.value; 537*6d67aabdSBjoern A. Zeeb 538e2340276SBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 539e2340276SBjoern A. Zeeb "acpi: eval if disallow 6ghz: %d\n", val); 540e2340276SBjoern A. Zeeb 541e2340276SBjoern A. Zeeb switch (val) { 542e2340276SBjoern A. Zeeb case 0: 543e2340276SBjoern A. Zeeb regd_allow_6ghz = true; 544e2340276SBjoern A. Zeeb break; 545e2340276SBjoern A. Zeeb case 1: 546e2340276SBjoern A. Zeeb regd_allow_6ghz = false; 547e2340276SBjoern A. Zeeb break; 548e2340276SBjoern A. Zeeb default: 549e2340276SBjoern A. Zeeb break; 550e2340276SBjoern A. Zeeb } 551e2340276SBjoern A. Zeeb 552e2340276SBjoern A. Zeeb bottom: 553e2340276SBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow 6ghz: %d\n", 554e2340276SBjoern A. Zeeb regd_allow_6ghz); 555e2340276SBjoern A. Zeeb 556*6d67aabdSBjoern A. Zeeb if (regd_allow_6ghz) { 557*6d67aabdSBjoern A. Zeeb rtw89_regd_setup_policy_6ghz(rtwdev); 558*6d67aabdSBjoern A. Zeeb rtw89_regd_setup_policy_6ghz_sp(rtwdev); 559e2340276SBjoern A. Zeeb return; 560*6d67aabdSBjoern A. Zeeb } 561e2340276SBjoern A. Zeeb 562e2340276SBjoern A. Zeeb sband = wiphy->bands[NL80211_BAND_6GHZ]; 563e2340276SBjoern A. Zeeb if (!sband) 564e2340276SBjoern A. Zeeb return; 565e2340276SBjoern A. Zeeb 566e2340276SBjoern A. Zeeb wiphy->bands[NL80211_BAND_6GHZ] = NULL; 567*6d67aabdSBjoern A. Zeeb kfree((__force void *)sband->iftype_data); 568e2340276SBjoern A. Zeeb kfree(sband); 569e2340276SBjoern A. Zeeb } 570e2340276SBjoern A. Zeeb 571e2340276SBjoern A. Zeeb int rtw89_regd_setup(struct rtw89_dev *rtwdev) 572e2340276SBjoern A. Zeeb { 573e2340276SBjoern A. Zeeb struct wiphy *wiphy = rtwdev->hw->wiphy; 574e2340276SBjoern A. Zeeb 575e2340276SBjoern A. Zeeb if (!wiphy) 576e2340276SBjoern A. Zeeb return -EINVAL; 577e2340276SBjoern A. Zeeb 578e2340276SBjoern A. Zeeb rtw89_regd_setup_unii4(rtwdev, wiphy); 579e2340276SBjoern A. Zeeb rtw89_regd_setup_6ghz(rtwdev, wiphy); 580e2340276SBjoern A. Zeeb 581e2340276SBjoern A. Zeeb wiphy->reg_notifier = rtw89_regd_notifier; 582e2340276SBjoern A. Zeeb return 0; 583e2340276SBjoern A. Zeeb } 584e2340276SBjoern A. Zeeb 5858e93258fSBjoern A. Zeeb int rtw89_regd_init(struct rtw89_dev *rtwdev, 5868e93258fSBjoern A. Zeeb void (*reg_notifier)(struct wiphy *wiphy, 5878e93258fSBjoern A. Zeeb struct regulatory_request *request)) 5888e93258fSBjoern A. Zeeb { 589e2340276SBjoern A. Zeeb struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; 590e2340276SBjoern A. Zeeb const struct rtw89_regd *chip_regd; 5918e93258fSBjoern A. Zeeb struct wiphy *wiphy = rtwdev->hw->wiphy; 5928e93258fSBjoern A. Zeeb int ret; 5938e93258fSBjoern A. Zeeb 594e2340276SBjoern A. Zeeb regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; 595e2340276SBjoern A. Zeeb 5968e93258fSBjoern A. Zeeb if (!wiphy) 5978e93258fSBjoern A. Zeeb return -EINVAL; 5988e93258fSBjoern A. Zeeb 5998e93258fSBjoern A. Zeeb chip_regd = rtw89_regd_find_reg_by_name(rtwdev->efuse.country_code); 6008e93258fSBjoern A. Zeeb #if defined(__FreeBSD__) 601e2340276SBjoern A. Zeeb rtwdev->regulatory.regd = chip_regd; 6028e93258fSBjoern A. Zeeb #endif 6038e93258fSBjoern A. Zeeb if (!rtw89_regd_is_ww(chip_regd)) { 6048e93258fSBjoern A. Zeeb #if defined(__linux__) 605e2340276SBjoern A. Zeeb rtwdev->regulatory.regd = chip_regd; 6068e93258fSBjoern A. Zeeb #endif 6078e93258fSBjoern A. Zeeb /* Ignore country ie if there is a country domain programmed in chip */ 6088e93258fSBjoern A. Zeeb wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; 6098e93258fSBjoern A. Zeeb wiphy->regulatory_flags |= REGULATORY_STRICT_REG; 6108e93258fSBjoern A. Zeeb 611e2340276SBjoern A. Zeeb ret = regulatory_hint(rtwdev->hw->wiphy, 612e2340276SBjoern A. Zeeb rtwdev->regulatory.regd->alpha2); 6138e93258fSBjoern A. Zeeb if (ret) 6148e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret); 6158e93258fSBjoern A. Zeeb 6168e93258fSBjoern A. Zeeb rtw89_debug_regd(rtwdev, chip_regd, "efuse country code"); 6178e93258fSBjoern A. Zeeb return 0; 6188e93258fSBjoern A. Zeeb } 6198e93258fSBjoern A. Zeeb 620e2340276SBjoern A. Zeeb rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd, 6218e93258fSBjoern A. Zeeb "worldwide roaming chip, follow the setting of stack"); 6228e93258fSBjoern A. Zeeb return 0; 6238e93258fSBjoern A. Zeeb } 6248e93258fSBjoern A. Zeeb 625*6d67aabdSBjoern A. Zeeb static void rtw89_regd_apply_policy_unii4(struct rtw89_dev *rtwdev, 626*6d67aabdSBjoern A. Zeeb struct wiphy *wiphy) 627*6d67aabdSBjoern A. Zeeb { 628*6d67aabdSBjoern A. Zeeb struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; 629*6d67aabdSBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 630*6d67aabdSBjoern A. Zeeb const struct rtw89_regd *regd = regulatory->regd; 631*6d67aabdSBjoern A. Zeeb struct ieee80211_supported_band *sband; 632*6d67aabdSBjoern A. Zeeb u8 index; 633*6d67aabdSBjoern A. Zeeb int i; 634*6d67aabdSBjoern A. Zeeb 635*6d67aabdSBjoern A. Zeeb sband = wiphy->bands[NL80211_BAND_5GHZ]; 636*6d67aabdSBjoern A. Zeeb if (!sband) 637*6d67aabdSBjoern A. Zeeb return; 638*6d67aabdSBjoern A. Zeeb 639*6d67aabdSBjoern A. Zeeb if (!chip->support_unii4) 640*6d67aabdSBjoern A. Zeeb return; 641*6d67aabdSBjoern A. Zeeb 642*6d67aabdSBjoern A. Zeeb index = rtw89_regd_get_index(regd); 643*6d67aabdSBjoern A. Zeeb if (index != RTW89_REGD_MAX_COUNTRY_NUM && 644*6d67aabdSBjoern A. Zeeb !test_bit(index, regulatory->block_unii4)) 645*6d67aabdSBjoern A. Zeeb return; 646*6d67aabdSBjoern A. Zeeb 647*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c unii-4 is blocked by policy\n", 648*6d67aabdSBjoern A. Zeeb regd->alpha2[0], regd->alpha2[1]); 649*6d67aabdSBjoern A. Zeeb 650*6d67aabdSBjoern A. Zeeb for (i = RTW89_5GHZ_UNII4_START_INDEX; i < sband->n_channels; i++) 651*6d67aabdSBjoern A. Zeeb sband->channels[i].flags |= IEEE80211_CHAN_DISABLED; 652*6d67aabdSBjoern A. Zeeb } 653*6d67aabdSBjoern A. Zeeb 654*6d67aabdSBjoern A. Zeeb static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev, 655*6d67aabdSBjoern A. Zeeb struct wiphy *wiphy) 656*6d67aabdSBjoern A. Zeeb { 657*6d67aabdSBjoern A. Zeeb struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; 658*6d67aabdSBjoern A. Zeeb const struct rtw89_regd *regd = regulatory->regd; 659*6d67aabdSBjoern A. Zeeb struct ieee80211_supported_band *sband; 660*6d67aabdSBjoern A. Zeeb u8 index; 661*6d67aabdSBjoern A. Zeeb int i; 662*6d67aabdSBjoern A. Zeeb 663*6d67aabdSBjoern A. Zeeb index = rtw89_regd_get_index(regd); 664*6d67aabdSBjoern A. Zeeb if (index != RTW89_REGD_MAX_COUNTRY_NUM && 665*6d67aabdSBjoern A. Zeeb !test_bit(index, regulatory->block_6ghz)) 666*6d67aabdSBjoern A. Zeeb return; 667*6d67aabdSBjoern A. Zeeb 668*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is blocked by policy\n", 669*6d67aabdSBjoern A. Zeeb regd->alpha2[0], regd->alpha2[1]); 670*6d67aabdSBjoern A. Zeeb 671*6d67aabdSBjoern A. Zeeb sband = wiphy->bands[NL80211_BAND_6GHZ]; 672*6d67aabdSBjoern A. Zeeb if (!sband) 673*6d67aabdSBjoern A. Zeeb return; 674*6d67aabdSBjoern A. Zeeb 675*6d67aabdSBjoern A. Zeeb for (i = 0; i < sband->n_channels; i++) 676*6d67aabdSBjoern A. Zeeb sband->channels[i].flags |= IEEE80211_CHAN_DISABLED; 677*6d67aabdSBjoern A. Zeeb } 678*6d67aabdSBjoern A. Zeeb 6798e93258fSBjoern A. Zeeb static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev, 6808e93258fSBjoern A. Zeeb struct wiphy *wiphy, 6818e93258fSBjoern A. Zeeb struct regulatory_request *request) 6828e93258fSBjoern A. Zeeb { 683e2340276SBjoern A. Zeeb rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(request->alpha2); 6848e93258fSBjoern A. Zeeb /* This notification might be set from the system of distros, 6858e93258fSBjoern A. Zeeb * and it does not expect the regulatory will be modified by 6868e93258fSBjoern A. Zeeb * connecting to an AP (i.e. country ie). 6878e93258fSBjoern A. Zeeb */ 6888e93258fSBjoern A. Zeeb if (request->initiator == NL80211_REGDOM_SET_BY_USER && 689e2340276SBjoern A. Zeeb !rtw89_regd_is_ww(rtwdev->regulatory.regd)) 6908e93258fSBjoern A. Zeeb wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; 6918e93258fSBjoern A. Zeeb else 6928e93258fSBjoern A. Zeeb wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE; 693*6d67aabdSBjoern A. Zeeb 694*6d67aabdSBjoern A. Zeeb rtw89_regd_apply_policy_unii4(rtwdev, wiphy); 695*6d67aabdSBjoern A. Zeeb rtw89_regd_apply_policy_6ghz(rtwdev, wiphy); 6968e93258fSBjoern A. Zeeb } 6978e93258fSBjoern A. Zeeb 6988e93258fSBjoern A. Zeeb void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) 6998e93258fSBjoern A. Zeeb { 7008e93258fSBjoern A. Zeeb struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 7018e93258fSBjoern A. Zeeb struct rtw89_dev *rtwdev = hw->priv; 7028e93258fSBjoern A. Zeeb 7038e93258fSBjoern A. Zeeb mutex_lock(&rtwdev->mutex); 7048e93258fSBjoern A. Zeeb rtw89_leave_ps_mode(rtwdev); 7058e93258fSBjoern A. Zeeb 7068e93258fSBjoern A. Zeeb if (wiphy->regd) { 7078e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 7088e93258fSBjoern A. Zeeb "There is a country domain programmed in chip, ignore notifications\n"); 7098e93258fSBjoern A. Zeeb goto exit; 7108e93258fSBjoern A. Zeeb } 7118e93258fSBjoern A. Zeeb rtw89_regd_notifier_apply(rtwdev, wiphy, request); 712e2340276SBjoern A. Zeeb rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd, 713e2340276SBjoern A. Zeeb "get from initiator %d, alpha2", 7148e93258fSBjoern A. Zeeb request->initiator); 7158e93258fSBjoern A. Zeeb 7168e93258fSBjoern A. Zeeb rtw89_core_set_chip_txpwr(rtwdev); 7178e93258fSBjoern A. Zeeb 7188e93258fSBjoern A. Zeeb exit: 7198e93258fSBjoern A. Zeeb mutex_unlock(&rtwdev->mutex); 7208e93258fSBjoern A. Zeeb } 721e2340276SBjoern A. Zeeb 722*6d67aabdSBjoern A. Zeeb /* Maximum Transmit Power field (@raw) can be EIRP or PSD. 723*6d67aabdSBjoern A. Zeeb * Both units are 0.5 dB-based. Return a constraint in dB. 724*6d67aabdSBjoern A. Zeeb */ 725*6d67aabdSBjoern A. Zeeb static s8 tpe_get_constraint(s8 raw) 726*6d67aabdSBjoern A. Zeeb { 727*6d67aabdSBjoern A. Zeeb const u8 hw_deviation = 3; /* unit: 0.5 dB */ 728*6d67aabdSBjoern A. Zeeb const u8 antenna_gain = 10; /* unit: 0.5 dB */ 729*6d67aabdSBjoern A. Zeeb const u8 array_gain = 6; /* unit: 0.5 dB */ 730*6d67aabdSBjoern A. Zeeb const u8 offset = hw_deviation + antenna_gain + array_gain; 731*6d67aabdSBjoern A. Zeeb 732*6d67aabdSBjoern A. Zeeb return (raw - offset) / 2; 733*6d67aabdSBjoern A. Zeeb } 734*6d67aabdSBjoern A. Zeeb 735*6d67aabdSBjoern A. Zeeb static void tpe_intersect_constraint(struct rtw89_reg_6ghz_tpe *tpe, s8 cstr) 736*6d67aabdSBjoern A. Zeeb { 737*6d67aabdSBjoern A. Zeeb if (tpe->valid) { 738*6d67aabdSBjoern A. Zeeb tpe->constraint = min(tpe->constraint, cstr); 739*6d67aabdSBjoern A. Zeeb return; 740*6d67aabdSBjoern A. Zeeb } 741*6d67aabdSBjoern A. Zeeb 742*6d67aabdSBjoern A. Zeeb tpe->constraint = cstr; 743*6d67aabdSBjoern A. Zeeb tpe->valid = true; 744*6d67aabdSBjoern A. Zeeb } 745*6d67aabdSBjoern A. Zeeb 746*6d67aabdSBjoern A. Zeeb static void tpe_deal_with_eirp(struct rtw89_reg_6ghz_tpe *tpe, 747*6d67aabdSBjoern A. Zeeb const struct ieee80211_parsed_tpe_eirp *eirp) 748*6d67aabdSBjoern A. Zeeb { 749*6d67aabdSBjoern A. Zeeb unsigned int i; 750*6d67aabdSBjoern A. Zeeb s8 cstr; 751*6d67aabdSBjoern A. Zeeb 752*6d67aabdSBjoern A. Zeeb if (!eirp->valid) 753*6d67aabdSBjoern A. Zeeb return; 754*6d67aabdSBjoern A. Zeeb 755*6d67aabdSBjoern A. Zeeb for (i = 0; i < eirp->count; i++) { 756*6d67aabdSBjoern A. Zeeb cstr = tpe_get_constraint(eirp->power[i]); 757*6d67aabdSBjoern A. Zeeb tpe_intersect_constraint(tpe, cstr); 758*6d67aabdSBjoern A. Zeeb } 759*6d67aabdSBjoern A. Zeeb } 760*6d67aabdSBjoern A. Zeeb 761*6d67aabdSBjoern A. Zeeb static s8 tpe_convert_psd_to_eirp(s8 psd) 762*6d67aabdSBjoern A. Zeeb { 763*6d67aabdSBjoern A. Zeeb static const unsigned int mlog20 = 1301; 764*6d67aabdSBjoern A. Zeeb 765*6d67aabdSBjoern A. Zeeb return psd + 10 * mlog20 / 1000; 766*6d67aabdSBjoern A. Zeeb } 767*6d67aabdSBjoern A. Zeeb 768*6d67aabdSBjoern A. Zeeb static void tpe_deal_with_psd(struct rtw89_reg_6ghz_tpe *tpe, 769*6d67aabdSBjoern A. Zeeb const struct ieee80211_parsed_tpe_psd *psd) 770*6d67aabdSBjoern A. Zeeb { 771*6d67aabdSBjoern A. Zeeb unsigned int i; 772*6d67aabdSBjoern A. Zeeb s8 cstr_psd; 773*6d67aabdSBjoern A. Zeeb s8 cstr; 774*6d67aabdSBjoern A. Zeeb 775*6d67aabdSBjoern A. Zeeb if (!psd->valid) 776*6d67aabdSBjoern A. Zeeb return; 777*6d67aabdSBjoern A. Zeeb 778*6d67aabdSBjoern A. Zeeb for (i = 0; i < psd->count; i++) { 779*6d67aabdSBjoern A. Zeeb cstr_psd = tpe_get_constraint(psd->power[i]); 780*6d67aabdSBjoern A. Zeeb cstr = tpe_convert_psd_to_eirp(cstr_psd); 781*6d67aabdSBjoern A. Zeeb tpe_intersect_constraint(tpe, cstr); 782*6d67aabdSBjoern A. Zeeb } 783*6d67aabdSBjoern A. Zeeb } 784*6d67aabdSBjoern A. Zeeb 785*6d67aabdSBjoern A. Zeeb static void rtw89_calculate_tpe(struct rtw89_dev *rtwdev, 786*6d67aabdSBjoern A. Zeeb struct rtw89_reg_6ghz_tpe *result_tpe, 787*6d67aabdSBjoern A. Zeeb const struct ieee80211_parsed_tpe *parsed_tpe) 788*6d67aabdSBjoern A. Zeeb { 789*6d67aabdSBjoern A. Zeeb static const u8 category = IEEE80211_TPE_CAT_6GHZ_DEFAULT; 790*6d67aabdSBjoern A. Zeeb 791*6d67aabdSBjoern A. Zeeb tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_local[category]); 792*6d67aabdSBjoern A. Zeeb tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_reg_client[category]); 793*6d67aabdSBjoern A. Zeeb tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_local[category]); 794*6d67aabdSBjoern A. Zeeb tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_reg_client[category]); 795*6d67aabdSBjoern A. Zeeb } 796*6d67aabdSBjoern A. Zeeb 797*6d67aabdSBjoern A. Zeeb static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev) 798e2340276SBjoern A. Zeeb { 799e2340276SBjoern A. Zeeb struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; 800*6d67aabdSBjoern A. Zeeb struct rtw89_reg_6ghz_tpe new = {}; 801*6d67aabdSBjoern A. Zeeb struct rtw89_vif *rtwvif; 802*6d67aabdSBjoern A. Zeeb bool changed = false; 803*6d67aabdSBjoern A. Zeeb 804*6d67aabdSBjoern A. Zeeb rtw89_for_each_rtwvif(rtwdev, rtwvif) { 805*6d67aabdSBjoern A. Zeeb const struct rtw89_reg_6ghz_tpe *tmp; 806*6d67aabdSBjoern A. Zeeb const struct rtw89_chan *chan; 807*6d67aabdSBjoern A. Zeeb 808*6d67aabdSBjoern A. Zeeb chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx); 809*6d67aabdSBjoern A. Zeeb if (chan->band_type != RTW89_BAND_6G) 810*6d67aabdSBjoern A. Zeeb continue; 811*6d67aabdSBjoern A. Zeeb 812*6d67aabdSBjoern A. Zeeb tmp = &rtwvif->reg_6ghz_tpe; 813*6d67aabdSBjoern A. Zeeb if (!tmp->valid) 814*6d67aabdSBjoern A. Zeeb continue; 815*6d67aabdSBjoern A. Zeeb 816*6d67aabdSBjoern A. Zeeb tpe_intersect_constraint(&new, tmp->constraint); 817*6d67aabdSBjoern A. Zeeb } 818*6d67aabdSBjoern A. Zeeb 819*6d67aabdSBjoern A. Zeeb if (memcmp(®ulatory->reg_6ghz_tpe, &new, 820*6d67aabdSBjoern A. Zeeb sizeof(regulatory->reg_6ghz_tpe)) != 0) 821*6d67aabdSBjoern A. Zeeb changed = true; 822*6d67aabdSBjoern A. Zeeb 823*6d67aabdSBjoern A. Zeeb if (changed) { 824*6d67aabdSBjoern A. Zeeb if (new.valid) 825*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 826*6d67aabdSBjoern A. Zeeb "recalc 6 GHz reg TPE to %d dBm\n", 827*6d67aabdSBjoern A. Zeeb new.constraint); 828*6d67aabdSBjoern A. Zeeb else 829*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 830*6d67aabdSBjoern A. Zeeb "recalc 6 GHz reg TPE to none\n"); 831*6d67aabdSBjoern A. Zeeb 832*6d67aabdSBjoern A. Zeeb regulatory->reg_6ghz_tpe = new; 833*6d67aabdSBjoern A. Zeeb } 834*6d67aabdSBjoern A. Zeeb 835*6d67aabdSBjoern A. Zeeb return changed; 836*6d67aabdSBjoern A. Zeeb } 837*6d67aabdSBjoern A. Zeeb 838*6d67aabdSBjoern A. Zeeb static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev, 839*6d67aabdSBjoern A. Zeeb struct rtw89_vif *rtwvif, bool active, 840*6d67aabdSBjoern A. Zeeb unsigned int *changed) 841*6d67aabdSBjoern A. Zeeb { 842*6d67aabdSBjoern A. Zeeb struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 843*6d67aabdSBjoern A. Zeeb struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 844*6d67aabdSBjoern A. Zeeb struct rtw89_reg_6ghz_tpe *tpe = &rtwvif->reg_6ghz_tpe; 845*6d67aabdSBjoern A. Zeeb 846*6d67aabdSBjoern A. Zeeb memset(tpe, 0, sizeof(*tpe)); 847*6d67aabdSBjoern A. Zeeb 848*6d67aabdSBjoern A. Zeeb if (!active || rtwvif->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD) 849*6d67aabdSBjoern A. Zeeb goto bottom; 850*6d67aabdSBjoern A. Zeeb 851*6d67aabdSBjoern A. Zeeb rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe); 852*6d67aabdSBjoern A. Zeeb if (!tpe->valid) 853*6d67aabdSBjoern A. Zeeb goto bottom; 854*6d67aabdSBjoern A. Zeeb 855*6d67aabdSBjoern A. Zeeb if (tpe->constraint < RTW89_MIN_VALID_POWER_CONSTRAINT) { 856*6d67aabdSBjoern A. Zeeb rtw89_err(rtwdev, 857*6d67aabdSBjoern A. Zeeb "%s: constraint %d dBm is less than min valid val\n", 858*6d67aabdSBjoern A. Zeeb __func__, tpe->constraint); 859*6d67aabdSBjoern A. Zeeb 860*6d67aabdSBjoern A. Zeeb tpe->valid = false; 861*6d67aabdSBjoern A. Zeeb return -EINVAL; 862*6d67aabdSBjoern A. Zeeb } 863*6d67aabdSBjoern A. Zeeb 864*6d67aabdSBjoern A. Zeeb bottom: 865*6d67aabdSBjoern A. Zeeb *changed += __rtw89_reg_6ghz_tpe_recalc(rtwdev); 866*6d67aabdSBjoern A. Zeeb return 0; 867*6d67aabdSBjoern A. Zeeb } 868*6d67aabdSBjoern A. Zeeb 869*6d67aabdSBjoern A. Zeeb static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev) 870*6d67aabdSBjoern A. Zeeb { 871*6d67aabdSBjoern A. Zeeb struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; 872*6d67aabdSBjoern A. Zeeb const struct rtw89_regd *regd = regulatory->regd; 873e2340276SBjoern A. Zeeb enum rtw89_reg_6ghz_power sel; 874e2340276SBjoern A. Zeeb const struct rtw89_chan *chan; 875e2340276SBjoern A. Zeeb struct rtw89_vif *rtwvif; 876e2340276SBjoern A. Zeeb int count = 0; 877*6d67aabdSBjoern A. Zeeb u8 index; 878e2340276SBjoern A. Zeeb 879e2340276SBjoern A. Zeeb rtw89_for_each_rtwvif(rtwdev, rtwvif) { 880e2340276SBjoern A. Zeeb chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx); 881e2340276SBjoern A. Zeeb if (chan->band_type != RTW89_BAND_6G) 882e2340276SBjoern A. Zeeb continue; 883e2340276SBjoern A. Zeeb 884e2340276SBjoern A. Zeeb if (count != 0 && rtwvif->reg_6ghz_power == sel) 885e2340276SBjoern A. Zeeb continue; 886e2340276SBjoern A. Zeeb 887e2340276SBjoern A. Zeeb sel = rtwvif->reg_6ghz_power; 888e2340276SBjoern A. Zeeb count++; 889e2340276SBjoern A. Zeeb } 890e2340276SBjoern A. Zeeb 891e2340276SBjoern A. Zeeb if (count != 1) 892e2340276SBjoern A. Zeeb sel = RTW89_REG_6GHZ_POWER_DFLT; 893e2340276SBjoern A. Zeeb 894*6d67aabdSBjoern A. Zeeb if (sel == RTW89_REG_6GHZ_POWER_STD) { 895*6d67aabdSBjoern A. Zeeb index = rtw89_regd_get_index(regd); 896*6d67aabdSBjoern A. Zeeb if (index == RTW89_REGD_MAX_COUNTRY_NUM || 897*6d67aabdSBjoern A. Zeeb test_bit(index, regulatory->block_6ghz_sp)) { 898*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 899*6d67aabdSBjoern A. Zeeb "%c%c 6 GHz SP is blocked by policy\n", 900*6d67aabdSBjoern A. Zeeb regd->alpha2[0], regd->alpha2[1]); 901*6d67aabdSBjoern A. Zeeb sel = RTW89_REG_6GHZ_POWER_DFLT; 902*6d67aabdSBjoern A. Zeeb } 903*6d67aabdSBjoern A. Zeeb } 904*6d67aabdSBjoern A. Zeeb 905e2340276SBjoern A. Zeeb if (regulatory->reg_6ghz_power == sel) 906*6d67aabdSBjoern A. Zeeb return false; 907e2340276SBjoern A. Zeeb 908e2340276SBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_REGD, 909e2340276SBjoern A. Zeeb "recalc 6 GHz reg power type to %d\n", sel); 910e2340276SBjoern A. Zeeb 911e2340276SBjoern A. Zeeb regulatory->reg_6ghz_power = sel; 912*6d67aabdSBjoern A. Zeeb return true; 913e2340276SBjoern A. Zeeb } 914e2340276SBjoern A. Zeeb 915*6d67aabdSBjoern A. Zeeb static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, 916*6d67aabdSBjoern A. Zeeb struct rtw89_vif *rtwvif, bool active, 917*6d67aabdSBjoern A. Zeeb unsigned int *changed) 918e2340276SBjoern A. Zeeb { 919e2340276SBjoern A. Zeeb struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 920e2340276SBjoern A. Zeeb 921e2340276SBjoern A. Zeeb if (active) { 922e2340276SBjoern A. Zeeb switch (vif->bss_conf.power_type) { 923e2340276SBjoern A. Zeeb case IEEE80211_REG_VLP_AP: 924e2340276SBjoern A. Zeeb rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP; 925e2340276SBjoern A. Zeeb break; 926e2340276SBjoern A. Zeeb case IEEE80211_REG_LPI_AP: 927e2340276SBjoern A. Zeeb rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI; 928e2340276SBjoern A. Zeeb break; 929e2340276SBjoern A. Zeeb case IEEE80211_REG_SP_AP: 930e2340276SBjoern A. Zeeb rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD; 931e2340276SBjoern A. Zeeb break; 932e2340276SBjoern A. Zeeb default: 933e2340276SBjoern A. Zeeb rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; 934e2340276SBjoern A. Zeeb break; 935e2340276SBjoern A. Zeeb } 936e2340276SBjoern A. Zeeb } else { 937e2340276SBjoern A. Zeeb rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; 938e2340276SBjoern A. Zeeb } 939e2340276SBjoern A. Zeeb 940*6d67aabdSBjoern A. Zeeb *changed += __rtw89_reg_6ghz_power_recalc(rtwdev); 941*6d67aabdSBjoern A. Zeeb return 0; 942*6d67aabdSBjoern A. Zeeb } 943*6d67aabdSBjoern A. Zeeb 944*6d67aabdSBjoern A. Zeeb int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 945*6d67aabdSBjoern A. Zeeb bool active) 946*6d67aabdSBjoern A. Zeeb { 947*6d67aabdSBjoern A. Zeeb unsigned int changed = 0; 948*6d67aabdSBjoern A. Zeeb int ret; 949*6d67aabdSBjoern A. Zeeb 950*6d67aabdSBjoern A. Zeeb lockdep_assert_held(&rtwdev->mutex); 951*6d67aabdSBjoern A. Zeeb 952*6d67aabdSBjoern A. Zeeb /* The result of reg_6ghz_tpe may depend on reg_6ghz_power type, 953*6d67aabdSBjoern A. Zeeb * so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc(). 954*6d67aabdSBjoern A. Zeeb */ 955*6d67aabdSBjoern A. Zeeb 956*6d67aabdSBjoern A. Zeeb ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, active, &changed); 957*6d67aabdSBjoern A. Zeeb if (ret) 958*6d67aabdSBjoern A. Zeeb return ret; 959*6d67aabdSBjoern A. Zeeb 960*6d67aabdSBjoern A. Zeeb ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif, active, &changed); 961*6d67aabdSBjoern A. Zeeb if (ret) 962*6d67aabdSBjoern A. Zeeb return ret; 963*6d67aabdSBjoern A. Zeeb 964*6d67aabdSBjoern A. Zeeb if (changed) 965*6d67aabdSBjoern A. Zeeb rtw89_core_set_chip_txpwr(rtwdev); 966*6d67aabdSBjoern A. Zeeb 967*6d67aabdSBjoern A. Zeeb return 0; 968e2340276SBjoern A. Zeeb } 969