/******************************************************************************
 *
 * Copyright(c) 2019 Realtek Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 *****************************************************************************/
#include "halrf_precomp.h"

const char * const _pw_lmt_regu_type_str[PW_LMT_MAX_REGULATION_NUM] = {
	/* elements not listed here will get NULL */
	[PW_LMT_REGU_WW13]		= "WW",
	[PW_LMT_REGU_ETSI]		= "ETSI",
	[PW_LMT_REGU_FCC]		= "FCC",
	[PW_LMT_REGU_MKK]		= "MKK",
	[PW_LMT_REGU_NA]		= "NONE",
	[PW_LMT_REGU_IC]		= "IC",
	[PW_LMT_REGU_KCC]		= "KCC",
	[PW_LMT_REGU_ACMA]		= "ACMA",
	[PW_LMT_REGU_NCC]		= "NCC",
	[PW_LMT_REGU_MEXICO]		= "MEXICO",
	[PW_LMT_REGU_CHILE]		= "CHILE",
	[PW_LMT_REGU_UKRAINE]		= "UKRAINE",
	[PW_LMT_REGU_CN]		= "CN",
	[PW_LMT_REGU_QATAR]		= "QATAR",
	[PW_LMT_REGU_UK]		= "UK",
	[PW_LMT_REGU_EXT_PWR]		= "EXT",
	[PW_LMT_REGU_NULL]		= NULL,
};

int halrf_get_predefined_pw_lmt_regu_type_from_str(const char *str)
{
	int i;

	for (i = 0; i < PW_LMT_MAX_REGULATION_NUM; i++)
		if (_pw_lmt_regu_type_str[i] && _os_strcmp(_pw_lmt_regu_type_str[i], str) == 0)
			return i;
	return -1;
}

const char * const *halrf_get_predefined_pw_lmt_regu_type_str_array(u8 *num)
{	
	if (num)
		*num = PW_LMT_REGU_PREDEF_NUM;
	return _pw_lmt_regu_type_str;
}

const enum halrf_pw_lmt_regulation_type _regulation_to_pw_lmt_regu_type[REGULATION_MAX] = {
	/* elements not listed here will get PW_LMT_REGU_WW13(0) */
	[REGULATION_WW]		= PW_LMT_REGU_WW13,
	[REGULATION_ETSI]	= PW_LMT_REGU_ETSI,
	[REGULATION_FCC]	= PW_LMT_REGU_FCC,
	[REGULATION_MKK]	= PW_LMT_REGU_MKK,
	[REGULATION_KCC]	= PW_LMT_REGU_KCC,
	[REGULATION_NCC]	= PW_LMT_REGU_NCC,
	[REGULATION_ACMA]	= PW_LMT_REGU_ACMA,
	[REGULATION_NA]		= PW_LMT_REGU_NA,
	[REGULATION_IC]		= PW_LMT_REGU_IC,
	[REGULATION_CHILE]	= PW_LMT_REGU_CHILE,
	[REGULATION_MEX]	= PW_LMT_REGU_MEXICO,
};

const enum halrf_pw_lmt_regulation_type _tpo_to_pw_lmt_regu_type[TPO_NA] = {
	/* elements not listed here will get PW_LMT_REGU_WW13(0) */
	[TPO_CHILE]		= PW_LMT_REGU_CHILE,
	[TPO_QATAR]		= PW_LMT_REGU_QATAR,
	[TPO_UKRAINE]		= PW_LMT_REGU_UKRAINE,
	[TPO_CN]		= PW_LMT_REGU_CN,
	/*[TPO_UK]		= PW_LMT_REGU_UK,*/
};

u8 halrf_get_regulation_info(struct rf_info *rf, u8 band)
{
	struct rtw_regulation_info rg_info = {0};
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	enum halrf_pw_lmt_regulation_type pw_lmt_type = PW_LMT_REGU_NULL;
	u8 reg = REGULATION_NA;
	u8 extra_regd_idx;
	const char *bstr =  NULL;

	halrf_query_regulation_info(rf, &rg_info);

	RF_DBG(rf, DBG_RF_INIT, "======>%s band=%d\n", __func__, band);

	RF_DBG(rf, DBG_RF_INIT, "domain_code=%d   regulation_2g=%d   regulation_5g=%d   chplan_ver=%d   country_ver=%d   rg_info.tpor=%d\n",
		rg_info.domain_code, rg_info.regulation_2g, rg_info.regulation_5g, rg_info.chplan_ver, rg_info.country_ver, rg_info.tpo);

	extra_regd_idx = halrf_get_power_limit_extra(rf);
	if (extra_regd_idx != 0xff)
		return extra_regd_idx;
	
#ifdef RTW_FLASH_98D
	if (pwr->regulation_idx != 0xff)
		return pwr->regulation_idx;
#else
	if (band == BAND_ON_24G) {
		reg = rg_info.regulation_2g;
		bstr = "2g";
	} else if (band == BAND_ON_5G) {
		reg = rg_info.regulation_5g;
		bstr = "5g";
	} else if (band == BAND_ON_6G) {
		/* TODO: 6G regulation */
		bstr = "6g";
	}

	/* TODO: consider _hal_file_regd_ext */

	if (rg_info.tpo != TPO_NA) {
		pw_lmt_type = tpo_to_pw_lmt_regu_type(rg_info.tpo);	
		RF_DBG(rf, DBG_RF_INIT, "%s extra pw_lmt_regu=%s(%d)\n",
			bstr, pw_lmt_regu_type_str(pw_lmt_type), pw_lmt_type);
	} else {
		if (reg == REGULATION_NA)
			return PW_LMT_REGU_NULL; /* return this to distinguish from PW_LMT_REGU_NA done by NONE option from TXPWR_LMT.txt */
		pw_lmt_type = regulation_to_pw_lmt_regu_type(reg);
	}

	if (pwr->regulation[band][pw_lmt_type] != true) {
		RF_DBG(rf, DBG_RF_INIT, "%s pw_lmt_regu=%s(%d) is not exist return WW13 !!!\n",
			bstr, pw_lmt_regu_type_str(pw_lmt_type), pw_lmt_type);
		return PW_LMT_REGU_WW13;
	}
#endif
	
	if (rf->phl_com->drv_mode == RTW_DRV_MODE_MP)
		return regulation_to_pw_lmt_regu_type(pwr->mp_regulation);
	
	return pw_lmt_type;
}

const char *halrf_get_pw_lmt_regu_type_str(struct rf_info *rf, u8 band)
{
	u8 reg = halrf_get_regulation_info(rf, band);

	return pw_lmt_regu_type_str(reg);
}

const char *halrf_get_pw_lmt_regu_type_str_extra(struct rf_info *rf, u8 band)
{
	struct rtw_para_pwrlmt_info_t *pwrlmt_info = NULL;
	u8 reg = halrf_get_regulation_info(rf, band);

	pwrlmt_info = &rf->phl_com->phy_sw_cap[HW_PHY_0].rf_txpwrlmt_info;

	if (reg >= PW_LMT_REGU_PREDEF_NUM)
		return pwrlmt_info->ext_regd_name[reg];

	return pw_lmt_regu_type_str(reg);
}

void halrf_power_by_rate_store_to_array(struct rf_info *rf,
			u32 band, u32 tx_num, u32 rate_id, u32 data)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	
	RF_DBG(rf, DBG_RF_INIT, "======>%s band=%d tx_num=%d rate_id=%d data=0x%x\n",
				__func__, band, tx_num, rate_id, data);

	if (band != (u32)BAND_ON_24G && band != (u32)BAND_ON_5G && band != (u32)BAND_ON_6G)
		RF_DBG(rf, DBG_RF_INIT, "Invalid Band %d\n", band);

	if (tx_num > 4 && tx_num != 15)
		RF_DBG(rf, DBG_RF_INIT, "Invalid TxNum %d\n", tx_num);

	if (band == 0 && tx_num == 0 && rate_id == 0) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_CCK1] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_CCK2] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_CCK5_5] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_CCK11] = (s8)((data & 0xff000000) >> 24);
	} else if (tx_num == 0 && rate_id == 1) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_OFDM6] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_OFDM9] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_OFDM12] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_OFDM18] = (s8)((data & 0xff000000) >> 24);
	} else if (tx_num == 0 && rate_id == 2) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_OFDM24] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_OFDM36] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_OFDM48] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_OFDM54] = (s8)((data & 0xff000000) >> 24);
	} else if (tx_num == 0 && rate_id == 3) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS0] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS1] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS2] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS3] = (s8)((data & 0xff000000) >> 24);

		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS1_MCS0] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS1_MCS1] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS1_MCS2] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS1_MCS3] = (s8)((data & 0xff000000) >> 24);

		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS0] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS1] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS2] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS3] = (s8)((data & 0xff000000) >> 24);
	} else if (tx_num == 0 && rate_id == 4) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS4] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS5] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS6] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS7] = (s8)((data & 0xff000000) >> 24);

		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS1_MCS4] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS1_MCS5] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS1_MCS6] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS1_MCS7] = (s8)((data & 0xff000000) >> 24);

		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS4] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS5] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS6] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS7] = (s8)((data & 0xff000000) >> 24);
	} else if (tx_num == 0 && rate_id == 5) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS1_MCS8] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS1_MCS9] = (s8)((data & 0xff00) >> 8);

		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS8] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS9] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS10] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS1_MCS11] = (s8)((data & 0xff000000) >> 24);
	} else if (tx_num == 0 && rate_id == 6) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HEDCM_NSS1_MCS0] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HEDCM_NSS1_MCS1] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HEDCM_NSS1_MCS3] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HEDCM_NSS1_MCS4] = (s8)((data & 0xff000000) >> 24);
	} else if (band == 0 && tx_num == 15 && rate_id == 7) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_OFFSET] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HT_OFFSET] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_OFDM_OFFSET] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_CCK_OFFSET] = (s8)((data & 0xff000000) >> 24);
	} else if (band == 0 && tx_num == 15 && rate_id == 8) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HEDCM_OFFSET] = (s8)((data & 0xff000000) >> 24);
	} else if (tx_num == 1 && rate_id == 3) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS8] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS9] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS10] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS11] = (s8)((data & 0xff000000) >> 24);

		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS2_MCS0] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS2_MCS1] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS2_MCS2] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS2_MCS3] = (s8)((data & 0xff000000) >> 24);

		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS0] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS1] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS2] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS3] = (s8)((data & 0xff000000) >> 24);
	} else if (tx_num == 1 && rate_id == 4) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS12] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS13] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS14] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_MCS15] = (s8)((data & 0xff000000) >> 24);

		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS2_MCS4] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS2_MCS5] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS2_MCS6] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS2_MCS7] = (s8)((data & 0xff000000) >> 24);

		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS4] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS5] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS6] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS7] = (s8)((data & 0xff000000) >> 24);
	} else if (tx_num == 1 && rate_id == 5) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS2_MCS8] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_NSS2_MCS9] = (s8)((data & 0xff00) >> 8);

		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS8] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS9] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS10] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HE_NSS2_MCS11] = (s8)((data & 0xff000000) >> 24);
	} else if (tx_num == 1 && rate_id == 6) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HEDCM_NSS2_MCS0] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HEDCM_NSS2_MCS1] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HEDCM_NSS2_MCS3] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HEDCM_NSS2_MCS4] = (s8)((data & 0xff000000) >> 24);
	} else if (band == 1 && tx_num == 15 && rate_id == 9) {
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HEDCM_OFFSET] = (s8)(data & 0xff);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_VHT_OFFSET] = (s8)((data & 0xff00) >> 8);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_HT_OFFSET] = (s8)((data & 0xff0000) >> 16);
		pwr->tx_pwr_by_rate[band][HALRF_DATA_RATE_OFDM_OFFSET] = (s8)((data & 0xff000000) >> 24);
	}
}

