Sugnan Prabhu S has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/57060 )
Change subject: vc/google/chromeos: Add support for per-platform antenna gain ......................................................................
vc/google/chromeos: Add support for per-platform antenna gain
Add support for the PPAG ACPI BIOS configuration table as per the connectivity document: 559910_Intel_Connectivity_Platforms_BIOS_Guidelines_Rev6_4.pdf
Change-Id: Ie8d25113feeeb4a4242cfd7d72a5091d2d5fb389 Signed-off-by: Sugnan Prabhu S sugnan.prabhu.s@intel.com --- M src/drivers/wifi/generic/acpi.c M src/include/sar.h M src/vendorcode/google/chromeos/sar.c 3 files changed, 123 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/60/57060/1
diff --git a/src/drivers/wifi/generic/acpi.c b/src/drivers/wifi/generic/acpi.c index 2d2a1b0..7d8706c 100644 --- a/src/drivers/wifi/generic/acpi.c +++ b/src/drivers/wifi/generic/acpi.c @@ -199,6 +199,66 @@ acpigen_pop_len(); }
+static void emit_wifi_antgain_table(struct wifi_ant_table *ant_gains) +{ + int i; + size_t package_size = 1; + + if (ant_gains == NULL) + return; + + /* + * Name ("PPAG", Package () { + * Revision, + * Package () { + * Domain Type, // 0x7:WiFi + * PPAG Mode, // Defines the mode of ANT_gain control to be used + * ANT_gain Table Chain A // Defines the ANT_gain in dBi for chain A + * ANT_gain Table Chain B // Defines the ANT_gain in dBi for chain B + * } + * }) + */ + if (ant_gains->version == 0) { + package_size = sizeof(ant_gains->gains_rev0) + 2; + } else if (ant_gains->version == 1 || ant_gains->version == 2) { + package_size = sizeof(ant_gains->gains_rev1) + 2; + } else { + printk(BIOS_ERR, "Invalid antenna gains version: %d\n", ant_gains->version); + return; + } + + acpigen_write_name("PPAG"); + acpigen_write_package(2); + acpigen_write_dword(ant_gains->version); + acpigen_write_package(package_size); + acpigen_write_dword(DOMAIN_TYPE_WIFI); + acpigen_write_dword(ant_gains->mode); + for (i = 0; i < ANT_GAINS_TABLE_COUNT; i++) { + if (ant_gains->version == 0) { + acpigen_write_byte(ant_gains->gains_rev0[i].ant_gain_2400); + acpigen_write_byte(ant_gains->gains_rev0[i].ant_gain_5150_5350); + acpigen_write_byte(ant_gains->gains_rev0[i].ant_gain_5350_5470); + acpigen_write_byte(ant_gains->gains_rev0[i].ant_gain_5470_5725); + acpigen_write_byte(ant_gains->gains_rev0[i].ant_gain_5725_5950); + } else if (ant_gains->version == 1 || ant_gains->version == 2) { + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_2400); + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_5150_5350); + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_5350_5470); + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_5470_5725); + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_5725_5945); + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_5945_6165); + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_6165_6405); + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_6405_6525); + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_6525_6705); + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_6705_6865); + acpigen_write_byte(ant_gains->gains_rev1[i].ant_gain_6865_7105); + } + } + + acpigen_pop_len(); + acpigen_pop_len(); +} + static void emit_sar_acpi_structures(const struct device *dev) { struct wifi_sar_limits sar_limits; @@ -218,6 +278,7 @@
emit_wifi_sar_table(sar_limits.sar_table); emit_wifi_sar_delta_table(sar_limits.wgds); + emit_wifi_antgain_table(sar_limits.ant_gains);
free(sar_limits.sar_table); } diff --git a/src/include/sar.h b/src/include/sar.h index 36c05f3..eba5ed8 100644 --- a/src/include/sar.h +++ b/src/include/sar.h @@ -4,6 +4,7 @@
#include <stdint.h>
+#define ANT_GAINS_TABLE_COUNT 2 #define BYTES_PER_SAR_LIMIT 10 #define BYTES_PER_SAR_LIMIT_REV1 22 #define BYTES_PER_SAR_LIMIT_REV2 (BYTES_PER_SAR_LIMIT_REV1 * 2) @@ -18,6 +19,33 @@ SAR_NUM_WGDS_GROUPS };
+struct wifi_ant_table { + uint8_t version; + uint8_t mode; + union { + struct { + uint8_t ant_gain_2400; + uint8_t ant_gain_5150_5350; + uint8_t ant_gain_5350_5470; + uint8_t ant_gain_5470_5725; + uint8_t ant_gain_5725_5950; + } __packed gains_rev0[ANT_GAINS_TABLE_COUNT]; + struct { + uint8_t ant_gain_2400; + uint8_t ant_gain_5150_5350; + uint8_t ant_gain_5350_5470; + uint8_t ant_gain_5470_5725; + uint8_t ant_gain_5725_5945; + uint8_t ant_gain_5945_6165; + uint8_t ant_gain_6165_6405; + uint8_t ant_gain_6405_6525; + uint8_t ant_gain_6525_6705; + uint8_t ant_gain_6705_6865; + uint8_t ant_gain_6865_7105; + } __packed gains_rev1[ANT_GAINS_TABLE_COUNT]; + } __packed; +} __packed; + struct wifi_sar_delta_table { uint8_t version; union { @@ -55,6 +83,7 @@ struct wifi_sar_limits { struct wifi_sar_table *sar_table; struct wifi_sar_delta_table *wgds; + struct wifi_ant_table *ant_gains; };
/* diff --git a/src/vendorcode/google/chromeos/sar.c b/src/vendorcode/google/chromeos/sar.c index c4ad1fe..391e68b 100644 --- a/src/vendorcode/google/chromeos/sar.c +++ b/src/vendorcode/google/chromeos/sar.c @@ -50,6 +50,19 @@ return REVISION_SIZE; }
+static int antgains_table_size(struct wifi_ant_table *gains_table) +{ + if (CONFIG(USE_SAR)) + return 0; + + if (gains_table->version == 0) + return sizeof(gains_table->gains_rev0) + REVISION_SIZE + PPAG_MODE_SIZE; + else if (gains_table->version == 1 || gains_table->version == 2) + return sizeof(gains_table->gains_rev1) + REVISION_SIZE + PPAG_MODE_SIZE; + else + return REVISION_SIZE; +} + /* * Retrieve WiFi SAR limits data from CBFS and decode it * Legacy WiFi SAR data is expected in the format: [<WRDD><EWRD>][WGDS] @@ -60,6 +73,7 @@ * SAR V2 configuration data is expected in the format: * SAR_REVISION[SAR_ENABLE,DSAR_ENABLE,DSAR_SET_NUM <WRDD><EWRD>] * WGDS_REVISION[WGDS_DATA] + * PPAG_REVISION[MODE,PPAG_DATA] * * 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 @@ -75,6 +89,21 @@ * [GROUP#0] is for FCC * [GROUP#1] is for Europe/Japan * [GROUP#2] is for ROW + * + * [PPAG_DATA] = [ANT_gain Table Chain A] [ANT_gain Table Chain A] + * + * [ANT_gain Table] = + * [Antenna gain used for 2400MHz frequency] + * [Antenna gain used for 5150-5350MHz frequency] + * [Antenna gain used for 5350-5470MHz frequency] + * [Antenna gain used for 5470-5725MHz frequency] + * [Antenna gain used for 5725-5945MHz frequency] + * [Antenna gain used for 5945-6165MHz frequency] version 1 and 2 + * [Antenna gain used for 6165-6405MHz frequency] version 1 and 2 + * [Antenna gain used for 6405-6525MHz frequency] version 1 and 2 + * [Antenna gain used for 6525-6705MHz frequency] version 1 and 2 + * [Antenna gain used for 6705-6865MHz frequency] version 1 and 2 + * [Antenna gain used for 6865-7105MHz frequency] version 1 and 2 */ int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits) { @@ -147,9 +176,12 @@ sar_limits->wgds = (struct wifi_sar_delta_table *)sar_ptr;
sar_ptr += wgds_table_size(sar_limits->wgds); + if (CONFIG(USE_SAR_V2)) + sar_limits->ant_gains = (struct wifi_ant_table *)sar_ptr;
expected_sar_bin_len = sar_table_size(sar_limits->sar_table) + - wgds_table_size(sar_limits->wgds); + wgds_table_size(sar_limits->wgds) + + antgains_table_size(sar_limits->ant_gains); if (sar_bin_len != expected_sar_bin_len) { printk(BIOS_ERR, "Error: length mismatch: expected: %ld, obtained: %ld\n", expected_sar_bin_len, sar_bin_len);