Browse Source

qcacmn: Add SAR power limit configuration

There is a regulatory requirement for Specific Absorption
Rate (SAR) whereby the phone transmit power is reduced
when it is determined that the phone is in close
proximity to the body.
Implement a vendor command interface to set SAR power
limts dynamically.

Change-Id: I0a214a2af780e9dd8c381c4e9eaa7d8cab6ef853
CRs-Fixed: 1098102
Manikandan Mohan 8 years ago
parent
commit
360f646c3b

+ 2 - 0
wmi/inc/wmi_unified_api.h

@@ -1311,6 +1311,8 @@ QDF_STATUS wmi_extract_vdev_extd_stats(void *wmi_hdl, void *evt_buf,
 
 QDF_STATUS wmi_unified_send_power_dbg_cmd(void *wmi_hdl,
 				struct wmi_power_dbg_params *param);
+QDF_STATUS wmi_unified_send_sar_limit_cmd(void *wmi_hdl,
+				struct sar_limit_cmd_params *params);
 QDF_STATUS wmi_unified_send_adapt_dwelltime_params_cmd(void *wmi_hdl,
 				   struct wmi_adaptive_dwelltime_params *
 				   wmi_param);

+ 31 - 0
wmi/inc/wmi_unified_param.h

@@ -7010,6 +7010,37 @@ typedef struct {
 	uint32_t tx_mu_transmitted;
 } wmi_host_peer_txmu_cnt_event;
 
+#define MAX_SAR_LIMIT_ROWS_SUPPORTED 64
+/**
+ * struct sar_limit_cmd_row - sar limts row
+ * @band_id: Optional param for frequency band
+ * @chain_id: Optional param for antenna chain id
+ * @mod_id: Optional param for modulation scheme
+ * @limit_value: Mandatory param providing power limits in steps of 0.5 dbm
+ * @validity_bitmap: bitmap of valid optional params in sar_limit_cmd_row struct
+ */
+struct sar_limit_cmd_row {
+	uint32_t band_id;
+	uint32_t chain_id;
+	uint32_t mod_id;
+	uint32_t limit_value;
+	uint32_t validity_bitmap;
+};
+
+/**
+ * struct sar_limit_cmd_params - sar limts params
+ * @sar_enable: flag to enable SAR
+ * @num_limit_rows: number of items in sar_limits
+ * @commit_limits: indicates firmware to start apply new SAR values
+ * @sar_limit_row_list: pointer to array of sar limit rows
+ */
+struct sar_limit_cmd_params {
+	uint32_t sar_enable;
+	uint32_t num_limit_rows;
+	uint32_t commit_limits;
+	struct sar_limit_cmd_row *sar_limit_row_list;
+};
+
 /*
  * struct wmi_peer_gid_userpos_list_event
  * @usr_list - User list

+ 3 - 0
wmi/inc/wmi_unified_priv.h

@@ -1180,6 +1180,9 @@ QDF_STATUS (*send_fw_test_cmd)(wmi_unified_t wmi_handle,
 QDF_STATUS (*send_encrypt_decrypt_send_cmd)(wmi_unified_t wmi_handle,
 				struct encrypt_decrypt_req_params *params);
 
+QDF_STATUS (*send_sar_limit_cmd)(wmi_unified_t wmi_handle,
+				struct sar_limit_cmd_params *params);
+
 QDF_STATUS (*send_peer_rx_reorder_queue_setup_cmd)(wmi_unified_t wmi_handle,
 		struct rx_reorder_queue_setup_params *param);
 

+ 19 - 0
wmi/src/wmi_unified_api.c

@@ -6365,6 +6365,25 @@ QDF_STATUS wmi_unified_send_power_dbg_cmd(void *wmi_hdl,
 	return QDF_STATUS_E_FAILURE;
 }
 
+/**
+ * wmi_unified_send_sar_limit_cmd() - send sar limit cmd to fw
+ * @wmi_hdl: wmi handle
+ * @params: sar limit command params
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS wmi_unified_send_sar_limit_cmd(void *wmi_hdl,
+				struct sar_limit_cmd_params *params)
+{
+	wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl;
+
+	if (wmi_handle->ops->send_sar_limit_cmd)
+		return wmi_handle->ops->send_sar_limit_cmd(
+						wmi_handle,
+						params);
+	return QDF_STATUS_E_FAILURE;
+}
+
 /**
  * wmi_unified_encrypt_decrypt_send_cmd() - send encryptdecrypt cmd to fw
  * @wmi_hdl: wmi handle

+ 83 - 0
wmi/src/wmi_unified_tlv.c

@@ -4182,6 +4182,88 @@ QDF_STATUS send_setup_install_key_cmd_tlv(wmi_unified_t wmi_handle,
 	return status;
 }
 
+/**
+ * send_sar_limit_cmd_tlv() - send sar limit cmd to fw
+ * @wmi_handle: wmi handle
+ * @params: sar limit params
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code
+ */
+static QDF_STATUS send_sar_limit_cmd_tlv(wmi_unified_t wmi_handle,
+		struct sar_limit_cmd_params *sar_limit_params)
+{
+	wmi_buf_t buf;
+	QDF_STATUS qdf_status;
+	wmi_sar_limits_cmd_fixed_param *cmd;
+	int i;
+	uint8_t *buf_ptr;
+	wmi_sar_limit_cmd_row *wmi_sar_rows_list;
+	struct sar_limit_cmd_row *sar_rows_list;
+	uint32_t len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
+
+	len += sizeof(wmi_sar_limit_cmd_row) * sar_limit_params->num_limit_rows;
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf) {
+		WMI_LOGE("Failed to allocate memory");
+		qdf_status = QDF_STATUS_E_NOMEM;
+		goto end;
+	}
+
+	buf_ptr = (uint8_t *) wmi_buf_data(buf);
+	cmd = (wmi_sar_limits_cmd_fixed_param *) buf_ptr;
+	WMITLV_SET_HDR(&cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_sar_limits_cmd_fixed_param,
+		       WMITLV_GET_STRUCT_TLVLEN
+		       (wmi_sar_limits_cmd_fixed_param));
+	cmd->sar_enable = sar_limit_params->sar_enable;
+	cmd->commit_limits = sar_limit_params->commit_limits;
+	cmd->num_limit_rows = sar_limit_params->num_limit_rows;
+
+	WMI_LOGD("no of sar rows = %d, len = %d",
+		 sar_limit_params->num_limit_rows, len);
+	buf_ptr += sizeof(*cmd);
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+		       sizeof(wmi_sar_limit_cmd_row) *
+			       sar_limit_params->num_limit_rows);
+	if (cmd->num_limit_rows == 0)
+		goto send_sar_limits;
+
+	wmi_sar_rows_list = (wmi_sar_limit_cmd_row *)
+			(buf_ptr + WMI_TLV_HDR_SIZE);
+	sar_rows_list = sar_limit_params->sar_limit_row_list;
+
+	for (i = 0; i < sar_limit_params->num_limit_rows; i++) {
+		WMITLV_SET_HDR(&wmi_sar_rows_list->tlv_header,
+			       WMITLV_TAG_STRUC_wmi_sar_limit_cmd_row,
+			       WMITLV_GET_STRUCT_TLVLEN(wmi_sar_limit_cmd_row));
+		wmi_sar_rows_list->band_id = sar_rows_list->band_id;
+		wmi_sar_rows_list->chain_id = sar_rows_list->chain_id;
+		wmi_sar_rows_list->mod_id = sar_rows_list->mod_id;
+		wmi_sar_rows_list->limit_value = sar_rows_list->limit_value;
+		wmi_sar_rows_list->validity_bitmap =
+						sar_rows_list->validity_bitmap;
+		WMI_LOGD("row %d, band_id = %d, chain_id = %d, mod_id = %d, limit_value = %d, validity_bitmap = %d",
+			 i, wmi_sar_rows_list->band_id,
+			 wmi_sar_rows_list->chain_id,
+			 wmi_sar_rows_list->mod_id,
+			 wmi_sar_rows_list->limit_value,
+			 wmi_sar_rows_list->validity_bitmap);
+		sar_rows_list++;
+		wmi_sar_rows_list++;
+	}
+send_sar_limits:
+	qdf_status = wmi_unified_cmd_send(wmi_handle, buf, len,
+				      WMI_SAR_LIMITS_CMDID);
+
+	if (QDF_IS_STATUS_ERROR(qdf_status)) {
+		WMI_LOGE("Failed to send WMI_SAR_LIMITS_CMDID");
+		wmi_buf_free(buf);
+	}
+
+end:
+	return qdf_status;
+}
+
 /**
  * send_encrypt_decrypt_send_cmd() - send encrypt/decrypt cmd to fw
  * @wmi_handle: wmi handle
@@ -13023,6 +13105,7 @@ struct wmi_ops tlv_ops =  {
 	.send_fw_test_cmd = send_fw_test_cmd_tlv,
 	.send_encrypt_decrypt_send_cmd =
 				send_encrypt_decrypt_send_cmd_tlv,
+	.send_sar_limit_cmd = send_sar_limit_cmd_tlv,
 	.send_power_dbg_cmd = send_power_dbg_cmd_tlv,
 	.extract_service_ready_ext = extract_service_ready_ext_tlv,
 	.extract_hw_mode_cap_service_ready_ext =