} __packed; /* TX_REDUCED_POWER_API_S_VER_4 */
#define IWL_NUM_GEO_PROFILES 3
+#define IWL_GEO_PER_CHAIN_SIZE 3
/**
* enum iwl_geo_per_chain_offset_operation - type of operation
struct iwl_per_chain_offset_group table[IWL_NUM_GEO_PROFILES];
} __packed; /* GEO_TX_POWER_LIMIT */
+/**
+ * struct iwl_geo_tx_power_profiles_resp - response to GEO_TX_POWER_LIMIT cmd
+ * @profile_idx: current geo profile in use
+ */
+struct iwl_geo_tx_power_profiles_resp {
+ __le32 profile_idx;
+} __packed; /* GEO_TX_POWER_LIMIT_RESP */
+
/**
* struct iwl_beacon_filter_cmd
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
return ret;
}
-static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm,
- struct iwl_mvm_geo_table *geo_table)
+static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
{
union acpi_object *wifi_pkg;
acpi_handle root_handle;
acpi_handle handle;
struct acpi_buffer wgds = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
- int i, ret;
+ int i, j, ret;
+ int idx = 1;
root_handle = ACPI_HANDLE(mvm->dev);
if (!root_handle) {
goto out_free;
}
- for (i = 0; i < ACPI_WGDS_WIFI_DATA_SIZE; i++) {
- union acpi_object *entry;
+ for (i = 0; i < IWL_NUM_GEO_PROFILES; i++) {
+ for (j = 0; j < IWL_MVM_GEO_TABLE_SIZE; j++) {
+ union acpi_object *entry;
- entry = &wifi_pkg->package.elements[i + 1];
- if ((entry->type != ACPI_TYPE_INTEGER) ||
- (entry->integer.value > U8_MAX))
- return -EINVAL;
+ entry = &wifi_pkg->package.elements[idx++];
+ if ((entry->type != ACPI_TYPE_INTEGER) ||
+ (entry->integer.value > U8_MAX))
+ return -EINVAL;
- geo_table->values[i] = entry->integer.value;
+ mvm->geo_profiles[i].values[j] = entry->integer.value;
+ }
}
ret = 0;
out_free:
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
}
+int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
+{
+ struct iwl_geo_tx_power_profiles_resp *resp;
+ int ret;
+
+ struct iwl_geo_tx_power_profiles_cmd geo_cmd = {
+ .ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE),
+ };
+ struct iwl_host_cmd cmd = {
+ .id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
+ .len = { sizeof(geo_cmd), },
+ .flags = CMD_WANT_SKB,
+ .data = { &geo_cmd },
+ };
+
+ ret = iwl_mvm_send_cmd(mvm, &cmd);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret);
+ return ret;
+ }
+
+ resp = (void *)cmd.resp_pkt->data;
+ ret = le32_to_cpu(resp->profile_idx);
+ if (WARN_ON(ret > IWL_NUM_GEO_PROFILES)) {
+ ret = -EIO;
+ IWL_WARN(mvm, "Invalid geographic profile idx (%d)\n", ret);
+ }
+
+ iwl_free_resp(&cmd);
+ return ret;
+}
+
static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
{
- struct iwl_mvm_geo_table geo_table;
struct iwl_geo_tx_power_profiles_cmd cmd = {
.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
};
- int ret, i, j, idx;
+ int ret, i, j;
u16 cmd_wide_id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);
- ret = iwl_mvm_sar_get_wgds_table(mvm, &geo_table);
+ ret = iwl_mvm_sar_get_wgds_table(mvm);
if (ret < 0) {
IWL_DEBUG_RADIO(mvm,
"Geo SAR BIOS table invalid or unavailable. (%d)\n",
for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) {
u8 *value;
- idx = i * ACPI_WGDS_NUM_BANDS * ACPI_WGDS_TABLE_SIZE +
- j * ACPI_WGDS_TABLE_SIZE;
- value = &geo_table.values[idx];
+ value = &mvm->geo_profiles[i].values[j *
+ IWL_GEO_PER_CHAIN_SIZE];
chain[j].max_tx_power = cpu_to_le16(value[0]);
chain[j].chain_a = value[1];
chain[j].chain_b = value[2];
#ifdef CONFIG_ACPI
#define IWL_MVM_SAR_TABLE_SIZE 10
#define IWL_MVM_SAR_PROFILE_NUM 4
-#define IWL_MVM_GEO_TABLE_SIZE 18
+#define IWL_MVM_GEO_TABLE_SIZE 6
struct iwl_mvm_sar_profile {
bool enabled;
u8 table[IWL_MVM_SAR_TABLE_SIZE];
};
-struct iwl_mvm_geo_table {
+struct iwl_mvm_geo_profile {
u8 values[IWL_MVM_GEO_TABLE_SIZE];
};
#endif
struct delayed_work cs_tx_unblock_dwork;
#ifdef CONFIG_ACPI
struct iwl_mvm_sar_profile sar_profiles[IWL_MVM_SAR_PROFILE_NUM];
+ struct iwl_mvm_geo_profile geo_profiles[IWL_NUM_GEO_PROFILES];
#endif
};
#ifdef CONFIG_ACPI
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b);
+int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm);
#else
static inline
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
{
return -ENOENT;
}
+
+static inline
+int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
+{
+ return -ENOENT;
+}
#endif /* CONFIG_ACPI */
#endif /* __IWL_MVM_H__ */