summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/drivers/wifi/generic/acpi.c62
-rw-r--r--src/include/sar.h46
-rw-r--r--src/vendorcode/google/chromeos/sar.c15
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",