diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/drivers/wifi/generic/acpi.c | 81 | ||||
-rw-r--r-- | src/drivers/wifi/generic/chip.h | 3 | ||||
-rw-r--r-- | src/include/sar.h | 16 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/sar.c | 10 |
4 files changed, 105 insertions, 5 deletions
diff --git a/src/drivers/wifi/generic/acpi.c b/src/drivers/wifi/generic/acpi.c index d3da51b116..e303589660 100644 --- a/src/drivers/wifi/generic/acpi.c +++ b/src/drivers/wifi/generic/acpi.c @@ -15,8 +15,9 @@ #include "wifi.h" #include "wifi_private.h" -/* WIFI Domain type */ +/* Domain type */ #define DOMAIN_TYPE_WIFI 0x7 +#define DOMAIN_TYPE_BLUETOOTH 0x12 /* Maximum number DSM UUID bifurcations in _DSM */ #define MAX_DSM_FUNCS 2 @@ -489,9 +490,59 @@ static void sar_emit_wtas(struct avg_profile *wtas) acpigen_write_package_end(); } -static void emit_sar_acpi_structures(const struct device *dev, struct dsm_profile *dsm) +static void sar_emit_brds(const struct bsar_profile *bsar) { - union wifi_sar_limits sar_limits = {{NULL, NULL, NULL, NULL, NULL} }; + size_t package_size, table_size; + const uint8_t *set; + + /* + * Name ("BRDS", Package () { + * Revision, + * Package () { + * Domain Type, // 0x12:Bluetooth + * Bluetooth SAR BIOS, // BIOS SAR Enable/disable + * Bluetooth Increase Power Mode // SAR Limitation Enable/disable + * Bluetooth SAR Power Restriction, // 00000000 - 0dBm + * // 11111111 - 31.875dBm + * // (Step 0.125dBm) + * Bluetooth SAR Table // SAR Tx power limit table + * } + * }) + */ + if (bsar->revision != BSAR_REVISION) { + printk(BIOS_ERR, "Unsupported BSAR table revision: %d\n", + bsar->revision); + return; + } + + acpigen_write_name("BRDS"); + acpigen_write_package(2); + acpigen_write_dword(bsar->revision); + + table_size = sizeof(*bsar) - + offsetof(struct bsar_profile, sar_lb_power_restriction); + /* + * Emit 'Domain Type' + 'Dynamic SAR Enable' + 'Increase Power Mode' + * + ('SAR Power Restriction' + SAR table). + */ + package_size = 1 + 1 + 1 + table_size; + acpigen_write_package(package_size); + acpigen_write_dword(DOMAIN_TYPE_BLUETOOTH); + acpigen_write_dword(1); + acpigen_write_dword(bsar->increased_power_mode_limitation); + + set = (const uint8_t *)&bsar->sar_lb_power_restriction; + for (int i = 0; i < table_size; i++) + acpigen_write_byte(set[i]); + + acpigen_write_package_end(); + acpigen_write_package_end(); +} + +static void emit_sar_acpi_structures(const struct device *dev, struct dsm_profile *dsm, + struct bsar_profile *bsar, bool *bsar_loaded) +{ + union wifi_sar_limits sar_limits = {0}; /* * If device type is PCI, ensure that the device has Intel vendor ID. CBFS SAR and SAR @@ -516,6 +567,12 @@ static void emit_sar_acpi_structures(const struct device *dev, struct dsm_profil if (sar_limits.dsm != NULL) memcpy(dsm, sar_limits.dsm, sizeof(struct dsm_profile)); + /* copy the bsar data to be later used for creating Bluetooth BRDS method */ + if (sar_limits.bsar != NULL) { + memcpy(bsar, sar_limits.bsar, sizeof(struct bsar_profile)); + *bsar_loaded = true; + } + free(sar_limits.sar); } @@ -576,11 +633,14 @@ static void wifi_ssdt_write_properties(const struct device *dev, const char *sco struct dsm_uuid dsm_ids[MAX_DSM_FUNCS]; /* We will need a copy dsm data to be used later for creating _DSM function */ struct dsm_profile dsm = {0}; + /* We will need a copy of bsar data to be used later for creating BRDS function */ + struct bsar_profile bsar = {0}; + bool bsar_loaded = false; uint8_t dsm_count = 0; /* Fill Wifi SAR related ACPI structures */ if (CONFIG(USE_SAR)) { - emit_sar_acpi_structures(dev, &dsm); + emit_sar_acpi_structures(dev, &dsm, &bsar, &bsar_loaded); if (dsm.supported_functions != 0) { for (int i = 1; i < ARRAY_SIZE(wifi_dsm_callbacks); i++) @@ -618,6 +678,19 @@ static void wifi_ssdt_write_properties(const struct device *dev, const char *sco acpigen_write_scope_end(); /* Scope */ + /* Fill Bluetooth companion SAR related ACPI structures */ + if (bsar_loaded && is_dev_enabled(config->bluetooth_companion)) { + const char *path = acpi_device_path(config->bluetooth_companion); + if (path) { /* Bluetooth device under USB Hub scope or PCIe root port */ + acpigen_write_scope(path); + sar_emit_brds(&bsar); + acpigen_write_scope_end(); + } else { + printk(BIOS_ERR, "Failed to get %s Bluetooth companion ACPI path\n", + dev_path(dev)); + } + } + printk(BIOS_INFO, "%s: %s %s\n", scope, dev->chip_ops ? dev->chip_ops->name : "", dev_path(dev)); } diff --git a/src/drivers/wifi/generic/chip.h b/src/drivers/wifi/generic/chip.h index 2729a35663..302dd144ef 100644 --- a/src/drivers/wifi/generic/chip.h +++ b/src/drivers/wifi/generic/chip.h @@ -19,6 +19,9 @@ struct drivers_wifi_generic_config { * SoC code propagates this value the applicable FSP UPD. */ bool enable_cnvi_ddr_rfim; + + /* Pointer to the Bluetooth companion device */ + DEVTREE_CONST struct device *bluetooth_companion; }; #endif /* _GENERIC_WIFI_H_ */ diff --git a/src/include/sar.h b/src/include/sar.h index c201cea2f4..7c1b95d530 100644 --- a/src/include/sar.h +++ b/src/include/sar.h @@ -9,8 +9,9 @@ #define MAX_DENYLIST_ENTRY 16 #define MAX_DSAR_SET_COUNT 3 #define MAX_GEO_OFFSET_REVISION 3 -#define MAX_PROFILE_COUNT 5 +#define MAX_PROFILE_COUNT 6 #define MAX_SAR_REVISION 2 +#define BSAR_REVISION 1 #define REVISION_SIZE 1 #define SAR_REV0_CHAINS_COUNT 2 #define SAR_REV0_SUBBANDS_COUNT 5 @@ -60,6 +61,18 @@ struct dsm_profile { uint32_t enablement_11be; }; +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; +} __packed; + struct sar_header { char marker[SAR_STR_PREFIX_SIZE]; uint8_t version; @@ -74,6 +87,7 @@ union wifi_sar_limits { struct gain_profile *ppag; struct avg_profile *wtas; struct dsm_profile *dsm; + struct bsar_profile *bsar; }; void *profile[MAX_PROFILE_COUNT]; }; diff --git a/src/vendorcode/google/chromeos/sar.c b/src/vendorcode/google/chromeos/sar.c index c42bf65437..8195886ebc 100644 --- a/src/vendorcode/google/chromeos/sar.c +++ b/src/vendorcode/google/chromeos/sar.c @@ -94,6 +94,14 @@ static int dsm_table_size(const struct dsm_profile *dsm) return sizeof(struct dsm_profile); } +static int bsar_table_size(const struct bsar_profile *bsar) +{ + if (bsar == NULL) + return 0; + + return sizeof(struct bsar_profile); +} + static bool valid_legacy_length(size_t bin_len) { if (bin_len == LEGACY_SAR_WGDS_BIN_SIZE) @@ -145,6 +153,7 @@ static int fill_wifi_sar_limits(union wifi_sar_limits *sar_limits, const uint8_t expected_sar_bin_size += gain_table_size(sar_limits->ppag); expected_sar_bin_size += sar_avg_table_size(sar_limits->wtas); expected_sar_bin_size += dsm_table_size(sar_limits->dsm); + expected_sar_bin_size += bsar_table_size(sar_limits->bsar); if (sar_bin_size != expected_sar_bin_size) { printk(BIOS_ERR, "Invalid SAR size, expected: %zu, obtained: %zu\n", @@ -210,6 +219,7 @@ static int fill_wifi_sar_limits_legacy(union wifi_sar_limits *sar_limits, * [PPAG_REVISION,MODE,CHAINS_COUNT,SUBBANDS_COUNT<PPAG_DATA>] * [WTAS_REVISION, WTAS_DATA] * [DSM_RETURN_VALUES] + * [BSAR_REVISION,IPML,LB,BR,EDR2,EDR3,LE,LE2,LE_LR] * * The configuration data will always have the revision added in the file for each of the * block, based on the revision number and validity, size of the specific block will be |