#define IWL_NUM_CHAIN_LIMITS 2
#define IWL_NUM_SUB_BANDS_V1 5
#define IWL_NUM_SUB_BANDS_V2 11
+#define IWL_NUM_SUB_BANDS_V3 12
/**
* struct iwl_dev_tx_power_common - Common part of the TX power reduction cmd
* @v1: command version 1 structure.
* @v5: command version 5 structure.
* @v7: command version 7 structure.
+ * @v8: command version 8 structure.
* @v1.flags: values from &enum iwl_ppag_flags
* @v1.gain: table of antenna gain values per chain and sub-band
* @v1.reserved: reserved
* @v7.ppag_config_info: see @struct bios_value_u32
* @v7.gain: table of antenna gain values per chain and sub-band
* @v7.reserved: reserved
+ * @v8.ppag_config_info: see @struct bios_value_u32
+ * @v8.gain: table of antenna gain values per chain and sub-band
*/
union iwl_ppag_table_cmd {
struct {
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
s8 reserved[2];
} __packed v7; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */
+ struct {
+ struct bios_value_u32 ppag_config_info;
+ s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3];
+ } __packed v8; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_8 */
} __packed;
#define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
}
IWL_EXPORT_SYMBOL(iwl_is_ppag_approved);
+/* Print the PPAG table as read from BIOS */
+void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands)
+{
+ int i, j;
+
+ IWL_DEBUG_RADIO(fwrt, "PPAG table as read from BIOS:\n");
+ IWL_DEBUG_RADIO(fwrt, "PPAG revision = %d\n", fwrt->ppag_bios_rev);
+ IWL_DEBUG_RADIO(fwrt, "PPAG flags = 0x%x\n", fwrt->ppag_flags);
+
+ if (WARN_ON_ONCE(n_subbands >
+ ARRAY_SIZE(fwrt->ppag_chains[0].subbands)))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(fwrt->ppag_chains); i++)
+ for (j = 0; j < n_subbands; j++)
+ IWL_DEBUG_RADIO(fwrt,
+ "ppag_chains[%d].subbands[%d] = %d\n",
+ i, j,
+ fwrt->ppag_chains[i].subbands[j]);
+}
+
bool iwl_is_tas_approved(void)
{
return dmi_check_system(dmi_tas_approved_list);
#define BIOS_SAR_MAX_CHAINS_PER_PROFILE 4
#define BIOS_SAR_NUM_CHAINS 2
#define BIOS_SAR_MAX_SUB_BANDS_NUM 11
+#define BIOS_PPAG_MAX_SUB_BANDS_NUM 12
#define BIOS_GEO_NUM_CHAINS 2
#define BIOS_GEO_MAX_NUM_BANDS 3
/* Same thing as with SAR, all revisions fit in revision 2 */
struct iwl_ppag_chain {
- s8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM];
+ s8 subbands[BIOS_PPAG_MAX_SUB_BANDS_NUM];
};
struct iwl_tas_data {
struct iwl_fw_runtime;
+/* Print the PPAG table as read from BIOS */
+void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands);
+
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,
{
struct iwl_fw_runtime *fwrt = &mld->fwrt;
union iwl_ppag_table_cmd cmd = {
- .v7.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source,
- .v7.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev,
- .v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
+ /* v7 and v8 have the same layout for the ppag_config_info */
+ .v8.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source,
+ .v8.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev,
+ .v8.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
};
+ int cmd_ver =
+ iwl_fw_lookup_cmd_ver(mld->fw,
+ WIDE_ID(PHY_OPS_GROUP,
+ PER_PLATFORM_ANT_GAIN_CMD), 1);
+ int cmd_len = sizeof(cmd.v8);
int ret;
+ BUILD_BUG_ON(offsetof(typeof(cmd), v8.ppag_config_info.hdr) !=
+ offsetof(typeof(cmd), v7.ppag_config_info.hdr));
+ BUILD_BUG_ON(offsetof(typeof(cmd), v8.gain) !=
+ offsetof(typeof(cmd), v7.gain));
+
+ BUILD_BUG_ON(ARRAY_SIZE(cmd.v7.gain) > ARRAY_SIZE(fwrt->ppag_chains));
+ BUILD_BUG_ON(ARRAY_SIZE(cmd.v7.gain[0]) >
+ ARRAY_SIZE(fwrt->ppag_chains[0].subbands));
+ BUILD_BUG_ON(ARRAY_SIZE(cmd.v8.gain) > ARRAY_SIZE(fwrt->ppag_chains));
+ BUILD_BUG_ON(ARRAY_SIZE(cmd.v8.gain[0]) >
+ ARRAY_SIZE(fwrt->ppag_chains[0].subbands));
+
IWL_DEBUG_RADIO(fwrt,
"PPAG MODE bits going to be sent: %d\n",
fwrt->ppag_flags);
- for (int chain = 0; chain < IWL_NUM_CHAIN_LIMITS; chain++) {
- for (int subband = 0; subband < IWL_NUM_SUB_BANDS_V2; subband++) {
- cmd.v7.gain[chain][subband] =
- fwrt->ppag_chains[chain].subbands[subband];
- IWL_DEBUG_RADIO(fwrt,
- "PPAG table: chain[%d] band[%d]: gain = %d\n",
- chain, subband, cmd.v7.gain[chain][subband]);
+ /* Since ver 7 will be deprecated at some point, don't bother making
+ * this code generic for both ver 7 and ver 8: duplicate the code.
+ */
+ if (cmd_ver == 7) {
+ for (int chain = 0; chain < ARRAY_SIZE(cmd.v7.gain); chain++) {
+ for (int subband = 0;
+ subband < ARRAY_SIZE(cmd.v7.gain[0]);
+ subband++) {
+ cmd.v7.gain[chain][subband] =
+ fwrt->ppag_chains[chain].subbands[subband];
+ IWL_DEBUG_RADIO(fwrt,
+ "PPAG table: chain[%d] band[%d]: gain = %d\n",
+ chain, subband,
+ cmd.v7.gain[chain][subband]);
+ }
}
+ cmd_len = sizeof(cmd.v7);
+ } else if (cmd_ver == 8) {
+ for (int chain = 0; chain < ARRAY_SIZE(cmd.v8.gain); chain++) {
+ for (int subband = 0;
+ subband < ARRAY_SIZE(cmd.v8.gain[0]);
+ subband++) {
+ cmd.v8.gain[chain][subband] =
+ fwrt->ppag_chains[chain].subbands[subband];
+ IWL_DEBUG_RADIO(fwrt,
+ "PPAG table: chain[%d] band[%d]: gain = %d\n",
+ chain, subband,
+ cmd.v8.gain[chain][subband]);
+ }
+ }
+ } else {
+ WARN(1, "Bad version for PER_PLATFORM_ANT_GAIN_CMD %d\n",
+ cmd_ver);
+ return -EINVAL;
}
IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP,
PER_PLATFORM_ANT_GAIN_CMD),
- &cmd, sizeof(cmd.v7));
+ &cmd, cmd_len);
if (ret < 0)
IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
ret);