u8 halrf_get_ch_idx_to_limit_array(struct rf_info *rf, u8 channel)
{
	u8	channelIndex;

	if (channel >= 1 && channel <= 14)
		channelIndex = channel - 1;
	else if (channel >= 36 && channel <= 64)
		channelIndex = (channel - 36) / 2;
	else if (channel >= 100 && channel <= 144)
		channelIndex = ((channel - 100) / 2) + 15;
	else if (channel >= 149 && channel <= 177)
		channelIndex = ((channel - 149) / 2) + 38;
	else
		channelIndex = 0;

	return channelIndex;
}

u8 halrf_get_limit_ch_idx_to_ch_idx(struct rf_info *rf, u8 band, u8 channel)
{
	u8	channelIndex;

	if (band == PW_LMT_BAND_2_4G) {
		if (channel >= 0 && channel <= 13)
			channelIndex = channel + 1;
		else
			channelIndex = 0;
	} else {
		if (channel >= 0 && channel <= 14)
			channelIndex = channel * 2 + 36;
		else if (channel >= 15 && channel <= 37)
			channelIndex = (channel - 15) * 2 + 100;
		else if (channel >= 38 && channel <= 52)
			channelIndex = (channel - 38) * 2 + 149;
		else
			channelIndex = 0;
	}

	return channelIndex;
}

