diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c | 151 |
1 files changed, 117 insertions, 34 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c index e7afea87e82e..d1aebadd50aa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c @@ -4,6 +4,28 @@ #include <linux/acpi.h> #include "mt792x.h" +static const char * const cc_list_all[] = { + "00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR", + "CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME", + "MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR", + "TW", "TH", "UA", "GB", "US", "VN", "KH", "PY", +}; + +static const char * const cc_list_eu[] = { + "AD", "AT", "BE", "BG", "CY", "CZ", "HR", "DK", + "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE", + "IT", "LV", "LI", "LT", "LU", "MC", "MT", "NL", + "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE", + "CH", +}; + +static const char * const cc_list_be[] = { + "AR", "BR", "BY", "CL", "IQ", "MX", "OM", "RU", + "RW", "VN", "KR", "UA", "", "", "", "", + "EU", "AT", "CN", "CA", "TW", "NZ", "PH", "UK", + "US", +}; + static int mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len) { @@ -66,13 +88,24 @@ free: } /* MTCL : Country List Table for 6G band */ -static void +/* MTCL : Country List Table for 6G band and 11BE */ +static int mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version) { - if (mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL) < 0) - *version = 1; + int len, ret; + + ret = mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, &len); + if (ret) + return ret; + + if (len == sizeof(struct mt792x_asar_cl)) + *version = ((struct mt792x_asar_cl *)*table)->version; + else if (len == sizeof(struct mt792x_asar_cl_v3)) + *version = ((struct mt792x_asar_cl_v3 *)*table)->version; else - *version = 2; + return -EINVAL; + + return ret; } /* MTDS : Dynamic SAR Power Table */ @@ -166,16 +199,16 @@ int mt792x_init_acpi_sar(struct mt792x_dev *dev) if (!asar) return -ENOMEM; - mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver); + ret = mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver); + if (ret) { + devm_kfree(dev->mt76.dev, asar->countrylist); + asar->countrylist = NULL; + } - /* MTDS is mandatory. Return error if table is invalid */ ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver); if (ret) { devm_kfree(dev->mt76.dev, asar->dyn); - devm_kfree(dev->mt76.dev, asar->countrylist); - devm_kfree(dev->mt76.dev, asar); - - return ret; + asar->dyn = NULL; } /* MTGS is optional */ @@ -290,7 +323,7 @@ int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default) const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; int i; - if (!phy->acpisar) + if (!phy->acpisar || !((struct mt792x_acpi_sar *)phy->acpisar)->dyn) return 0; /* When ACPI SAR enabled in HW, we should apply rules for .frp @@ -349,43 +382,75 @@ u8 mt792x_acpi_get_flags(struct mt792x_phy *phy) } EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags); -static u8 +static u32 +mt792x_acpi_get_mtcl_map_v3(int row, int column, struct mt792x_asar_cl_v3 *cl) +{ + u32 config = 0; + u8 mode_be = 0; + + mode_be = (cl->mode_be > 0x02) ? 0 : cl->mode_be; + + if (cl->version > 2 && cl->clbe[row] & BIT(column)) + config |= (mode_be & 0x3) << 4; + + return config; +} + +static u32 mt792x_acpi_get_mtcl_map(int row, int column, struct mt792x_asar_cl *cl) { - u8 config = 0; + u32 config = 0; + u8 mode_6g, mode_5g9; - if (cl->cl6g[row] & BIT(column)) - config |= (cl->mode_6g & 0x3) << 2; + mode_6g = (cl->mode_6g > 0x02) ? 0 : cl->mode_6g; + mode_5g9 = (cl->mode_5g9 > 0x01) ? 0 : cl->mode_5g9; + + if ((cl->cl6g[row] & BIT(column)) || cl->mode_6g == 0x02) + config |= (mode_6g & 0x3) << 2; if (cl->version > 1 && cl->cl5g9[row] & BIT(column)) - config |= (cl->mode_5g9 & 0x3); + config |= (mode_5g9 & 0x3); return config; } -u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2) +static u32 +mt792x_acpi_parse_mtcl_tbl_v3(struct mt792x_phy *phy, char *alpha2) { - static const char * const cc_list_all[] = { - "00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR", - "CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME", - "MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR", - "TW", "TH", "UA", "GB", "US", "VN", "KH", "PY", - }; - static const char * const cc_list_eu[] = { - "AT", "BE", "BG", "CY", "CZ", "HR", "DK", "EE", - "FI", "FR", "DE", "GR", "HU", "IS", "IE", "IT", - "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL", - "PT", "RO", "MT", "SK", "SI", "ES", "CH", - }; struct mt792x_acpi_sar *sar = phy->acpisar; - struct mt792x_asar_cl *cl; + struct mt792x_asar_cl_v3 *cl = sar->countrylist_v3; int col, row, i; - if (!sar) - return 0xf; + if (sar->ver != 3) + goto out; + + if (!cl) + return MT792X_ACPI_MTCL_INVALID; + + for (i = 0; i < ARRAY_SIZE(cc_list_be); i++) { + col = 7 - i % 8; + row = i / 8; + if (!memcmp(cc_list_be[i], alpha2, 2)) + return mt792x_acpi_get_mtcl_map_v3(row, col, cl); + } + for (i = 0; i < ARRAY_SIZE(cc_list_eu); i++) { + if (!memcmp(cc_list_eu[i], alpha2, 2)) + return mt792x_acpi_get_mtcl_map_v3(3, 7, cl); + } + +out: + /* Depends on driver */ + return 0x20; +} + +static u32 +mt792x_acpi_parse_mtcl_tbl(struct mt792x_phy *phy, char *alpha2) +{ + struct mt792x_acpi_sar *sar = phy->acpisar; + struct mt792x_asar_cl *cl = sar->countrylist; + int col, row, i; - cl = sar->countrylist; if (!cl) - return 0xc; + return MT792X_ACPI_MTCL_INVALID; for (i = 0; i < ARRAY_SIZE(cc_list_all); i++) { col = 7 - i % 8; @@ -400,4 +465,22 @@ u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2) return mt792x_acpi_get_mtcl_map(0, 7, cl); } + +u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2) +{ + struct mt792x_acpi_sar *sar = phy->acpisar; + u32 config = 0; + + if (!sar) + return MT792X_ACPI_MTCL_INVALID; + + config = mt792x_acpi_parse_mtcl_tbl_v3(phy, alpha2); + + if (config == MT792X_ACPI_MTCL_INVALID) + return MT792X_ACPI_MTCL_INVALID; + + config |= mt792x_acpi_parse_mtcl_tbl(phy, alpha2); + + return config; +} EXPORT_SYMBOL_GPL(mt792x_acpi_get_mtcl_conf); |