summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/wifi/generic/acpi.c81
-rw-r--r--src/drivers/wifi/generic/chip.h3
-rw-r--r--src/include/sar.h16
-rw-r--r--src/vendorcode/google/chromeos/sar.c10
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