u16 halrf_hw_rate_to_pwr_by_rate(struct rf_info *rf, u16 rate)
{
	u16 ret_rate = HALRF_DATA_RATE_OFDM6;

	switch(rate) {
	case RTW_DATA_RATE_CCK1:	ret_rate = HALRF_DATA_RATE_CCK1; break;
	case RTW_DATA_RATE_CCK2:	ret_rate = HALRF_DATA_RATE_CCK2; break;
	case RTW_DATA_RATE_CCK5_5:	ret_rate = HALRF_DATA_RATE_CCK5_5; break;
	case RTW_DATA_RATE_CCK11:	ret_rate = HALRF_DATA_RATE_CCK11; break;
	case RTW_DATA_RATE_OFDM6:	ret_rate = HALRF_DATA_RATE_OFDM6; break;
	case RTW_DATA_RATE_OFDM9:	ret_rate = HALRF_DATA_RATE_OFDM9; break;
	case RTW_DATA_RATE_OFDM12:	ret_rate = HALRF_DATA_RATE_OFDM12; break;
	case RTW_DATA_RATE_OFDM18:	ret_rate = HALRF_DATA_RATE_OFDM18; break;
	case RTW_DATA_RATE_OFDM24:	ret_rate = HALRF_DATA_RATE_OFDM24; break;
	case RTW_DATA_RATE_OFDM36:	ret_rate = HALRF_DATA_RATE_OFDM36; break;
	case RTW_DATA_RATE_OFDM48:	ret_rate = HALRF_DATA_RATE_OFDM48; break;
	case RTW_DATA_RATE_OFDM54:	ret_rate = HALRF_DATA_RATE_OFDM54; break;

	case RTW_DATA_RATE_MCS0:	ret_rate = HALRF_DATA_RATE_MCS0; break;
	case RTW_DATA_RATE_MCS1:	ret_rate = HALRF_DATA_RATE_MCS1; break;
	case RTW_DATA_RATE_MCS2:	ret_rate = HALRF_DATA_RATE_MCS2; break;
	case RTW_DATA_RATE_MCS3:	ret_rate = HALRF_DATA_RATE_MCS3; break;
	case RTW_DATA_RATE_MCS4:	ret_rate = HALRF_DATA_RATE_MCS4; break;
	case RTW_DATA_RATE_MCS5:	ret_rate = HALRF_DATA_RATE_MCS5; break;
	case RTW_DATA_RATE_MCS6:	ret_rate = HALRF_DATA_RATE_MCS6; break;
	case RTW_DATA_RATE_MCS7:	ret_rate = HALRF_DATA_RATE_MCS7; break;
	case RTW_DATA_RATE_MCS8:	ret_rate = HALRF_DATA_RATE_MCS8; break;
	case RTW_DATA_RATE_MCS9:	ret_rate = HALRF_DATA_RATE_MCS9; break;
	case RTW_DATA_RATE_MCS10:	ret_rate = HALRF_DATA_RATE_MCS10; break;
	case RTW_DATA_RATE_MCS11:	ret_rate = HALRF_DATA_RATE_MCS11; break;
	case RTW_DATA_RATE_MCS12:	ret_rate = HALRF_DATA_RATE_MCS12; break;
	case RTW_DATA_RATE_MCS13:	ret_rate = HALRF_DATA_RATE_MCS13; break;
	case RTW_DATA_RATE_MCS14:	ret_rate = HALRF_DATA_RATE_MCS14; break;
	case RTW_DATA_RATE_MCS15:	ret_rate = HALRF_DATA_RATE_MCS15; break;
	case RTW_DATA_RATE_MCS16:	ret_rate = HALRF_DATA_RATE_MCS16; break;
	case RTW_DATA_RATE_MCS17:	ret_rate = HALRF_DATA_RATE_MCS17; break;
	case RTW_DATA_RATE_MCS18:	ret_rate = HALRF_DATA_RATE_MCS18; break;
	case RTW_DATA_RATE_MCS19:	ret_rate = HALRF_DATA_RATE_MCS19; break;
	case RTW_DATA_RATE_MCS20:	ret_rate = HALRF_DATA_RATE_MCS20; break;
	case RTW_DATA_RATE_MCS21:	ret_rate = HALRF_DATA_RATE_MCS21; break;
	case RTW_DATA_RATE_MCS22:	ret_rate = HALRF_DATA_RATE_MCS22; break;
	case RTW_DATA_RATE_MCS23:	ret_rate = HALRF_DATA_RATE_MCS23; break;
	case RTW_DATA_RATE_MCS24:	ret_rate = HALRF_DATA_RATE_MCS24; break;
	case RTW_DATA_RATE_MCS25:	ret_rate = HALRF_DATA_RATE_MCS25; break;
	case RTW_DATA_RATE_MCS26:	ret_rate = HALRF_DATA_RATE_MCS26; break;
	case RTW_DATA_RATE_MCS27:	ret_rate = HALRF_DATA_RATE_MCS27; break;
	case RTW_DATA_RATE_MCS28:	ret_rate = HALRF_DATA_RATE_MCS28; break;
	case RTW_DATA_RATE_MCS29:	ret_rate = HALRF_DATA_RATE_MCS29; break;
	case RTW_DATA_RATE_MCS30:	ret_rate = HALRF_DATA_RATE_MCS30; break;
	case RTW_DATA_RATE_MCS31:	ret_rate = HALRF_DATA_RATE_MCS31; break;

	case RTW_DATA_RATE_VHT_NSS1_MCS0:	ret_rate = HALRF_DATA_RATE_VHT_NSS1_MCS0; break;
	case RTW_DATA_RATE_VHT_NSS1_MCS1:	ret_rate = HALRF_DATA_RATE_VHT_NSS1_MCS1; break;
	case RTW_DATA_RATE_VHT_NSS1_MCS2:	ret_rate = HALRF_DATA_RATE_VHT_NSS1_MCS2; break;
	case RTW_DATA_RATE_VHT_NSS1_MCS3:	ret_rate = HALRF_DATA_RATE_VHT_NSS1_MCS3; break;
	case RTW_DATA_RATE_VHT_NSS1_MCS4:	ret_rate = HALRF_DATA_RATE_VHT_NSS1_MCS4; break;
	case RTW_DATA_RATE_VHT_NSS1_MCS5:	ret_rate = HALRF_DATA_RATE_VHT_NSS1_MCS5; break;
	case RTW_DATA_RATE_VHT_NSS1_MCS6:	ret_rate = HALRF_DATA_RATE_VHT_NSS1_MCS6; break;
	case RTW_DATA_RATE_VHT_NSS1_MCS7:	ret_rate = HALRF_DATA_RATE_VHT_NSS1_MCS7; break;
	case RTW_DATA_RATE_VHT_NSS1_MCS8:	ret_rate = HALRF_DATA_RATE_VHT_NSS1_MCS8; break;
	case RTW_DATA_RATE_VHT_NSS1_MCS9:	ret_rate = HALRF_DATA_RATE_VHT_NSS1_MCS9; break;	
	case RTW_DATA_RATE_VHT_NSS2_MCS0:	ret_rate = HALRF_DATA_RATE_VHT_NSS2_MCS0; break;
	case RTW_DATA_RATE_VHT_NSS2_MCS1:	ret_rate = HALRF_DATA_RATE_VHT_NSS2_MCS1; break;
	case RTW_DATA_RATE_VHT_NSS2_MCS2:	ret_rate = HALRF_DATA_RATE_VHT_NSS2_MCS2; break;
	case RTW_DATA_RATE_VHT_NSS2_MCS3:	ret_rate = HALRF_DATA_RATE_VHT_NSS2_MCS3; break;
	case RTW_DATA_RATE_VHT_NSS2_MCS4:	ret_rate = HALRF_DATA_RATE_VHT_NSS2_MCS4; break;
	case RTW_DATA_RATE_VHT_NSS2_MCS5:	ret_rate = HALRF_DATA_RATE_VHT_NSS2_MCS5; break;
	case RTW_DATA_RATE_VHT_NSS2_MCS6:	ret_rate = HALRF_DATA_RATE_VHT_NSS2_MCS6; break;
	case RTW_DATA_RATE_VHT_NSS2_MCS7:	ret_rate = HALRF_DATA_RATE_VHT_NSS2_MCS7; break;
	case RTW_DATA_RATE_VHT_NSS2_MCS8:	ret_rate = HALRF_DATA_RATE_VHT_NSS2_MCS8; break;
	case RTW_DATA_RATE_VHT_NSS2_MCS9:	ret_rate = HALRF_DATA_RATE_VHT_NSS2_MCS9; break;	
	case RTW_DATA_RATE_VHT_NSS3_MCS0:	ret_rate = HALRF_DATA_RATE_VHT_NSS3_MCS0; break;
	case RTW_DATA_RATE_VHT_NSS3_MCS1:	ret_rate = HALRF_DATA_RATE_VHT_NSS3_MCS1; break;
	case RTW_DATA_RATE_VHT_NSS3_MCS2:	ret_rate = HALRF_DATA_RATE_VHT_NSS3_MCS2; break;
	case RTW_DATA_RATE_VHT_NSS3_MCS3:	ret_rate = HALRF_DATA_RATE_VHT_NSS3_MCS3; break;
	case RTW_DATA_RATE_VHT_NSS3_MCS4:	ret_rate = HALRF_DATA_RATE_VHT_NSS3_MCS4; break;
	case RTW_DATA_RATE_VHT_NSS3_MCS5:	ret_rate = HALRF_DATA_RATE_VHT_NSS3_MCS5; break;
	case RTW_DATA_RATE_VHT_NSS3_MCS6:	ret_rate = HALRF_DATA_RATE_VHT_NSS3_MCS6; break;
	case RTW_DATA_RATE_VHT_NSS3_MCS7:	ret_rate = HALRF_DATA_RATE_VHT_NSS3_MCS7; break;
	case RTW_DATA_RATE_VHT_NSS3_MCS8:	ret_rate = HALRF_DATA_RATE_VHT_NSS3_MCS8; break;
	case RTW_DATA_RATE_VHT_NSS3_MCS9:	ret_rate = HALRF_DATA_RATE_VHT_NSS3_MCS9; break;
	case RTW_DATA_RATE_VHT_NSS4_MCS0:	ret_rate = HALRF_DATA_RATE_VHT_NSS4_MCS0; break;
	case RTW_DATA_RATE_VHT_NSS4_MCS1:	ret_rate = HALRF_DATA_RATE_VHT_NSS4_MCS1; break;
	case RTW_DATA_RATE_VHT_NSS4_MCS2:	ret_rate = HALRF_DATA_RATE_VHT_NSS4_MCS2; break;
	case RTW_DATA_RATE_VHT_NSS4_MCS3:	ret_rate = HALRF_DATA_RATE_VHT_NSS4_MCS3; break;
	case RTW_DATA_RATE_VHT_NSS4_MCS4:	ret_rate = HALRF_DATA_RATE_VHT_NSS4_MCS4; break;
	case RTW_DATA_RATE_VHT_NSS4_MCS5:	ret_rate = HALRF_DATA_RATE_VHT_NSS4_MCS5; break;
	case RTW_DATA_RATE_VHT_NSS4_MCS6:	ret_rate = HALRF_DATA_RATE_VHT_NSS4_MCS6; break;
	case RTW_DATA_RATE_VHT_NSS4_MCS7:	ret_rate = HALRF_DATA_RATE_VHT_NSS4_MCS7; break;
	case RTW_DATA_RATE_VHT_NSS4_MCS8:	ret_rate = HALRF_DATA_RATE_VHT_NSS4_MCS8; break;
	case RTW_DATA_RATE_VHT_NSS4_MCS9:	ret_rate = HALRF_DATA_RATE_VHT_NSS4_MCS9; break;

	case RTW_DATA_RATE_HE_NSS1_MCS0:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS0; break;
	case RTW_DATA_RATE_HE_NSS1_MCS1:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS1; break;
	case RTW_DATA_RATE_HE_NSS1_MCS2:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS2; break;
	case RTW_DATA_RATE_HE_NSS1_MCS3:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS3; break;
	case RTW_DATA_RATE_HE_NSS1_MCS4:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS4; break;
	case RTW_DATA_RATE_HE_NSS1_MCS5:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS5; break;
	case RTW_DATA_RATE_HE_NSS1_MCS6:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS6; break;
	case RTW_DATA_RATE_HE_NSS1_MCS7:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS7; break;
	case RTW_DATA_RATE_HE_NSS1_MCS8:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS8; break;
	case RTW_DATA_RATE_HE_NSS1_MCS9:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS9; break; 
	case RTW_DATA_RATE_HE_NSS1_MCS10:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS10; break;
	case RTW_DATA_RATE_HE_NSS1_MCS11:	ret_rate = HALRF_DATA_RATE_HE_NSS1_MCS11; break; 
	case RTW_DATA_RATE_HE_NSS2_MCS0:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS0; break;
	case RTW_DATA_RATE_HE_NSS2_MCS1:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS1; break;
	case RTW_DATA_RATE_HE_NSS2_MCS2:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS2; break;
	case RTW_DATA_RATE_HE_NSS2_MCS3:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS3; break;
	case RTW_DATA_RATE_HE_NSS2_MCS4:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS4; break;
	case RTW_DATA_RATE_HE_NSS2_MCS5:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS5; break;
	case RTW_DATA_RATE_HE_NSS2_MCS6:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS6; break;
	case RTW_DATA_RATE_HE_NSS2_MCS7:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS7; break;
	case RTW_DATA_RATE_HE_NSS2_MCS8:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS8; break;
	case RTW_DATA_RATE_HE_NSS2_MCS9:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS9; break;
	case RTW_DATA_RATE_HE_NSS2_MCS10:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS10; break;
	case RTW_DATA_RATE_HE_NSS2_MCS11:	ret_rate = HALRF_DATA_RATE_HE_NSS2_MCS11; break; 
	case RTW_DATA_RATE_HE_NSS3_MCS0:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS0; break;
	case RTW_DATA_RATE_HE_NSS3_MCS1:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS1; break;
	case RTW_DATA_RATE_HE_NSS3_MCS2:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS2; break;
	case RTW_DATA_RATE_HE_NSS3_MCS3:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS3; break;
	case RTW_DATA_RATE_HE_NSS3_MCS4:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS4; break;
	case RTW_DATA_RATE_HE_NSS3_MCS5:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS5; break;
	case RTW_DATA_RATE_HE_NSS3_MCS6:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS6; break;
	case RTW_DATA_RATE_HE_NSS3_MCS7:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS7; break;
	case RTW_DATA_RATE_HE_NSS3_MCS8:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS8; break;
	case RTW_DATA_RATE_HE_NSS3_MCS9:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS9; break;
	case RTW_DATA_RATE_HE_NSS3_MCS10:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS10; break;
	case RTW_DATA_RATE_HE_NSS3_MCS11:	ret_rate = HALRF_DATA_RATE_HE_NSS3_MCS11; break; 
	case RTW_DATA_RATE_HE_NSS4_MCS0:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS0; break;
	case RTW_DATA_RATE_HE_NSS4_MCS1:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS1; break;
	case RTW_DATA_RATE_HE_NSS4_MCS2:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS2; break;
	case RTW_DATA_RATE_HE_NSS4_MCS3:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS3; break;
	case RTW_DATA_RATE_HE_NSS4_MCS4:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS4; break;
	case RTW_DATA_RATE_HE_NSS4_MCS5:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS5; break;
	case RTW_DATA_RATE_HE_NSS4_MCS6:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS6; break;
	case RTW_DATA_RATE_HE_NSS4_MCS7:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS7; break;
	case RTW_DATA_RATE_HE_NSS4_MCS8:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS8; break;
	case RTW_DATA_RATE_HE_NSS4_MCS9:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS9; break;
	case RTW_DATA_RATE_HE_NSS4_MCS10:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS10; break;
	case RTW_DATA_RATE_HE_NSS4_MCS11:	ret_rate = HALRF_DATA_RATE_HE_NSS4_MCS11; break; 

	}

	return ret_rate;
}

