diff --git a/src/drivers/wifi/generic/acpi.c b/src/drivers/wifi/generic/acpi.c index aa49be35e2..ed5b632216 100644 --- a/src/drivers/wifi/generic/acpi.c +++ b/src/drivers/wifi/generic/acpi.c @@ -42,6 +42,13 @@ static const uint8_t *wgds_fetch_set(struct geo_profile *wgds, size_t set_num) return wgds_table + (wgds->bands_count * set_num); } +static const uint8_t *ppag_fetch_set(struct gain_profile *ppag, size_t set_num) +{ + const uint8_t *ppag_table = &ppag->ppag_table[0]; + + return ppag_table + (ppag->bands_count * set_num); +} + static void sar_emit_wrds(const struct sar_profile *sar) { int i; @@ -216,6 +223,50 @@ static void sar_emit_wgds(struct geo_profile *wgds) acpigen_write_package_end(); } +static void sar_emit_ppag(struct gain_profile *ppag) +{ + int i; + size_t package_size, set_num; + const uint8_t *set; + + if (ppag == 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 (ppag->revision > MAX_ANT_GAINS_REVISION) { + printk(BIOS_ERR, "Invalid PPAG revision: %d\n", ppag->revision); + return; + } + + package_size = 1 + 1 + ppag->chains_count * ppag->bands_count; + + acpigen_write_name("PPAG"); + acpigen_write_package(2); + acpigen_write_dword(ppag->revision); + acpigen_write_package(package_size); + acpigen_write_dword(DOMAIN_TYPE_WIFI); + acpigen_write_dword(ppag->mode); + + for (set_num = 0; set_num < ppag->chains_count; set_num++) { + set = ppag_fetch_set(ppag, set_num); + for (i = 0; i < ppag->bands_count; i++) + acpigen_write_byte(set[i]); + } + + acpigen_write_package_end(); + acpigen_write_package_end(); +} + static void emit_sar_acpi_structures(const struct device *dev) { union wifi_sar_limits sar_limits; @@ -236,6 +287,7 @@ static void emit_sar_acpi_structures(const struct device *dev) sar_emit_wrds(sar_limits.sar); sar_emit_ewrd(sar_limits.sar); sar_emit_wgds(sar_limits.wgds); + sar_emit_ppag(sar_limits.ppag); free(sar_limits.sar); } diff --git a/src/include/sar.h b/src/include/sar.h index 625fd51648..e8a1b287b5 100644 --- a/src/include/sar.h +++ b/src/include/sar.h @@ -4,9 +4,10 @@ #include +#define MAX_ANT_GAINS_REVISION 2 #define MAX_DSAR_SET_COUNT 3 #define MAX_GEO_OFFSET_REVISION 3 -#define MAX_PROFILE_COUNT 2 +#define MAX_PROFILE_COUNT 3 #define MAX_SAR_REVISION 2 #define REVISION_SIZE 1 #define SAR_REV0_CHAINS_COUNT 2 @@ -30,6 +31,14 @@ struct sar_profile { uint8_t sar_table[0]; } __packed; +struct gain_profile { + uint8_t revision; + uint8_t mode; + uint8_t chains_count; + uint8_t bands_count; + uint8_t ppag_table[0]; +} __packed; + struct sar_header { char marker[SAR_STR_PREFIX_SIZE]; uint8_t version; @@ -41,6 +50,7 @@ union wifi_sar_limits { struct { struct sar_profile *sar; struct geo_profile *wgds; + struct gain_profile *ppag; }; void *profile[MAX_PROFILE_COUNT]; }; diff --git a/src/vendorcode/google/chromeos/sar.c b/src/vendorcode/google/chromeos/sar.c index d6cb021412..5c16f7606b 100644 --- a/src/vendorcode/google/chromeos/sar.c +++ b/src/vendorcode/google/chromeos/sar.c @@ -68,6 +68,14 @@ static int wgds_table_size(const struct geo_profile *geo) return sizeof(struct geo_profile) + (geo->chains_count * geo->bands_count); } +static int gain_table_size(const struct gain_profile *gain) +{ + if (gain == NULL) + return 0; + + return sizeof(struct gain_profile) + (gain->chains_count * gain->bands_count); +} + static bool valid_legacy_length(size_t bin_len) { if (bin_len == LEGACY_SAR_WGDS_BIN_SIZE) @@ -116,6 +124,7 @@ static int fill_wifi_sar_limits(union wifi_sar_limits *sar_limits, const uint8_t expected_sar_bin_size = header_size; expected_sar_bin_size += sar_table_size(sar_limits->sar); expected_sar_bin_size += wgds_table_size(sar_limits->wgds); + expected_sar_bin_size += gain_table_size(sar_limits->ppag); if (sar_bin_size != expected_sar_bin_size) { printk(BIOS_ERR, "ERROR: Invalid SAR size, expected: %ld, obtained: %ld\n", @@ -178,6 +187,7 @@ static int fill_wifi_sar_limits_legacy(union wifi_sar_limits *sar_limits, * Offsets * [SAR_REVISION,DSAR_SET_COUNT,CHAINS_COUNT,SUBBANDS_COUNT [EWRD]] * [WGDS_REVISION,CHAINS_COUNT,SUBBANDS_COUNT] + * [PPAG_REVISION,MODE,CHAINS_COUNT,SUBBANDS_COUNT] * * 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 @@ -195,6 +205,23 @@ static int fill_wifi_sar_limits_legacy(union wifi_sar_limits *sar_limits, * [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] = + * Supported by Revision 0, 1 and 2 + * [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] + * Supported by Revision 1 and 2 + * [Antenna gain used for 5945-6165MHz frequency] + * [Antenna gain used for 6165-6405MHz frequency] + * [Antenna gain used for 6405-6525MHz frequency] + * [Antenna gain used for 6525-6705MHz frequency] + * [Antenna gain used for 6705-6865MHz frequency] + * [Antenna gain used for 6865-7105MHz frequency] */ int get_wifi_sar_limits(union wifi_sar_limits *sar_limits) {