mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-05-24 10:39:52 +00:00
wifi: iwlwifi: prepare for reading PPAG table from UEFI
As PPAG table is going to be read from UEFI, there are some cleanups required: Move functions/definitions that are common to both UEFI and ACPI to regulatory.h/c. In addition, rename the functions/macros names so it will be clear which one is ACPI specific, and which is common for ACPI and UEFI. Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Reviewed-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://msgid.link/20240131091413.25623670b422.I8132af7517e4faf0ea8cbeb2efe9651edd319b98@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
be3a8cbb1c
commit
09059c6764
5 changed files with 187 additions and 203 deletions
|
@ -4,7 +4,6 @@
|
||||||
* Copyright (C) 2019-2023 Intel Corporation
|
* Copyright (C) 2019-2023 Intel Corporation
|
||||||
*/
|
*/
|
||||||
#include <linux/uuid.h>
|
#include <linux/uuid.h>
|
||||||
#include <linux/dmi.h>
|
|
||||||
#include "iwl-drv.h"
|
#include "iwl-drv.h"
|
||||||
#include "iwl-debug.h"
|
#include "iwl-debug.h"
|
||||||
#include "acpi.h"
|
#include "acpi.h"
|
||||||
|
@ -20,63 +19,6 @@ const guid_t iwl_rfi_guid = GUID_INIT(0x7266172C, 0x220B, 0x4B29,
|
||||||
0xDD, 0x26, 0xB5, 0xFD);
|
0xDD, 0x26, 0xB5, 0xFD);
|
||||||
IWL_EXPORT_SYMBOL(iwl_rfi_guid);
|
IWL_EXPORT_SYMBOL(iwl_rfi_guid);
|
||||||
|
|
||||||
static const struct dmi_system_id dmi_ppag_approved_list[] = {
|
|
||||||
{ .ident = "HP",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ .ident = "SAMSUNG",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ .ident = "MSFT",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ .ident = "ASUS",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ .ident = "GOOGLE-HP",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
|
||||||
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ .ident = "GOOGLE-ASUS",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
|
||||||
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek COMPUTER INC."),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ .ident = "GOOGLE-SAMSUNG",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
|
||||||
DMI_MATCH(DMI_BOARD_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ .ident = "DELL",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ .ident = "DELL",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ .ident = "RAZER",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "Razer"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int iwl_acpi_get_handle(struct device *dev, acpi_string method,
|
static int iwl_acpi_get_handle(struct device *dev, acpi_string method,
|
||||||
acpi_handle *ret_handle)
|
acpi_handle *ret_handle)
|
||||||
{
|
{
|
||||||
|
@ -1002,7 +944,7 @@ read_table:
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrt->ppag_flags = flags->integer.value & ACPI_PPAG_MASK;
|
fwrt->ppag_flags = flags->integer.value & IWL_PPAG_ETSI_CHINA_MASK;
|
||||||
cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
|
cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
|
||||||
WIDE_ID(PHY_OPS_GROUP,
|
WIDE_ID(PHY_OPS_GROUP,
|
||||||
PER_PLATFORM_ANT_GAIN_CMD),
|
PER_PLATFORM_ANT_GAIN_CMD),
|
||||||
|
@ -1036,11 +978,11 @@ read_table:
|
||||||
if (cmd_ver >= 4)
|
if (cmd_ver >= 4)
|
||||||
continue;
|
continue;
|
||||||
if ((j == 0 &&
|
if ((j == 0 &&
|
||||||
(fwrt->ppag_chains[i].subbands[j] > ACPI_PPAG_MAX_LB ||
|
(fwrt->ppag_chains[i].subbands[j] > IWL_PPAG_MAX_LB ||
|
||||||
fwrt->ppag_chains[i].subbands[j] < ACPI_PPAG_MIN_LB)) ||
|
fwrt->ppag_chains[i].subbands[j] < IWL_PPAG_MIN_LB)) ||
|
||||||
(j != 0 &&
|
(j != 0 &&
|
||||||
(fwrt->ppag_chains[i].subbands[j] > ACPI_PPAG_MAX_HB ||
|
(fwrt->ppag_chains[i].subbands[j] > IWL_PPAG_MAX_HB ||
|
||||||
fwrt->ppag_chains[i].subbands[j] < ACPI_PPAG_MIN_HB))) {
|
fwrt->ppag_chains[i].subbands[j] < IWL_PPAG_MIN_HB))) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
@ -1056,110 +998,6 @@ out_free:
|
||||||
}
|
}
|
||||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_ppag_table);
|
IWL_EXPORT_SYMBOL(iwl_acpi_get_ppag_table);
|
||||||
|
|
||||||
int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
|
||||||
union iwl_ppag_table_cmd *cmd,
|
|
||||||
int *cmd_size)
|
|
||||||
{
|
|
||||||
u8 cmd_ver;
|
|
||||||
int i, j, num_sub_bands;
|
|
||||||
s8 *gain;
|
|
||||||
|
|
||||||
/* many firmware images for JF lie about this */
|
|
||||||
if (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id) ==
|
|
||||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF))
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
if (!fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
|
|
||||||
IWL_DEBUG_RADIO(fwrt,
|
|
||||||
"PPAG capability not supported by FW, command not sent.\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
|
|
||||||
WIDE_ID(PHY_OPS_GROUP,
|
|
||||||
PER_PLATFORM_ANT_GAIN_CMD),
|
|
||||||
IWL_FW_CMD_VER_UNKNOWN);
|
|
||||||
if (!fwrt->ppag_table_valid || (cmd_ver <= 3 && !fwrt->ppag_flags)) {
|
|
||||||
IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The 'flags' field is the same in v1 and in v2 so we can just
|
|
||||||
* use v1 to access it.
|
|
||||||
*/
|
|
||||||
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
|
|
||||||
|
|
||||||
IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
|
|
||||||
if (cmd_ver == 1) {
|
|
||||||
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
|
|
||||||
gain = cmd->v1.gain[0];
|
|
||||||
*cmd_size = sizeof(cmd->v1);
|
|
||||||
if (fwrt->ppag_ver == 1 || fwrt->ppag_ver == 2) {
|
|
||||||
/* in this case FW supports revision 0 */
|
|
||||||
IWL_DEBUG_RADIO(fwrt,
|
|
||||||
"PPAG table rev is %d, send truncated table\n",
|
|
||||||
fwrt->ppag_ver);
|
|
||||||
}
|
|
||||||
} else if (cmd_ver >= 2 && cmd_ver <= 4) {
|
|
||||||
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
|
|
||||||
gain = cmd->v2.gain[0];
|
|
||||||
*cmd_size = sizeof(cmd->v2);
|
|
||||||
if (fwrt->ppag_ver == 0) {
|
|
||||||
/* in this case FW supports revisions 1 or 2 */
|
|
||||||
IWL_DEBUG_RADIO(fwrt,
|
|
||||||
"PPAG table rev is 0, send padded table\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ppag mode */
|
|
||||||
IWL_DEBUG_RADIO(fwrt,
|
|
||||||
"PPAG MODE bits were read from bios: %d\n",
|
|
||||||
cmd->v1.flags);
|
|
||||||
if ((cmd_ver == 1 && !fw_has_capa(&fwrt->fw->ucode_capa,
|
|
||||||
IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) ||
|
|
||||||
(cmd_ver == 2 && fwrt->ppag_ver == 2)) {
|
|
||||||
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
|
|
||||||
IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
|
|
||||||
} else {
|
|
||||||
IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
IWL_DEBUG_RADIO(fwrt,
|
|
||||||
"PPAG MODE bits going to be sent: %d\n",
|
|
||||||
cmd->v1.flags);
|
|
||||||
|
|
||||||
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
|
|
||||||
for (j = 0; j < num_sub_bands; j++) {
|
|
||||||
gain[i * num_sub_bands + j] =
|
|
||||||
fwrt->ppag_chains[i].subbands[j];
|
|
||||||
IWL_DEBUG_RADIO(fwrt,
|
|
||||||
"PPAG table: chain[%d] band[%d]: gain = %d\n",
|
|
||||||
i, j, gain[i * num_sub_bands + j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
IWL_EXPORT_SYMBOL(iwl_fill_ppag_table);
|
|
||||||
|
|
||||||
bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!dmi_check_system(dmi_ppag_approved_list)) {
|
|
||||||
IWL_DEBUG_RADIO(fwrt,
|
|
||||||
"System vendor '%s' is not in the approved list, disabling PPAG.\n",
|
|
||||||
dmi_get_system_info(DMI_SYS_VENDOR));
|
|
||||||
fwrt->ppag_flags = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
IWL_EXPORT_SYMBOL(iwl_acpi_is_ppag_approved);
|
|
||||||
|
|
||||||
void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
||||||
struct iwl_phy_specific_cfg *filters)
|
struct iwl_phy_specific_cfg *filters)
|
||||||
{
|
{
|
||||||
|
|
|
@ -94,29 +94,12 @@
|
||||||
#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((IWL_NUM_CHAIN_LIMITS * \
|
#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((IWL_NUM_CHAIN_LIMITS * \
|
||||||
IWL_NUM_SUB_BANDS_V2) + 2)
|
IWL_NUM_SUB_BANDS_V2) + 2)
|
||||||
|
|
||||||
/* PPAG gain value bounds in 1/8 dBm */
|
|
||||||
#define ACPI_PPAG_MIN_LB -16
|
|
||||||
#define ACPI_PPAG_MAX_LB 24
|
|
||||||
#define ACPI_PPAG_MIN_HB -16
|
|
||||||
#define ACPI_PPAG_MAX_HB 40
|
|
||||||
#define ACPI_PPAG_MASK 3
|
|
||||||
#define IWL_PPAG_ETSI_MASK BIT(0)
|
|
||||||
|
|
||||||
#define IWL_SAR_ENABLE_MSK BIT(0)
|
#define IWL_SAR_ENABLE_MSK BIT(0)
|
||||||
#define IWL_REDUCE_POWER_FLAGS_POS 1
|
#define IWL_REDUCE_POWER_FLAGS_POS 1
|
||||||
|
|
||||||
/* The Inidcator whether UEFI WIFI GUID tables are locked is read from ACPI */
|
/* The Inidcator whether UEFI WIFI GUID tables are locked is read from ACPI */
|
||||||
#define UEFI_WIFI_GUID_UNLOCKED 0
|
#define UEFI_WIFI_GUID_UNLOCKED 0
|
||||||
|
|
||||||
/*
|
|
||||||
* The profile for revision 2 is a superset of revision 1, which is in
|
|
||||||
* turn a superset of revision 0. So we can store all revisions
|
|
||||||
* inside revision 2, which is what we represent here.
|
|
||||||
*/
|
|
||||||
struct iwl_ppag_chain {
|
|
||||||
s8 subbands[ACPI_SAR_NUM_SUB_BANDS_REV2];
|
|
||||||
};
|
|
||||||
|
|
||||||
enum iwl_dsm_funcs_rev_0 {
|
enum iwl_dsm_funcs_rev_0 {
|
||||||
DSM_FUNC_QUERY = 0,
|
DSM_FUNC_QUERY = 0,
|
||||||
DSM_FUNC_DISABLE_SRD = 1,
|
DSM_FUNC_DISABLE_SRD = 1,
|
||||||
|
@ -207,12 +190,6 @@ __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt);
|
||||||
|
|
||||||
int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt);
|
int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt);
|
||||||
|
|
||||||
int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
|
||||||
union iwl_ppag_table_cmd *cmd,
|
|
||||||
int *cmd_size);
|
|
||||||
|
|
||||||
bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt);
|
|
||||||
|
|
||||||
void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
||||||
struct iwl_phy_specific_cfg *filters);
|
struct iwl_phy_specific_cfg *filters);
|
||||||
|
|
||||||
|
@ -284,18 +261,6 @@ static inline int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
|
||||||
union iwl_ppag_table_cmd *cmd,
|
|
||||||
int *cmd_size)
|
|
||||||
{
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
static inline void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
||||||
struct iwl_phy_specific_cfg *filters)
|
struct iwl_phy_specific_cfg *filters)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2023 Intel Corporation
|
* Copyright (C) 2023 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
#include <linux/dmi.h>
|
||||||
#include "iwl-drv.h"
|
#include "iwl-drv.h"
|
||||||
#include "iwl-debug.h"
|
#include "iwl-debug.h"
|
||||||
#include "regulatory.h"
|
#include "regulatory.h"
|
||||||
|
@ -24,6 +25,63 @@ IWL_BIOS_TABLE_LOADER(wrds);
|
||||||
IWL_BIOS_TABLE_LOADER(ewrd);
|
IWL_BIOS_TABLE_LOADER(ewrd);
|
||||||
IWL_BIOS_TABLE_LOADER(wgds);
|
IWL_BIOS_TABLE_LOADER(wgds);
|
||||||
|
|
||||||
|
static const struct dmi_system_id dmi_ppag_approved_list[] = {
|
||||||
|
{ .ident = "HP",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .ident = "SAMSUNG",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .ident = "MSFT",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .ident = "ASUS",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .ident = "GOOGLE-HP",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||||
|
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .ident = "GOOGLE-ASUS",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||||
|
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek COMPUTER INC."),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .ident = "GOOGLE-SAMSUNG",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||||
|
DMI_MATCH(DMI_BOARD_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .ident = "DELL",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .ident = "DELL",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .ident = "RAZER",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Razer"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
|
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -147,3 +205,106 @@ int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
IWL_EXPORT_SYMBOL(iwl_sar_fill_profile);
|
IWL_EXPORT_SYMBOL(iwl_sar_fill_profile);
|
||||||
|
|
||||||
|
int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||||
|
union iwl_ppag_table_cmd *cmd, int *cmd_size)
|
||||||
|
{
|
||||||
|
u8 cmd_ver;
|
||||||
|
int i, j, num_sub_bands;
|
||||||
|
s8 *gain;
|
||||||
|
|
||||||
|
/* many firmware images for JF lie about this */
|
||||||
|
if (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id) ==
|
||||||
|
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (!fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
|
||||||
|
IWL_DEBUG_RADIO(fwrt,
|
||||||
|
"PPAG capability not supported by FW, command not sent.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
|
||||||
|
WIDE_ID(PHY_OPS_GROUP,
|
||||||
|
PER_PLATFORM_ANT_GAIN_CMD),
|
||||||
|
IWL_FW_CMD_VER_UNKNOWN);
|
||||||
|
if (!fwrt->ppag_table_valid || (cmd_ver <= 3 && !fwrt->ppag_flags)) {
|
||||||
|
IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The 'flags' field is the same in v1 and in v2 so we can just
|
||||||
|
* use v1 to access it.
|
||||||
|
*/
|
||||||
|
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
|
||||||
|
|
||||||
|
IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
|
||||||
|
if (cmd_ver == 1) {
|
||||||
|
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
|
||||||
|
gain = cmd->v1.gain[0];
|
||||||
|
*cmd_size = sizeof(cmd->v1);
|
||||||
|
if (fwrt->ppag_ver == 1 || fwrt->ppag_ver == 2) {
|
||||||
|
/* in this case FW supports revision 0 */
|
||||||
|
IWL_DEBUG_RADIO(fwrt,
|
||||||
|
"PPAG table rev is %d, send truncated table\n",
|
||||||
|
fwrt->ppag_ver);
|
||||||
|
}
|
||||||
|
} else if (cmd_ver >= 2 && cmd_ver <= 4) {
|
||||||
|
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
|
||||||
|
gain = cmd->v2.gain[0];
|
||||||
|
*cmd_size = sizeof(cmd->v2);
|
||||||
|
if (fwrt->ppag_ver == 0) {
|
||||||
|
/* in this case FW supports revisions 1 or 2 */
|
||||||
|
IWL_DEBUG_RADIO(fwrt,
|
||||||
|
"PPAG table rev is 0, send padded table\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ppag mode */
|
||||||
|
IWL_DEBUG_RADIO(fwrt,
|
||||||
|
"PPAG MODE bits were read from bios: %d\n",
|
||||||
|
cmd->v1.flags);
|
||||||
|
if ((cmd_ver == 1 &&
|
||||||
|
!fw_has_capa(&fwrt->fw->ucode_capa,
|
||||||
|
IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) ||
|
||||||
|
(cmd_ver == 2 && fwrt->ppag_ver == 2)) {
|
||||||
|
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
|
||||||
|
IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
|
||||||
|
} else {
|
||||||
|
IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
IWL_DEBUG_RADIO(fwrt,
|
||||||
|
"PPAG MODE bits going to be sent: %d\n",
|
||||||
|
cmd->v1.flags);
|
||||||
|
|
||||||
|
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
|
||||||
|
for (j = 0; j < num_sub_bands; j++) {
|
||||||
|
gain[i * num_sub_bands + j] =
|
||||||
|
fwrt->ppag_chains[i].subbands[j];
|
||||||
|
IWL_DEBUG_RADIO(fwrt,
|
||||||
|
"PPAG table: chain[%d] band[%d]: gain = %d\n",
|
||||||
|
i, j, gain[i * num_sub_bands + j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
IWL_EXPORT_SYMBOL(iwl_fill_ppag_table);
|
||||||
|
|
||||||
|
bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt)
|
||||||
|
{
|
||||||
|
if (!dmi_check_system(dmi_ppag_approved_list)) {
|
||||||
|
IWL_DEBUG_RADIO(fwrt,
|
||||||
|
"System vendor '%s' is not in the approved list, disabling PPAG.\n",
|
||||||
|
dmi_get_system_info(DMI_SYS_VENDOR));
|
||||||
|
fwrt->ppag_flags = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
IWL_EXPORT_SYMBOL(iwl_is_ppag_approved);
|
||||||
|
|
|
@ -31,6 +31,15 @@
|
||||||
|
|
||||||
#define IWL_SAR_ENABLE_MSK BIT(0)
|
#define IWL_SAR_ENABLE_MSK BIT(0)
|
||||||
|
|
||||||
|
/* PPAG gain value bounds in 1/8 dBm */
|
||||||
|
#define IWL_PPAG_MIN_LB -16
|
||||||
|
#define IWL_PPAG_MAX_LB 24
|
||||||
|
#define IWL_PPAG_MIN_HB -16
|
||||||
|
#define IWL_PPAG_MAX_HB 40
|
||||||
|
|
||||||
|
#define IWL_PPAG_ETSI_CHINA_MASK 3
|
||||||
|
#define IWL_PPAG_ETSI_MASK BIT(0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The profile for revision 2 is a superset of revision 1, which is in
|
* The profile for revision 2 is a superset of revision 1, which is in
|
||||||
* turn a superset of revision 0. So we can store all revisions
|
* turn a superset of revision 0. So we can store all revisions
|
||||||
|
@ -75,6 +84,11 @@ struct iwl_geo_profile {
|
||||||
struct iwl_geo_profile_band bands[BIOS_GEO_MAX_NUM_BANDS];
|
struct iwl_geo_profile_band bands[BIOS_GEO_MAX_NUM_BANDS];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Same thing as with SAR, all revisions fit in revision 2 */
|
||||||
|
struct iwl_ppag_chain {
|
||||||
|
s8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM];
|
||||||
|
};
|
||||||
|
|
||||||
struct iwl_fw_runtime;
|
struct iwl_fw_runtime;
|
||||||
|
|
||||||
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
|
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
|
||||||
|
@ -87,6 +101,12 @@ int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,
|
||||||
__le16 *per_chain, u32 n_tables, u32 n_subbands,
|
__le16 *per_chain, u32 n_tables, u32 n_subbands,
|
||||||
int prof_a, int prof_b);
|
int prof_a, int prof_b);
|
||||||
|
|
||||||
|
int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||||
|
union iwl_ppag_table_cmd *cmd,
|
||||||
|
int *cmd_size);
|
||||||
|
|
||||||
|
bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);
|
||||||
|
|
||||||
int iwl_bios_get_wrds_table(struct iwl_fw_runtime *fwrt);
|
int iwl_bios_get_wrds_table(struct iwl_fw_runtime *fwrt);
|
||||||
|
|
||||||
int iwl_bios_get_ewrd_table(struct iwl_fw_runtime *fwrt);
|
int iwl_bios_get_ewrd_table(struct iwl_fw_runtime *fwrt);
|
||||||
|
|
|
@ -1104,7 +1104,7 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
|
||||||
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
|
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
|
||||||
{
|
{
|
||||||
/* no need to read the table, done in INIT stage */
|
/* no need to read the table, done in INIT stage */
|
||||||
if (!(iwl_acpi_is_ppag_approved(&mvm->fwrt)))
|
if (!(iwl_is_ppag_approved(&mvm->fwrt)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return iwl_mvm_ppag_send_cmd(mvm);
|
return iwl_mvm_ppag_send_cmd(mvm);
|
||||||
|
|
Loading…
Add table
Reference in a new issue