u16 halrf_get_dcm_offset_pwr_by_rate(struct rf_info *rf, u16 rate,
						u8 dcm, u8 offset)
{
	u16 rate_tmp = 0;

	if (dcm == 0)
		rate_tmp = halrf_hw_rate_to_pwr_by_rate(rf, rate);
	else if (dcm == 1) {
		if (rate == RTW_DATA_RATE_HE_NSS1_MCS0)
			rate_tmp = HALRF_DATA_RATE_HEDCM_NSS1_MCS0;
		else if (rate == RTW_DATA_RATE_HE_NSS1_MCS1)
			rate_tmp = HALRF_DATA_RATE_HEDCM_NSS1_MCS1;
		else if (rate == RTW_DATA_RATE_HE_NSS1_MCS3)
			rate_tmp = HALRF_DATA_RATE_HEDCM_NSS1_MCS3;
		else if (rate == RTW_DATA_RATE_HE_NSS1_MCS4)
			rate_tmp = HALRF_DATA_RATE_HEDCM_NSS1_MCS4;
		else if (rate == RTW_DATA_RATE_HE_NSS2_MCS0)
			rate_tmp = HALRF_DATA_RATE_HEDCM_NSS2_MCS0;
		else if (rate == RTW_DATA_RATE_HE_NSS2_MCS1)
			rate_tmp = HALRF_DATA_RATE_HEDCM_NSS2_MCS1;
		else if (rate == RTW_DATA_RATE_HE_NSS2_MCS3)
			rate_tmp = HALRF_DATA_RATE_HEDCM_NSS2_MCS3;
		else if (rate == RTW_DATA_RATE_HE_NSS2_MCS4)
			rate_tmp = HALRF_DATA_RATE_HEDCM_NSS2_MCS4;
	}

	if (offset == 1) {
		/*if (dcm == 1)*/
		if (rate >= RTW_DATA_RATE_HE_NSS1_MCS0 && rate <= RTW_DATA_RATE_HE_NSS4_MCS11)
			rate_tmp = HALRF_DATA_RATE_HEDCM_OFFSET;
		if (rate >= RTW_DATA_RATE_VHT_NSS1_MCS0 && rate <= RTW_DATA_RATE_VHT_NSS4_MCS9)
			rate_tmp = HALRF_DATA_RATE_VHT_OFFSET;
		if (rate >= RTW_DATA_RATE_MCS0 && rate <= RTW_DATA_RATE_MCS31)
			rate_tmp = HALRF_DATA_RATE_HT_OFFSET;
		if (rate >= RTW_DATA_RATE_OFDM6 && rate <= RTW_DATA_RATE_OFDM54)
			rate_tmp = HALRF_DATA_RATE_OFDM_OFFSET;
		if (rate >= RTW_DATA_RATE_CCK1 && rate <= RTW_DATA_RATE_CCK11)
			rate_tmp = HALRF_DATA_RATE_CCK_OFFSET;
		
	}

	return rate_tmp;

}

u8 halrf_hw_rate_to_limit_rate_tx_num(struct rf_info *rf, u16 rate)
{
	if (rate >= RTW_DATA_RATE_CCK1 && rate <= RTW_DATA_RATE_CCK11)
		return PW_LMT_RS_CCK;
	else if (rate >= RTW_DATA_RATE_OFDM6 && rate <= RTW_DATA_RATE_OFDM54)
		return PW_LMT_RS_OFDM;
	else if (rate >= RTW_DATA_RATE_MCS0 && rate <= RTW_DATA_RATE_MCS7)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_MCS8 && rate <= RTW_DATA_RATE_MCS15)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_MCS16 && rate <= RTW_DATA_RATE_MCS23)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_MCS24 && rate <= RTW_DATA_RATE_MCS31)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_VHT_NSS1_MCS0 && rate <= RTW_DATA_RATE_VHT_NSS1_MCS9)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_VHT_NSS2_MCS0 && rate <= RTW_DATA_RATE_VHT_NSS2_MCS9)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_VHT_NSS3_MCS0 && rate <= RTW_DATA_RATE_VHT_NSS3_MCS9)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_VHT_NSS4_MCS0 && rate <= RTW_DATA_RATE_VHT_NSS4_MCS9)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_HE_NSS1_MCS0 && rate <= RTW_DATA_RATE_HE_NSS1_MCS11)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_HE_NSS2_MCS0 && rate <= RTW_DATA_RATE_HE_NSS2_MCS11)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_HE_NSS3_MCS0 && rate <= RTW_DATA_RATE_HE_NSS3_MCS11)
		return PW_LMT_RS_HE;
	else if (rate >= RTW_DATA_RATE_HE_NSS4_MCS0 && rate <= RTW_DATA_RATE_HE_NSS4_MCS11)
		return PW_LMT_RS_HE;
	else
		return PW_LMT_RS_HE;

}

void halrf_power_limit_store_to_array(struct rf_info *rf,
			u8 regulation, u8 band, u8 bandwidth, u8 rate,
			u8 tx_num, u8 beamforming, u8 chnl, s8 val)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	u8 ch = halrf_get_ch_idx_to_limit_array(rf, chnl);

	RF_DBG(rf, DBG_RF_INIT, "======>%s regulation=%d band=%d bandwidth=%d rate=%d\n",
		__func__, regulation, band, bandwidth, rate);

	RF_DBG(rf, DBG_RF_INIT, "======>%s tx_num=%d beamforming=%d chnl=%d ch=%d val=%d\n",
		__func__, tx_num, beamforming, chnl, ch, val);

	if (band == PW_LMT_BAND_2_4G) {
		pwr->tx_pwr_limit_2g[regulation][bandwidth][rate][beamforming][ch][tx_num] = val;		
		RF_DBG(rf, DBG_RF_POWER, "pwr_limit(%d) = pwr->tx_pwr_limit_2g[%d][%d][%d][%d][%d][%d]\n",
			val, regulation, bandwidth, rate, beamforming, ch, tx_num);
	} else if (band == PW_LMT_BAND_5G) {
		pwr->tx_pwr_limit_5g[regulation][bandwidth][rate][beamforming][ch][tx_num] = val;
		RF_DBG(rf, DBG_RF_POWER, "pwr_limit(%d) = pwr->tx_pwr_limit_5g[%d][%d][%d][%d][%d][%d]\n",
			val, regulation, bandwidth, rate, beamforming, ch, tx_num);
	}
}

void halrf_power_limit_set_worldwide(struct rf_info *rf)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	u32 reg, bw, rate, bf, ch, tx_num;
	s8 tmp;

	RF_DBG(rf, DBG_RF_INIT, "======>%s\n", __func__);

	for (tx_num = 0; tx_num < MAX_HALRF_PATH; tx_num++) {
		for (ch = 0; ch < PW_LMT_MAX_CHANNEL_NUMBER_2G; ch++) {
			for (bf = 0; bf < PW_LMT_MAX_BF_NUM; bf++) {
				for (rate = 0; rate < PW_LMT_MAX_RS_NUM; rate++) {
					for (bw = 0; bw < PW_LMT_MAX_2G_BANDWITH_NUM; bw++) {
						tmp = 127;
						for (reg = 0; reg < PW_LMT_MAX_REGULATION_NUM; reg++) {
							RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_2g[%d][%d][%d][%d][%d][%d]=   %d\n",
								reg, bw, rate, bf, ch, tx_num ,pwr->tx_pwr_limit_2g[reg][bw][rate][bf][ch][tx_num]);
							if (tmp > pwr->tx_pwr_limit_2g[reg][bw][rate][bf][ch][tx_num] &&
								pwr->tx_pwr_limit_2g[reg][bw][rate][bf][ch][tx_num] > 0) {
								tmp = pwr->tx_pwr_limit_2g[reg][bw][rate][bf][ch][tx_num];
							}
						}
						if (tmp == 127)
							tmp = 0;
						pwr->tx_pwr_limit_2g[PW_LMT_REGU_WW13][bw][rate][bf][ch][tx_num] = tmp;

						RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_2g[%d][%d][%d][%d][%d][%d]=   %d\n",
								PW_LMT_REGU_WW13, bw, rate, bf, ch, tx_num ,pwr->tx_pwr_limit_2g[PW_LMT_REGU_WW13][bw][rate][bf][ch][tx_num]);
					}
				}
			}
		}
	}

	for (tx_num = 0; tx_num < MAX_HALRF_PATH; tx_num++) {
		for (ch = 0; ch < PW_LMT_MAX_CHANNEL_NUMBER_5G; ch++) {
			for (bf = 0; bf < PW_LMT_MAX_BF_NUM; bf++) {
				for (rate = 0; rate < PW_LMT_MAX_RS_NUM; rate++) {
					for (bw = 0; bw < PW_LMT_MAX_BANDWIDTH_NUM; bw++) {
						tmp = 127;
						for (reg = 0; reg < PW_LMT_MAX_REGULATION_NUM; reg++) {
							RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_5g[%d][%d][%d][%d][%d][%d]=   %d\n",
								reg, bw, rate, bf, ch, tx_num, pwr->tx_pwr_limit_5g[reg][bw][rate][bf][ch][tx_num]);
							if (tmp > pwr->tx_pwr_limit_5g[reg][bw][rate][bf][ch][tx_num] &&
								pwr->tx_pwr_limit_5g[reg][bw][rate][bf][ch][tx_num] > 0) {
								tmp = pwr->tx_pwr_limit_5g[reg][bw][rate][bf][ch][tx_num];
							}
						}
						if (tmp == 127)
							tmp = 0;
						pwr->tx_pwr_limit_5g[PW_LMT_REGU_WW13][bw][rate][bf][ch][tx_num] = tmp;

						RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_5g[%d][%d][%d][%d][%d][%d]=   %d\n",
								PW_LMT_REGU_WW13, bw, rate, bf, ch, tx_num, pwr->tx_pwr_limit_5g[PW_LMT_REGU_WW13][bw][rate][bf][ch][tx_num]);
					}
				}
			}
		}
	}

	RF_DBG(rf, DBG_RF_INIT, "<======%s finish!!!\n", __func__);

}

