diff options
-rw-r--r-- | src/drivers/wifi/generic/acpi.c | 62 | ||||
-rw-r--r-- | src/include/sar.h | 46 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/sar.c | 15 |
3 files changed, 108 insertions, 15 deletions
diff --git a/src/drivers/wifi/generic/acpi.c b/src/drivers/wifi/generic/acpi.c index 3cd55e36fe..be44f6b907 100644 --- a/src/drivers/wifi/generic/acpi.c +++ b/src/drivers/wifi/generic/acpi.c @@ -599,7 +599,7 @@ static void sar_emit_brds(const struct bsar_profile *bsar) * } * }) */ - if (bsar->revision != BSAR_REVISION) { + if (bsar->revision == 0 || bsar->revision > MAX_BSAR_REVISION) { printk(BIOS_ERR, "Unsupported BSAR table revision: %d\n", bsar->revision); return; @@ -609,11 +609,14 @@ static void sar_emit_brds(const struct bsar_profile *bsar) acpigen_write_package(2); acpigen_write_dword(bsar->revision); - table_size = sizeof(*bsar) - - offsetof(struct bsar_profile, sar_lb_power_restriction); + if (bsar->revision == 1) + table_size = sizeof(bsar->revs.rev1); + else + table_size = sizeof(bsar->revs.rev2); + /* * Emit 'Domain Type' + 'Dynamic SAR Enable' + 'Increase Power Mode' - * + ('SAR Power Restriction' + SAR table). + * + ('SAR Power Restriction' + SAR table) | (Chain A and B SAR tables). */ package_size = 1 + 1 + 1 + table_size; acpigen_write_package(package_size); @@ -621,7 +624,7 @@ static void sar_emit_brds(const struct bsar_profile *bsar) acpigen_write_dword(1); acpigen_write_dword(bsar->increased_power_mode_limitation); - set = (const uint8_t *)&bsar->sar_lb_power_restriction; + set = (const uint8_t *)&bsar->revs; for (int i = 0; i < table_size; i++) acpigen_write_byte(set[i]); @@ -876,6 +879,54 @@ static void sar_emit_bdmm(const struct bdmm_profile *bdmm) acpigen_write_package_end(); } +static void sar_emit_ebrd(const struct ebrd_profile *ebrd) +{ + if (ebrd == NULL) + return; + + size_t package_size, table_size; + const uint8_t *set; + + /* + * Name ("EBRD", Package () { + * Revision, + * Package () { + * Domain Type, // 0x12:Bluetooth + * Dynamic SAR Enable, + * Number of Optional SAR, + * Three SAR Sets + * } + * }) + */ + if (ebrd->revision != EBRD_REVISION) { + printk(BIOS_ERR, "Unsupported EBRD table revision: %d\n", + ebrd->revision); + return; + } + + acpigen_write_name("EBRD"); + acpigen_write_package(2); + acpigen_write_dword(ebrd->revision); + + /* + * Emit 'Domain Type' + 'Dynamic Sar Enabled' + 'Number of Optional SAR' + + * 'Three SAR Sets' + */ + table_size = sizeof(*ebrd) - offsetof(struct ebrd_profile, sar_table_sets); + package_size = 1 + 1 + 1 + table_size; + acpigen_write_package(package_size); + acpigen_write_dword(DOMAIN_TYPE_BLUETOOTH); + acpigen_write_dword(ebrd->dynamic_sar_enable); + acpigen_write_dword(ebrd->number_of_optional_sar); + + set = (const uint8_t *)&ebrd->sar_table_sets; + for (size_t i = 0; i < table_size; i++) + acpigen_write_byte(set[i]); + + acpigen_write_package_end(); + acpigen_write_package_end(); +} + static void emit_wifi_sar_acpi_structures(const struct device *dev, union wifi_sar_limits *sar_limits) { @@ -1014,6 +1065,7 @@ static void wifi_ssdt_write_properties(const struct device *dev, const char *sco sar_emit_bbsm(sar_limits.bbsm); sar_emit_bucs(sar_limits.bucs); sar_emit_bdmm(sar_limits.bdmm); + sar_emit_ebrd(sar_limits.ebrd); acpigen_write_scope_end(); } else { printk(BIOS_ERR, "Failed to get %s Bluetooth companion ACPI path\n", diff --git a/src/include/sar.h b/src/include/sar.h index 4643b24f86..44fcd1e322 100644 --- a/src/include/sar.h +++ b/src/include/sar.h @@ -9,9 +9,9 @@ #define MAX_DENYLIST_ENTRY 16 #define MAX_DSAR_SET_COUNT 3 #define MAX_GEO_OFFSET_REVISION 3 -#define MAX_PROFILE_COUNT 13 +#define MAX_PROFILE_COUNT 14 #define MAX_SAR_REVISION 2 -#define BSAR_REVISION 1 +#define MAX_BSAR_REVISION 2 #define WBEM_REVISION 0 #define BPAG_REVISION 2 #define BBFB_REVISION 1 @@ -19,6 +19,7 @@ #define BBSM_REVISION 1 #define BUCS_REVISION 1 #define BDMM_REVISION 1 +#define EBRD_REVISION 1 #define REVISION_SIZE 1 #define SAR_REV0_CHAINS_COUNT 2 #define SAR_REV0_SUBBANDS_COUNT 5 @@ -70,16 +71,32 @@ struct dsm_profile { uint32_t rfi_mitigation; }; +struct sar_power_table { + uint8_t restriction_for_2g4; + uint8_t restriction_for_5g2; + uint8_t restriction_for_5g8_5g9; + uint8_t restriction_for_6g1; + uint8_t restriction_for_6g3; +} __packed; + struct bsar_profile { uint8_t revision; uint8_t increased_power_mode_limitation; - uint8_t sar_lb_power_restriction; - uint8_t br_modulation; - uint8_t edr2_modulation; - uint8_t edr3_modulation; - uint8_t le_modulation; - uint8_t le2_mhz_modulation; - uint8_t le_lr_modulation; + union { + struct rev1 { + uint8_t sar_lb_power_restriction; + uint8_t br_modulation; + uint8_t edr2_modulation; + uint8_t edr3_modulation; + uint8_t le_modulation; + uint8_t le2_mhz_modulation; + uint8_t le_lr_modulation; + } rev1; + struct rev2 { + struct sar_power_table set_1_chain_a; + struct sar_power_table set_1_chain_b; + } rev2; + } revs; } __packed; struct wbem_profile { @@ -117,6 +134,16 @@ struct bdmm_profile { uint8_t dual_mac_enable; } __packed; +struct ebrd_profile { + uint8_t revision; + uint32_t dynamic_sar_enable; + uint32_t number_of_optional_sar; + struct { + struct sar_power_table chain_a; + struct sar_power_table chain_b; + } sar_table_sets[3]; +} __packed; + struct sar_header { char marker[SAR_STR_PREFIX_SIZE]; uint8_t version; @@ -139,6 +166,7 @@ union wifi_sar_limits { struct bbsm_profile *bbsm; struct bucs_profile *bucs; struct bdmm_profile *bdmm; + struct ebrd_profile *ebrd; }; void *profile[MAX_PROFILE_COUNT]; }; diff --git a/src/vendorcode/google/chromeos/sar.c b/src/vendorcode/google/chromeos/sar.c index dd43c977df..6ebf931d7d 100644 --- a/src/vendorcode/google/chromeos/sar.c +++ b/src/vendorcode/google/chromeos/sar.c @@ -96,10 +96,14 @@ static size_t dsm_table_size(const struct dsm_profile *dsm) static size_t bsar_table_size(const struct bsar_profile *bsar) { + int revs_offset = offsetof(struct bsar_profile, revs); + if (bsar == NULL) return 0; - return sizeof(struct bsar_profile); + if (bsar->revision == 2) + return revs_offset + sizeof(bsar->revs.rev2); + return revs_offset + sizeof(bsar->revs.rev1); } static size_t wbem_table_size(const struct wbem_profile *wbem) @@ -158,6 +162,14 @@ static size_t bdmm_table_size(const struct bdmm_profile *bdmm) return sizeof(struct bdmm_profile); } +static size_t ebrd_table_size(const struct ebrd_profile *ebrd) +{ + if (ebrd == NULL) + return 0; + + return sizeof(struct ebrd_profile); +} + static bool valid_legacy_length(size_t bin_len) { if (bin_len == LEGACY_SAR_WGDS_BIN_SIZE) @@ -217,6 +229,7 @@ static int fill_wifi_sar_limits(union wifi_sar_limits *sar_limits, const uint8_t expected_sar_bin_size += bbsm_table_size(sar_limits->bbsm); expected_sar_bin_size += bucs_table_size(sar_limits->bucs); expected_sar_bin_size += bdmm_table_size(sar_limits->bdmm); + expected_sar_bin_size += ebrd_table_size(sar_limits->ebrd); if (sar_bin_size != expected_sar_bin_size) { printk(BIOS_ERR, "Invalid SAR size, expected: %zu, obtained: %zu\n", |