void halrf_power_limit_ru_store_to_array(struct rf_info *rf,
			u8 band, u8 bandwidth, u8 tx_num, u8 rate,
			u8 regulation, u8 chnl, s8 val)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	u8 ch = halrf_get_ch_idx_to_limit_array(rf, chnl);

	RF_DBG(rf, DBG_RF_INIT, "======>%s regulation=%d band=%d bandwidth=%d rate=%d\n",
		__func__, regulation, band, bandwidth, rate);

	RF_DBG(rf, DBG_RF_INIT, "======>%s tx_num=%d chnl=%d ch=%d val=%d\n",
		__func__, tx_num, chnl, ch, val);

	if (band == PW_LMT_BAND_2_4G) {
		pwr->tx_pwr_limit_ru_2g[regulation][bandwidth][rate][ch][tx_num] = val;		
		RF_DBG(rf, DBG_RF_POWER, "pwr_limit_ru(%d) = pwr->tx_pwr_limit_ru_2g[%d][%d][%d][%d][%d]\n",
			val, regulation, bandwidth, rate, ch, tx_num);
	} else if (band == PW_LMT_BAND_5G) {
		pwr->tx_pwr_limit_ru_5g[regulation][bandwidth][rate][ch][tx_num] = val;
		RF_DBG(rf, DBG_RF_POWER, "pwr_limit_ru(%d) = pwr->tx_pwr_limit_ru_5g[%d][%d][%d][%d][%d]\n",
			val, regulation, bandwidth, rate, ch, tx_num);
	}
}

void halrf_power_limit_ru_set_worldwide(struct rf_info *rf)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	u32 reg, bw, rate, ch, tx_num;
	s8 tmp;

	RF_DBG(rf, DBG_RF_INIT, "======>%s\n", __func__);

	for (tx_num = 0; tx_num < MAX_HALRF_PATH; tx_num++) {
		for (ch = 0; ch < PW_LMT_MAX_CHANNEL_NUMBER_2G; ch++) {
			for (rate = 0; rate < PW_LMT_MAX_RS_NUM; rate++) {
				for (bw = 0; bw < PW_LMT_RU_BW_NULL; bw++) {
					tmp = 127;
					for (reg = 0; reg < PW_LMT_MAX_REGULATION_NUM; reg++) {
						RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_ru_2g[%d][%d][%d][%d][%d]=   %d\n",
							reg, bw, rate, ch, tx_num, pwr->tx_pwr_limit_ru_2g[reg][bw][rate][ch][tx_num]);

						if (tmp > pwr->tx_pwr_limit_ru_2g[reg][bw][rate][ch][tx_num] &&
							pwr->tx_pwr_limit_ru_2g[reg][bw][rate][ch][tx_num] > 0) {
							tmp = pwr->tx_pwr_limit_ru_2g[reg][bw][rate][ch][tx_num];
						}
					}
					if (tmp == 127)
						tmp = 0;
					pwr->tx_pwr_limit_ru_2g[PW_LMT_REGU_WW13][bw][rate][ch][tx_num] = tmp;

					RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_ru_2g[%d][%d][%d][%d][%d]=   %d\n",
							PW_LMT_REGU_WW13, bw, rate, ch, tx_num, pwr->tx_pwr_limit_ru_2g[PW_LMT_REGU_WW13][bw][rate][ch][tx_num]);

				}
			}
		}
	}

	for (tx_num = 0; tx_num < MAX_HALRF_PATH; tx_num++) {
		for (ch = 0; ch < PW_LMT_MAX_CHANNEL_NUMBER_5G; ch++) {
			for (rate = 0; rate < PW_LMT_MAX_RS_NUM; rate++) {
				for (bw = 0; bw < PW_LMT_RU_BW_NULL; bw++) {
					tmp = 127;
					for (reg = 0; reg < PW_LMT_MAX_REGULATION_NUM; reg++) {
						RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_ru_5g[%d][%d][%d][%d][%d]=   %d\n",
							reg, bw, rate, ch, tx_num, pwr->tx_pwr_limit_ru_5g[reg][bw][rate][ch][tx_num]);

						if (tmp > pwr->tx_pwr_limit_ru_5g[reg][bw][rate][ch][tx_num] &&
							pwr->tx_pwr_limit_ru_5g[reg][bw][rate][ch][tx_num] > 0) {
							tmp = pwr->tx_pwr_limit_ru_5g[reg][bw][rate][ch][tx_num];
						}
					}
					if (tmp == 127)
						tmp = 0;
					pwr->tx_pwr_limit_ru_5g[PW_LMT_REGU_WW13][bw][rate][ch][tx_num] = tmp;

					RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_ru_5g[%d][%d][%d][%d][%d]=   %d\n",
							PW_LMT_REGU_WW13, bw, rate, ch, tx_num, pwr->tx_pwr_limit_ru_5g[PW_LMT_REGU_WW13][bw][rate][ch][tx_num]);

				}
			}
		}
	}

	RF_DBG(rf, DBG_RF_INIT, "<======%s finish!!!\n", __func__);

}

void halrf_power_limit_set_ext_pwr_limit_table(struct rf_info *rf,
							enum phl_phy_idx phy)
{
#ifdef SPF_PHL_RF_019_SAR
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	struct rtw_hal_com_t *hal = rf->hal_com;
	u32 reg, bw, rate, bf, ch, tx_num;
	s8 ext_pwr = 0;
	u8 real_ch;

	RF_DBG(rf, DBG_RF_INIT, "======>%s   phy=%d\n", __func__, phy);

	reg = (u32)halrf_get_regulation_info(rf, BAND_ON_24G);

	for (tx_num = 0; tx_num < MAX_HALRF_PATH; tx_num++) {
		ext_pwr = hal->rtw_tpu_ext_pwr_lmt_i[phy].ext_pwr_lmt_2_4g[tx_num];
		for (ch = 0; ch < PW_LMT_MAX_CHANNEL_NUMBER_2G; ch++) {
			for (bf = 0; bf < PW_LMT_MAX_BF_NUM; bf++) {
				for (rate = 0; rate < PW_LMT_MAX_RS_NUM; rate++) {
					for (bw = 0; bw < PW_LMT_MAX_2G_BANDWITH_NUM; bw++) {
						
						RF_DBG(rf, DBG_RF_INIT, "ext_pwr_lmt_2_4g[%d]=%d   pwr->tx_pwr_limit_2g[%d][%d][%d][%d][%d][%d]=   %d\n",
							tx_num, ext_pwr,
							reg, bw, rate, bf, ch, tx_num , pwr->tx_pwr_limit_2g[reg][bw][rate][bf][ch][tx_num]);

						if (ext_pwr > 0) {
							if (pwr->tx_pwr_limit_2g[reg][bw][rate][bf][ch][tx_num] > 0 &&
									pwr->tx_pwr_limit_2g[reg][bw][rate][bf][ch][tx_num] < ext_pwr) {
								pwr->tx_pwr_limit_2g[PW_LMT_REGU_EXT_PWR][bw][rate][bf][ch][tx_num] =
									pwr->tx_pwr_limit_2g[reg][bw][rate][bf][ch][tx_num];
							} else {
								pwr->tx_pwr_limit_2g[PW_LMT_REGU_EXT_PWR][bw][rate][bf][ch][tx_num] = ext_pwr;
							}
						} else {
							pwr->tx_pwr_limit_2g[PW_LMT_REGU_EXT_PWR][bw][rate][bf][ch][tx_num] =
								pwr->tx_pwr_limit_2g[reg][bw][rate][bf][ch][tx_num];
						}

						RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_2g[%d][%d][%d][%d][%d][%d] =   %d\n",
								PW_LMT_REGU_EXT_PWR, bw, rate, bf, ch, tx_num ,
								pwr->tx_pwr_limit_2g[PW_LMT_REGU_EXT_PWR][bw][rate][bf][ch][tx_num]);
					}
				}
			}
		}
	}

	reg = (u32)halrf_get_regulation_info(rf, BAND_ON_5G);

	for (tx_num = 0; tx_num < MAX_HALRF_PATH; tx_num++) {
		for (ch = 0; ch < PW_LMT_MAX_CHANNEL_NUMBER_5G; ch++) {
			real_ch = halrf_get_limit_ch_idx_to_ch_idx(rf, PW_LMT_BAND_5G, (u8)ch);
			if (real_ch >= 36 && real_ch <= 48)
				ext_pwr = hal->rtw_tpu_ext_pwr_lmt_i[phy].ext_pwr_lmt_5g_band1[tx_num];
			else if (real_ch >= 50 && real_ch <= 64)
				ext_pwr = hal->rtw_tpu_ext_pwr_lmt_i[phy].ext_pwr_lmt_5g_band2[tx_num];
			else if (real_ch >= 100 && real_ch <= 144)
				ext_pwr = hal->rtw_tpu_ext_pwr_lmt_i[phy].ext_pwr_lmt_5g_band3[tx_num];
			else if (real_ch >= 149 && real_ch <= 177)
				ext_pwr = hal->rtw_tpu_ext_pwr_lmt_i[phy].ext_pwr_lmt_5g_band4[tx_num];

			for (bf = 0; bf < PW_LMT_MAX_BF_NUM; bf++) {
				for (rate = 0; rate < PW_LMT_MAX_RS_NUM; rate++) {
					for (bw = 0; bw < PW_LMT_MAX_BANDWIDTH_NUM; bw++) {

						RF_DBG(rf, DBG_RF_INIT, "ext_pwr_lmt_5g[%d]=%d   pwr->tx_pwr_limit_5g[%d][%d][%d][%d][%d][%d]=   %d\n",
							tx_num, ext_pwr,
							reg, bw, rate, bf, ch, tx_num , pwr->tx_pwr_limit_5g[reg][bw][rate][bf][ch][tx_num]);

						if (ext_pwr > 0) {
							if (pwr->tx_pwr_limit_5g[reg][bw][rate][bf][ch][tx_num] > 0 &&
									pwr->tx_pwr_limit_5g[reg][bw][rate][bf][ch][tx_num] < ext_pwr) {
								pwr->tx_pwr_limit_5g[PW_LMT_REGU_EXT_PWR][bw][rate][bf][ch][tx_num] =
									pwr->tx_pwr_limit_5g[reg][bw][rate][bf][ch][tx_num];
							} else {
								pwr->tx_pwr_limit_5g[PW_LMT_REGU_EXT_PWR][bw][rate][bf][ch][tx_num] = ext_pwr;
							}
						} else {
							pwr->tx_pwr_limit_5g[PW_LMT_REGU_EXT_PWR][bw][rate][bf][ch][tx_num] =
								pwr->tx_pwr_limit_5g[reg][bw][rate][bf][ch][tx_num];
						}

						RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_5g[%d][%d][%d][%d][%d][%d]=   %d\n",
							PW_LMT_REGU_EXT_PWR, bw, rate, bf, ch, tx_num,
							pwr->tx_pwr_limit_5g[PW_LMT_REGU_EXT_PWR][bw][rate][bf][ch][tx_num]);
					}
				}
			}
		}
	}

	RF_DBG(rf, DBG_RF_INIT, "<======%s finish!!!\n", __func__);
#endif
}

void halrf_power_limit_set_ext_pwr_limit_ru_table(struct rf_info *rf,
							enum phl_phy_idx phy)
{
#ifdef SPF_PHL_RF_019_SAR
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	struct rtw_hal_com_t *hal = rf->hal_com;
	u32 reg, bw, rate, ch, tx_num;
	s8 ext_pwr = 0;
	u8 real_ch; 

	RF_DBG(rf, DBG_RF_INIT, "======>%s   phy=%d\n", __func__, phy);

	reg = (u32)halrf_get_regulation_info(rf, BAND_ON_24G);

	for (tx_num = 0; tx_num < MAX_HALRF_PATH; tx_num++) {
		ext_pwr = hal->rtw_tpu_ext_pwr_lmt_i[phy].ext_pwr_lmt_2_4g[tx_num];
		for (ch = 0; ch < PW_LMT_MAX_CHANNEL_NUMBER_2G; ch++) {
			for (rate = 0; rate < PW_LMT_MAX_RS_NUM; rate++) {
				for (bw = 0; bw < PW_LMT_RU_BW_NULL; bw++) {

					RF_DBG(rf, DBG_RF_INIT, "ext_pwr_lmt_2_4g[%d]=%d   pwr->tx_pwr_limit_ru_2g[%d][%d][%d][%d][%d]=   %d\n",
						tx_num, ext_pwr,
						reg, bw, rate, ch, tx_num, pwr->tx_pwr_limit_ru_2g[reg][bw][rate][ch][tx_num]);

					if (ext_pwr > 0) {
						if (pwr->tx_pwr_limit_ru_2g[reg][bw][rate][ch][tx_num] > 0 &&
								pwr->tx_pwr_limit_ru_2g[reg][bw][rate][ch][tx_num] < ext_pwr) {
							pwr->tx_pwr_limit_ru_2g[PW_LMT_REGU_EXT_PWR][bw][rate][ch][tx_num] =
								pwr->tx_pwr_limit_ru_2g[reg][bw][rate][ch][tx_num];
						} else {
							pwr->tx_pwr_limit_ru_2g[PW_LMT_REGU_EXT_PWR][bw][rate][ch][tx_num] = ext_pwr;
						}
					} else {
						pwr->tx_pwr_limit_ru_2g[PW_LMT_REGU_EXT_PWR][bw][rate][ch][tx_num] =
							pwr->tx_pwr_limit_ru_2g[reg][bw][rate][ch][tx_num];
					}

					RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_ru_2g[%d][%d][%d][%d][%d] =   %d\n",
						PW_LMT_REGU_EXT_PWR, bw, rate, ch, tx_num,
						pwr->tx_pwr_limit_ru_2g[PW_LMT_REGU_EXT_PWR][bw][rate][ch][tx_num]);
				}
			}
		}
	}

	reg = (u32)halrf_get_regulation_info(rf, BAND_ON_5G);

	for (tx_num = 0; tx_num < MAX_HALRF_PATH; tx_num++) {
		for (ch = 0; ch < PW_LMT_MAX_CHANNEL_NUMBER_5G; ch++) {
			real_ch = halrf_get_limit_ch_idx_to_ch_idx(rf, PW_LMT_BAND_5G, (u8)ch);
			if (real_ch >= 36 && real_ch <= 48)
				ext_pwr = hal->rtw_tpu_ext_pwr_lmt_i[phy].ext_pwr_lmt_5g_band1[tx_num];
			else if (real_ch >= 50 && real_ch <= 64)
				ext_pwr = hal->rtw_tpu_ext_pwr_lmt_i[phy].ext_pwr_lmt_5g_band2[tx_num];
			else if (real_ch >= 100 && real_ch <= 144)
				ext_pwr = hal->rtw_tpu_ext_pwr_lmt_i[phy].ext_pwr_lmt_5g_band3[tx_num];
			else if (real_ch >= 149 && real_ch <= 177)
				ext_pwr = hal->rtw_tpu_ext_pwr_lmt_i[phy].ext_pwr_lmt_5g_band4[tx_num];

			for (rate = 0; rate < PW_LMT_MAX_RS_NUM; rate++) {
				for (bw = 0; bw < PW_LMT_RU_BW_NULL; bw++) {

					RF_DBG(rf, DBG_RF_INIT, "ext_pwr_lmt_5g[%d]=%d   pwr->tx_pwr_limit_ru_5g[%d][%d][%d][%d][%d]=   %d\n",
						tx_num, ext_pwr,
						reg, bw, rate, ch, tx_num, pwr->tx_pwr_limit_ru_5g[reg][bw][rate][ch][tx_num]);

					if (ext_pwr > 0) {
						if (pwr->tx_pwr_limit_ru_5g[reg][bw][rate][ch][tx_num] > 0 &&
								pwr->tx_pwr_limit_ru_5g[reg][bw][rate][ch][tx_num] < ext_pwr) {
							pwr->tx_pwr_limit_ru_5g[PW_LMT_REGU_EXT_PWR][bw][rate][ch][tx_num] =
								pwr->tx_pwr_limit_ru_5g[reg][bw][rate][ch][tx_num];
						} else {
							pwr->tx_pwr_limit_ru_5g[PW_LMT_REGU_EXT_PWR][bw][rate][ch][tx_num] = ext_pwr;
						}
					} else {
						pwr->tx_pwr_limit_ru_5g[PW_LMT_REGU_EXT_PWR][bw][rate][ch][tx_num] =
							pwr->tx_pwr_limit_ru_5g[reg][bw][rate][ch][tx_num];
					}

					RF_DBG(rf, DBG_RF_INIT, "pwr->tx_pwr_limit_ru_5g[%d][%d][%d][%d][%d]=   %d\n",
						PW_LMT_REGU_EXT_PWR, bw, rate, ch, tx_num,
						pwr->tx_pwr_limit_ru_5g[PW_LMT_REGU_EXT_PWR][bw][rate][ch][tx_num]);
				}
			}
		}
	}

	RF_DBG(rf, DBG_RF_INIT, "<======%s finish!!!\n", __func__);
#endif
}


s8 halrf_get_power_by_rate(struct rf_info *rf,
	enum phl_phy_idx phy,
	u8 rf_path, u16 rate, u8 dcm, u8 offset)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	u8 band;
	u16 rate_tmp;
	s8 pwr_by_rate;
	u8 channel = rf->hal_com->band[phy].cur_chandef.center_ch;

	RF_DBG(rf, DBG_RF_POWER, "======>%s rf_path=%d rate=0x%x dcm=%d\n",
		__func__, rf_path, rate, dcm);

	if (channel >= 1 && channel <= 14)
		band = PW_LMT_BAND_2_4G;
	else
		band = PW_LMT_BAND_5G;

	rate_tmp = halrf_get_dcm_offset_pwr_by_rate(rf, rate, dcm, offset);

	if ((rate_tmp >= HALRF_DATA_RATE_CCK1 && rate_tmp <= HALRF_DATA_RATE_CCK11) ||
		rate_tmp == HALRF_DATA_RATE_CCK_OFFSET) {
		pwr_by_rate = pwr->tx_pwr_by_rate[PW_LMT_BAND_2_4G][rate_tmp];

		RF_DBG(rf, DBG_RF_POWER, "pwr_by_rate(%d)=pwr->tx_pwr_by_rate[%d][%d] channel=%d\n",
			pwr_by_rate, PW_LMT_BAND_2_4G, rate_tmp, channel);
	} else {
		pwr_by_rate = pwr->tx_pwr_by_rate[band][rate_tmp];

		RF_DBG(rf, DBG_RF_POWER, "pwr_by_rate(%d)=pwr->tx_pwr_by_rate[%d][%d] channel=%d\n",
			pwr_by_rate, band, rate_tmp, channel);
	}

	return pwr_by_rate;
}

s8 halrf_get_power_by_rate_band(struct rf_info *rf,
	enum phl_phy_idx phy, u16 rate, u8 dcm, u8 offset, u32 band)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	u16 rate_tmp;
	s8 pwr_by_rate;

	RF_DBG(rf, DBG_RF_POWER, "======>%s rate=0x%x dcm=%d band=%d\n",
		__func__, rate, dcm, band);

	rate_tmp = halrf_get_dcm_offset_pwr_by_rate(rf, rate, dcm, offset);

	if ((rate_tmp >= HALRF_DATA_RATE_CCK1 && rate_tmp <= HALRF_DATA_RATE_CCK11) ||
		rate_tmp == HALRF_DATA_RATE_CCK_OFFSET) {
		pwr_by_rate = pwr->tx_pwr_by_rate[PW_LMT_BAND_2_4G][rate_tmp];

		RF_DBG(rf, DBG_RF_POWER, "pwr_by_rate(%d)=pwr->tx_pwr_by_rate[%d][%d] band=%d\n",
			pwr_by_rate, PW_LMT_BAND_2_4G, rate_tmp, band);
	} else {
		pwr_by_rate = pwr->tx_pwr_by_rate[band][rate_tmp];

		RF_DBG(rf, DBG_RF_POWER, "pwr_by_rate(%d)=pwr->tx_pwr_by_rate[%d][%d] band=%d\n",
			pwr_by_rate, band, rate_tmp, band);
	}

	return pwr_by_rate;
}

s8 halrf_get_power_limit(struct rf_info *rf,
	enum phl_phy_idx phy, u8 rf_path, u16 rate, u8 bandwidth,
	u8 beamforming, u8 tx_num, u8 channel)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	struct rtw_phl_com_t *phl = rf->phl_com;
	
#ifdef SPF_PHL_RF_019_SAR
	struct rtw_hal_com_t *hal = rf->hal_com;
#endif
	s8 pwr_limit;
	u8 limit_rate = PW_LMT_RS_CCK, limit_ch, reg;

	RF_DBG(rf, DBG_RF_POWER, "======>%s rf_path=%d rate=0x%x beamforming=%d\n",
		__func__, rf_path, rate, beamforming);

	limit_rate = halrf_hw_rate_to_limit_rate_tx_num(rf, rate);
	limit_ch = halrf_get_ch_idx_to_limit_array(rf, channel);

	if (channel >= 1 && channel <= 14) {

#ifdef SPF_PHL_RF_019_SAR
		if (hal->ext_pwr_lmt_en == true)
			reg = PW_LMT_REGU_EXT_PWR;
		else
#endif
			reg = halrf_get_regulation_info(rf, BAND_ON_24G);

		pwr_limit = pwr->tx_pwr_limit_2g[reg][bandwidth][limit_rate][beamforming][limit_ch][tx_num];
		RF_DBG(rf, DBG_RF_POWER, "pwr_limit(%d) = pwr->tx_pwr_limit_2g[%d][%d][%d][%d][%d][%d]\n",
			pwr_limit, reg, bandwidth, limit_rate, beamforming, limit_ch, tx_num);
	} else {
#ifdef SPF_PHL_RF_019_SAR
		if (hal->ext_pwr_lmt_en == true)
			reg = PW_LMT_REGU_EXT_PWR;
		else
#endif
			reg = halrf_get_regulation_info(rf, BAND_ON_5G);

		pwr_limit = pwr->tx_pwr_limit_5g[reg][bandwidth][limit_rate][beamforming][limit_ch][tx_num];
		RF_DBG(rf, DBG_RF_POWER, "pwr_limit(%d) = pwr->tx_pwr_limit_5g[%d][%d][%d][%d][%d][%d]\n",
			pwr_limit, reg, bandwidth, limit_rate, beamforming, limit_ch, tx_num);
	}

	if (pwr_limit == 127)
		pwr_limit = 0;

	return pwr_limit;
}

s8 halrf_get_power_limit_ru(struct rf_info *rf,
	enum phl_phy_idx phy, u8 rf_path, u16 rate, u8 bandwidth,
	u8 tx_num, u8 channel)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	struct rtw_phl_com_t *phl = rf->phl_com;

#ifdef SPF_PHL_RF_019_SAR
	struct rtw_hal_com_t *hal = rf->hal_com;
#endif
	s8 pwr_limit_ru;
	u8 limit_rate = PW_LMT_RS_CCK, limit_ch, reg;

	RF_DBG(rf, DBG_RF_POWER, "======>%s phy=%d rf_path=%d rate=0x%x\n",
		__func__, phy, rf_path, rate);

	limit_rate = halrf_hw_rate_to_limit_rate_tx_num(rf, rate);
	limit_ch = halrf_get_ch_idx_to_limit_array(rf, channel);

	if (channel >= 1 && channel <= 14) {
#ifdef SPF_PHL_RF_019_SAR
		if (hal->ext_pwr_lmt_en == true)
			reg = PW_LMT_REGU_EXT_PWR;
		else
#endif
			reg = halrf_get_regulation_info(rf, BAND_ON_24G);

		pwr_limit_ru = pwr->tx_pwr_limit_ru_2g[reg][bandwidth][limit_rate][limit_ch][tx_num];
		RF_DBG(rf, DBG_RF_POWER, "pwr_limit_ru(%d) = pwr->tx_pwr_limit_ru_2g[%d][%d][%d][%d][%d]\n",
			pwr_limit_ru, reg, bandwidth, limit_rate, limit_ch, tx_num);
	} else {
#ifdef SPF_PHL_RF_019_SAR
		if (hal->ext_pwr_lmt_en == true)
			reg = PW_LMT_REGU_EXT_PWR;
		else
#endif
			reg = halrf_get_regulation_info(rf, BAND_ON_5G);

		pwr_limit_ru = pwr->tx_pwr_limit_ru_5g[reg][bandwidth][limit_rate][limit_ch][tx_num];
		RF_DBG(rf, DBG_RF_POWER, "pwr_limit_ru(%d) = pwr->tx_pwr_limit_ru_5g[%d][%d][%d][%d][%d]\n",
			pwr_limit_ru, reg, bandwidth, limit_rate, limit_ch, tx_num);
	}

	if (pwr_limit_ru == 127)
		pwr_limit_ru = 0;

	return pwr_limit_ru;
}

s16 halrf_get_power(void *rf_void,
	u8 rf_path, u16 rate, u8 dcm, u8 offset, u8 bandwidth,
	u8 beamforming, u8 channel)
{
	struct rf_info *rf = (struct rf_info *)rf_void;
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	struct rtw_phl_com_t *phl = rf->phl_com;
	u8 band, limit_rate = PW_LMT_RS_CCK, tx_num = PW_LMT_PH_1T, limit_ch;
	u16 rate_tmp;
	s16 pwr_by_rate, pwr_limit, power;

	RF_DBG(rf, DBG_RF_INIT, "======>%s rf_path=%d rate=%d dcm=%d bw=%d bf=%d ch=%d\n",
		__func__, rf_path, rate, dcm, bandwidth, beamforming, channel);

	if (channel >= 1 && channel <= 14)
		band = PW_LMT_BAND_2_4G;
	else
		band = PW_LMT_BAND_5G;

	tx_num = rf_path;

	rate_tmp = halrf_get_dcm_offset_pwr_by_rate(rf, rate, dcm, offset);

	pwr_by_rate = (s16)pwr->tx_pwr_by_rate[band][rate_tmp];

	RF_DBG(rf, DBG_RF_INIT, "pwr_by_rate(%d)=(s16)pwr->tx_pwr_by_rate[%d][%d]\n",
		pwr_by_rate, band, rate_tmp);

	limit_rate = halrf_hw_rate_to_limit_rate_tx_num(rf, rate);
	limit_ch = halrf_get_ch_idx_to_limit_array(rf, channel);

	if (channel >= 1 && channel <= 14) {
		pwr_limit = (s16)pwr->tx_pwr_limit_2g[halrf_get_regulation_info(rf, BAND_ON_24G)][bandwidth][limit_rate][beamforming][limit_ch][tx_num];
		RF_DBG(rf, DBG_RF_INIT, "pwr_limit(%d) = (s16)pwr->tx_pwr_limit_2g[%d][%d][%d][%d][%d][%d]\n",
			pwr_limit, halrf_get_regulation_info(rf, BAND_ON_24G), bandwidth, limit_rate, beamforming, limit_ch, tx_num);
	} else {
		pwr_limit = (s16)pwr->tx_pwr_limit_5g[halrf_get_regulation_info(rf, BAND_ON_5G)][bandwidth][limit_rate][beamforming][limit_ch][tx_num];
		RF_DBG(rf, DBG_RF_INIT, "pwr_limit(%d) = (s16)pwr->tx_pwr_limit_5g[%d][%d][%d][%d][%d][%d]\n",
			pwr_limit, halrf_get_regulation_info(rf, BAND_ON_5G), bandwidth, limit_rate, beamforming, limit_ch, tx_num);
	}

	if (pwr_by_rate > pwr_limit)
		power = pwr_limit;
	else
		power = pwr_by_rate;

	RF_DBG(rf, DBG_RF_INIT, "power = %d\n", power);

	return power;
}

bool halrf_set_power(struct rf_info *rf, enum phl_phy_idx phy,
	enum phl_pwr_table pwr_table)
{
	struct rtw_hal_com_t *hal_com = rf->hal_com;
	bool result = true;

#ifdef RF_8852A_SUPPORT
	if (hal_com->chip_id == CHIP_WIFI6_8852A) {
		halrf_set_power_8852a(rf, phy, pwr_table);
	}
#endif

#ifdef RF_8852B_SUPPORT
	if (hal_com->chip_id == CHIP_WIFI6_8852B) {
		halrf_set_power_8852b(rf, phy, pwr_table);
	}
#endif

	return result;
}

bool halrf_get_efuse_power_table_switch(struct rf_info *rf, enum phl_phy_idx phy_idx)
{
	struct rtw_phl_com_t *phl_com = rf->phl_com;
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	struct rtw_tpu_info *tpu = &rf->hal_com->band[phy_idx].rtw_tpu_i;
	bool result = true;

	pwr->pwr_table_switch_efuse = phl_com->dev_cap.rf_board_opt & 0x3;
	pwr->pwr_by_rate_switch = phl_com->dev_cap.pwrbyrate_off; 
	pwr->pwr_limit_switch =  phl_com->dev_cap.pwrlmt_type;

	RF_DBG(rf, DBG_RF_POWER, "======>%s From Driver pwr->pwr_by_rate_switch=%d\n",
		__func__, pwr->pwr_by_rate_switch);

	RF_DBG(rf, DBG_RF_POWER, "======>%s From Driver pwr->pwr_limit_switch=%d\n",
			__func__, pwr->pwr_limit_switch);

	RF_DBG(rf, DBG_RF_POWER, "======>%s From Efuse pwr->pwr_table_switch_efuse=%d\n",
			__func__, pwr->pwr_table_switch_efuse);

	if (pwr->pwr_limit_switch == PWLMT_DISABLE)
		tpu->pwr_lmt_en = false;
	else if (pwr->pwr_limit_switch == PWBYRATE_AND_PWLMT)
		tpu->pwr_lmt_en = true;
	else {
		if (pwr->pwr_table_switch_efuse == 0)
			tpu->pwr_lmt_en = false;
		else if (pwr->pwr_table_switch_efuse == 2)
			tpu->pwr_lmt_en = false;
		else
			tpu->pwr_lmt_en = true;
	}

	halrf_mac_write_pwr_limit_en(rf, phy_idx);

	return result;
}

void halrf_set_power_table_switch(struct rf_info *rf,
	enum phl_phy_idx phy, u8 pwr_by_rate, u8 pwr_limt)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;

	pwr->pwr_by_rate_switch = pwr_by_rate;
	pwr->pwr_limit_switch = pwr_limt;
}

u8 halrf_get_power_limit_extra(struct rf_info *rf)
{
	struct halrf_pwr_info *pwr = &rf->pwr_info;
	struct rtw_para_pwrlmt_info_t *pwrlmt_info = NULL;
	struct _halrf_file_regd_ext *pregd_codemap = NULL;
	struct _halrf_file_regd_ext *array = NULL;
	struct rtw_regulation_info rg_info = {0};
	struct rtw_hal_com_t *hal = rf->hal_com;
	u16 i, j, regd_idx = 0xff;

	pwrlmt_info = &rf->phl_com->phy_sw_cap[HW_PHY_0].rf_txpwrlmt_info;
	pregd_codemap = (struct _halrf_file_regd_ext *) pwrlmt_info->ext_reg_codemap;

	if (pwrlmt_info->para_src == 0) {
		RF_DBG(rf, DBG_RF_POWER, "======>%s   is_form_folder=%d   Return!!!\n",
			__func__, pwrlmt_info->para_src);
		return 0xff;
	}

	RF_DBG(rf, DBG_RF_POWER, "======>%s  total_regd_idx=%d  extra_limit_idx=%d\n",
		__func__, pwrlmt_info->ext_regd_arridx, pwrlmt_info->ext_reg_map_num);

	halrf_query_regulation_info(rf, &rg_info);
		
	RF_DBG(rf, DBG_RF_POWER, "domain_code=0x%x   country=%s   regulation_2g=%d   regulation_5g=%d	chplan_ver=%d	country_ver=%d\n",
		rg_info.domain_code, rg_info.country, rg_info.regulation_2g, rg_info.regulation_5g, rg_info.chplan_ver, rg_info.country_ver);

	for (i = 0; i <= pwrlmt_info->ext_regd_arridx; i++)
		RF_DBG(rf, DBG_RF_POWER, "ext_regd_name[%d]=%s\n", i, pwrlmt_info->ext_regd_name[i]);

	RF_DBG(rf, DBG_RF_POWER, "======>   Start domain code Search\n");
	for (i = 0; i < pwrlmt_info->ext_reg_map_num; i++) {
		array = (struct _halrf_file_regd_ext *)&pregd_codemap[i];

		RF_DBG(rf, DBG_RF_POWER, "======>   %d\n", i);
		RF_DBG(rf, DBG_RF_POWER, "ent->domain=0x%x\n", array->domain);
		RF_DBG(rf, DBG_RF_POWER, "ent->country=%s\n", array->country);
		RF_DBG(rf, DBG_RF_POWER, "ent->reg_name=%s\n", array->reg_name);

		if (rg_info.domain_code == (u8)array->domain) {
			RF_DBG(rf, DBG_RF_POWER, "Search rg_info.domain_code == Power limit array->domain\n");
			for (j = 0; j <= pwrlmt_info->ext_regd_arridx; j++) {
				if (_os_strcmp(array->reg_name, pwrlmt_info->ext_regd_name[j]) == 0) {
					regd_idx = j;
					i = pwrlmt_info->ext_reg_map_num;
					RF_DBG(rf, DBG_RF_POWER, "======>   Search regd_idx=%d\n", regd_idx);
					break;
				}
			}
		}
	}
	RF_DBG(rf, DBG_RF_POWER, "<======   End domain code Search\n");

	RF_DBG(rf, DBG_RF_POWER, "======>   Start Country code Search\n");
	for (i = 0; i < pwrlmt_info->ext_reg_map_num; i++) {
		array = (struct _halrf_file_regd_ext *)&pregd_codemap[i];
		
		RF_DBG(rf, DBG_RF_POWER, "======>   %d\n", i);
		RF_DBG(rf, DBG_RF_POWER, "ent->domain=0x%x\n", array->domain);
		RF_DBG(rf, DBG_RF_POWER, "ent->country=%s\n", array->country);
		RF_DBG(rf, DBG_RF_POWER, "ent->reg_name=%s\n", array->reg_name);

		if (hal_mem_cmp(hal, rg_info.country, array->country, 2) == 0 && _os_strcmp(rg_info.country, "") != 0) {
			RF_DBG(rf, DBG_RF_POWER, "Search rg_info.country == Power limit array->country\n");
			for (j = 0; j <= pwrlmt_info->ext_regd_arridx; j++) {
				if (_os_strcmp(array->reg_name, pwrlmt_info->ext_regd_name[j]) == 0) {
					regd_idx = j;
					i = pwrlmt_info->ext_reg_map_num;
					RF_DBG(rf, DBG_RF_POWER, "======>   Search regd_idx=%d\n", regd_idx);
					break;
				}
			}
		}
	}
	RF_DBG(rf, DBG_RF_POWER, "<======   End Country code Search\n");

	RF_DBG(rf, DBG_RF_POWER, "Return regd_idx = %d\n", regd_idx);

	return (u8)regd_idx;
}

void halrf_reload_pwr_limit_tbl_and_set(struct rf_info *rf,
	enum phl_phy_idx phy, enum phl_pwr_table pwr_table)
{
	struct rtw_para_pwrlmt_info_t *pwrlmt_info = NULL;
	
	bool is_form_folder;
	u32 folder_len;
	u32 *folder_array;

	RF_DBG(rf, DBG_RF_POWER, "======>%s\n", __func__);

	if (pwr_table == PWR_LIMIT) {
		pwrlmt_info = &rf->phl_com->phy_sw_cap[HW_PHY_0].rf_txpwrlmt_info;

		is_form_folder = pwrlmt_info->para_src;
		folder_len = pwrlmt_info->para_data_len;
		folder_array = pwrlmt_info->para_data;

		RF_DBG(rf, DBG_RF_POWER, "Reload power limit table and set. is_form_folder=%d folder_len=%d\n",
			is_form_folder, folder_len);

		halrf_config_store_power_limit(rf , is_form_folder,
				folder_len, folder_array);

		halrf_set_power(rf, phy, pwr_table);
	}

	if (pwr_table == PWR_LIMIT_RU) {
		pwrlmt_info = &rf->phl_com->phy_sw_cap[HW_PHY_0].rf_txpwrlmt_ru_info;

		is_form_folder = pwrlmt_info->para_src;
		folder_len = pwrlmt_info->para_data_len;
		folder_array = pwrlmt_info->para_data;
		
		RF_DBG(rf, DBG_RF_POWER, "Reload power limit RU table and set. is_form_folder=%d folder_len=%d\n",
			is_form_folder, folder_len);

		halrf_config_store_power_limit_ru(rf , is_form_folder,
				folder_len, folder_array);

		halrf_set_power(rf, phy, pwr_table);
	}

	RF_DBG(rf, DBG_RF_POWER, "<======%s finish!\n", __func__);
}
