/******************************************************************************
 *
 * Copyright(c) 2007 - 2020  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.
 *
 * The full GNU General Public License is included in this distribution in the
 * file called LICENSE.
 *
 * Contact Information:
 * wlanfae <wlanfae@realtek.com>
 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
 * Hsinchu 300, Taiwan.
 *
 * Larry Finger <Larry.Finger@lwfinger.net>
 *
 *****************************************************************************/
#include "halbb_precomp.h"

#ifdef HALBB_DIG_SUPPORT

#ifdef BB_8852A_2_SUPPORT
u8 halbb_lna_idx_by_rssi(struct bb_info *bb, u8 rssi)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	u8 lna_idx = LNA_IDX_MAX;

	if (rssi < bb_dig_u->dig_op_para.igi_rssi_th[0])
		lna_idx = 6;
	else if (rssi < bb_dig_u->dig_op_para.igi_rssi_th[1])
		lna_idx = 5;
	else if (rssi < bb_dig_u->dig_op_para.igi_rssi_th[2])
		lna_idx = 4;
	else if (rssi < bb_dig_u->dig_op_para.igi_rssi_th[3])
		lna_idx = 3;
	else if (rssi < bb_dig_u->dig_op_para.igi_rssi_th[4])
		lna_idx = 2;
	else
		lna_idx = 1;

	return lna_idx;
}

u8 halbb_tia_idx_by_rssi(struct bb_info *bb, u8 rssi)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	u8 tia_idx = TIA_IDX_MAX;

	if (rssi < bb_dig_u->dig_op_para.igi_rssi_th[0])
		tia_idx = 1;
	else
		tia_idx = 0;

	return tia_idx;
}

u8 halbb_rxb_idx_by_rssi(struct bb_info *bb,
			 struct agc_gaincode_set *set, u8 rssi)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	u8 rxb_idx = RXB_IDX_MAX;
	s8 lna_gain = bb_dig->lna_gain[set->lna_idx];
	s8 tia_gain = bb_dig->tia_gain[set->tia_idx];
	s32 rxb_idx_tmp = RXB_IDX_MAX;
	s32 wb_rssi = rssi + lna_gain + tia_gain;

	rxb_idx_tmp = (bb_dig->ib_pkpwr - bb_dig->ib_pbk + 110) - wb_rssi + 10;

	if (rxb_idx_tmp > RXB_IDX_MAX)
		rxb_idx = RXB_IDX_MAX;
	else if (rxb_idx_tmp < RXB_IDX_MIN)
		rxb_idx = RXB_IDX_MIN;
	else
		rxb_idx = (u8)rxb_idx_tmp;

	BB_DIG_DBG(bb, DIG_DBG_LV2, "wb_rssi=%03d, rxb_idx_tmp=%03d\n",
		   wb_rssi, rxb_idx_tmp);

	return rxb_idx;
}


void halbb_dig_set_igi_cr_8852a(struct bb_info *bb, const struct agc_gaincode_set set)
{
	if (bb->ic_type != BB_RTL8852A)
		return;

	halbb_set_igi_8852a_2(bb, set.lna_idx, set.tia_idx, set.rxb_idx, RF_PATH_A);
	halbb_set_igi_8852a_2(bb, set.lna_idx, set.tia_idx, set.rxb_idx, RF_PATH_B);

	BB_DIG_DBG(bb, DIG_DBG_LV1, "Set (lna,tia,rxb)=((%d,%d,%02d))\n",
		   set.lna_idx, set.tia_idx, set.rxb_idx);
}

void halbb_dig_agc_update_8852a(struct bb_info *bb, struct bb_dig_op_para_unit *para)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	u8 igi_rssi_th_ifem[IGI_RSSI_TH_NUM] = {68, 84, 90, 98, 104};
	u8 igi_rssi_th_efem[IGI_RSSI_TH_NUM] = {68, 84, 90, 98, 104};
	u8 *igi_rssi_th;


	if (bb->ic_type != BB_RTL8852A)
		return;

	/* gain para update */
	bb_dig->lna_gain = bb_dig->lna_gain_g;
	bb_dig->tia_gain = bb_dig->tia_gain_g;

	/* igi rssi th update */
	switch (bb->phl_com->dev_cap.rfe_type) {
	case 51:
	case 52:
	case 53:
	case 54:
		igi_rssi_th = igi_rssi_th_efem;
		break;
	default:
		igi_rssi_th = igi_rssi_th_ifem;
	}

	halbb_mem_cpy(bb, &para->igi_rssi_th, igi_rssi_th, sizeof(u8) * IGI_RSSI_TH_NUM);

	BB_DIG_DBG(bb, DIG_DBG_LV1, "Sigi_rssi_th[4:0] = %d,%d,%d,%d,%d\n",
		   para->igi_rssi_th[4], para->igi_rssi_th[3],
		   para->igi_rssi_th[2], para->igi_rssi_th[1],
		   para->igi_rssi_th[0]);
}

#if 0
void halbb_dig_write_igi_8852a(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;

	halbb_dig_set_igi_cr_8852a(bb, bb_dig_u->cur_gaincode);
}
#endif

void halbb_gaincode_by_rssi_8852a(struct bb_info *bb,
			    struct agc_gaincode_set *set, u8 rssi) {
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;

	if (bb->ic_type != BB_RTL8852A)
		return;

	set->lna_idx = halbb_lna_idx_by_rssi(bb, rssi);
	set->tia_idx = halbb_tia_idx_by_rssi(bb, rssi);
	set->rxb_idx = halbb_rxb_idx_by_rssi(bb, set, rssi);

	BB_DIG_DBG(bb, DIG_DBG_LV1, "final_rssi=%03d, (lna,tia,rab)=(%d,%d,%02d)\n",
	       rssi, set->lna_idx, set->tia_idx, set->rxb_idx);
}

bool halbb_dig_gaincode_update_en_8852a(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	struct rtw_hw_band *hw_band = &bb->hal_com->band[bb->bb_phy_idx];

	if ((bb->ic_type != BB_RTL8852A) || (bb->hal_com->cv >= CCV))
		return false;

	if (hw_band->cur_chandef.band != BAND_ON_24G)
		return false;

	halbb_gaincode_by_rssi_8852a(bb, &bb_dig_u->cur_gaincode, bb_dig_u->igi_fa_rssi);

	return true;
}

#endif

#ifdef HALBB_DIG_DAMPING_CHK
void halbb_dig_recorder_reset(struct bb_info *bb)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;
	struct bb_dig_record_info *dig_rc = &dig->bb_dig_record_i;

	BB_DBG(bb, DBG_DIG,  "%s ======>\n", __func__);

	halbb_mem_set(bb, dig_rc, 0, sizeof(struct bb_dig_record_info));
}

void halbb_dig_recorder(struct bb_info *bb, u8 igi_curr, u32 fa_metrics)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;
	struct bb_dig_record_info *dig_rc = &dig->bb_dig_record_i;
	u8 igi_pre = dig_rc->igi_history[0];
	u8 igi_up = 0;

//	if (!bb->bb_link_i.is_linked)
//		return;

	BB_DBG(bb, DBG_DIG,  "%s ======>\n", __func__);

#if 0
	if (bb->bb_link_i.first_connect) {
		BB_DBG(bb, DBG_DIG,  "first_connect\n");
		halbb_dig_recorder_reset(bb);
		dig_rc->igi_history[0] = igi_curr;
		dig_rc->fa_history[0] = fa_metrics;
		return;
	}
#endif

	igi_pre = dig_rc->igi_history[0];
	igi_up = (igi_curr > igi_pre) ? 1 : 0;
	dig_rc->igi_bitmap = (dig_rc->igi_bitmap << 1) | igi_up;

	dig_rc->igi_history[5] = dig_rc->igi_history[4];
	dig_rc->igi_history[4] = dig_rc->igi_history[3];
	dig_rc->igi_history[3] = dig_rc->igi_history[2];
	dig_rc->igi_history[2] = dig_rc->igi_history[1];
	dig_rc->igi_history[1] = dig_rc->igi_history[0];
	dig_rc->igi_history[0] = igi_curr;

	dig_rc->fa_history[5] = dig_rc->fa_history[4];
	dig_rc->fa_history[4] = dig_rc->fa_history[3];
	dig_rc->fa_history[3] = dig_rc->fa_history[2];
	dig_rc->fa_history[2] = dig_rc->fa_history[1];
	dig_rc->fa_history[1] = dig_rc->fa_history[0];
	dig_rc->fa_history[0] = fa_metrics;

	BB_DBG(bb, DBG_DIG, "igi_history[5:0] = {%02d, %02d, %02d, %02d, %02d, %02d}\n",
		dig_rc->igi_history[5], dig_rc->igi_history[4], dig_rc->igi_history[3], dig_rc->igi_history[2],
		dig_rc->igi_history[1], dig_rc->igi_history[0]);
	BB_DBG(bb, DBG_DIG, "fa_history[5:0]  = {%02d, %02d, %02d, %02d, %02d, %02d}\n",
	       dig_rc->fa_history[5], dig_rc->fa_history[4], dig_rc->fa_history[3], dig_rc->fa_history[2],
	       dig_rc->fa_history[1], dig_rc->fa_history[0]);
	BB_DBG(bb, DBG_DIG, "igi_bitmap[5:0]=0x%x{ %d,  %d,  %d,  %d,  %d,  %d}\n",
	       dig_rc->igi_bitmap,
	       (dig_rc->igi_bitmap & BIT5) >> 5,
	       (dig_rc->igi_bitmap & BIT4) >> 4,
	       (dig_rc->igi_bitmap & BIT3) >> 3,
	       (dig_rc->igi_bitmap & BIT2) >> 2,
	       (dig_rc->igi_bitmap & BIT1) >> 1,
	       dig_rc->igi_bitmap & BIT0);
}

void halbb_dig_damping_chk(struct bb_info *bb)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;
	struct bb_dig_record_info *dig_rc = &dig->bb_dig_record_i;
	struct bb_dig_op_unit *bb_dig_u = dig->p_cur_dig_unit;
	u8 diff1 = 0, diff2 = 0;
	u32 fa_low_th = bb_dig_u->dig_op_para.fa_th[0];
	u32 fa_high_th = bb_dig_u->dig_op_para.fa_th[1];
	u32 fa_high_th2 = bb_dig_u->dig_op_para.fa_th[2];
	u32 fa_high_th3 = bb_dig_u->dig_op_para.fa_th[3];
	bool fa_pattern_match = false;
	u32 time_tmp = 0;

	if (!bb->bb_link_i.is_linked)
		return;

	BB_DBG(bb, DBG_DIG, "%s ======>\n", __func__);

	/*@== Release Damping ================================================*/
	if (dig_rc->damping_lock_en) {
		BB_DBG(bb, DBG_DIG,
		       "[Damping Limit!] limit_time=%d, phydm_sys_up_time=%d\n",
		       dig_rc->limit_time, bb->bb_sys_up_time);

		time_tmp = dig_rc->limit_time + DIG_LIMIT_PERIOD;

		if (DIFF_2(bb->bb_ch_i.rssi_min, dig_rc->limit_rssi) > dig->rls_rssi_diff_th ||
		    time_tmp < bb->bb_sys_up_time) {
			dig_rc->damping_lock_en = false;
			BB_DBG(bb, DBG_DIG, "[Rls] rssi=%d.%d, limit_rssi=%d.%d, th=%d.%d\n",
			       bb->bb_ch_i.rssi_min >> 1,
			       (bb->bb_ch_i.rssi_min & 1) * 5,
			       dig_rc->limit_rssi >> 1,
			       (dig_rc->limit_rssi & 1) * 5,
			       dig->rls_rssi_diff_th >> 1,
			       (dig->rls_rssi_diff_th & 1) * 5);
		}
		return;
	}

	/*@== Damping Pattern Check===========================================*/
	BB_DBG(bb, DBG_DIG, "fa_th{H2, H2, H1, L}= {%d,%d,%d,%d}\n",
	       fa_high_th3, fa_high_th2, fa_high_th, fa_low_th);

	if ((dig_rc->igi_bitmap & 0xf) == 0x5) {
		BB_DBG(bb, DBG_DIG, "[Type:0] map=0x5\n");
	/*@ 4b'0101
	* IGI:[3]down(0x24)->[2]up(0x26)->[1]down(0x24)->[0]up(0x26)->[new](Lock @ 0x26)
	* FA: [3] >high1   ->[2] <low   ->[1] >high1   ->[0] <low   ->[new]   <low
	*
	* IGI:[3]down(0x24)->[2]up(0x28)->[1]down(0x24)->[0]up(0x28)->[new](Lock @ 0x28)
	* FA: [3] >high2   ->[2] <low   ->[1] >high2   ->[0] <low   ->[new]   <low
	*/
		if (dig_rc->igi_history[0] > dig_rc->igi_history[1])
			diff1 = dig_rc->igi_history[0] - dig_rc->igi_history[1];

		if (dig_rc->igi_history[2] > dig_rc->igi_history[3])
			diff2 = dig_rc->igi_history[2] - dig_rc->igi_history[3];

		if (dig_rc->fa_history[0] < fa_low_th &&
		    dig_rc->fa_history[1] >= fa_high_th &&
		    dig_rc->fa_history[2] < fa_low_th &&
		    dig_rc->fa_history[3] >= fa_high_th) {
		    /*@Check each fa element*/
			fa_pattern_match = true;
		}

	} else if ((dig_rc->igi_bitmap & 0x1f) == 0x9) {
		BB_DBG(bb, DBG_DIG, "[Type:1] map=0x9\n");
	/*@ 5b'01001
	* IGI:[3]up(0x28)->[2]down(0x26)->[1]down(0x24)->[0]up(0x28)->[new](Lock @ 0x28)
	* FA: [3]  <low  ->[2] <low     ->[1] >high2   ->[0] <low   ->[new]  <low
	*/
		if (dig_rc->igi_history[0] > dig_rc->igi_history[1])
			diff1 = dig_rc->igi_history[0] - dig_rc->igi_history[1];

		if (dig_rc->igi_history[3] > dig_rc->igi_history[4])
			diff2 = dig_rc->igi_history[3] - dig_rc->igi_history[4];

		if (dig_rc->fa_history[0] < fa_low_th &&
		    dig_rc->fa_history[1] >= fa_high_th2 &&
		    dig_rc->fa_history[2] < fa_low_th &&
		    dig_rc->fa_history[3] < fa_low_th) {
		    /*@Check each fa element*/
			fa_pattern_match = true;
		}
	} else if ((dig_rc->igi_bitmap & 0x3f) == 0x11) {
		BB_DBG(bb, DBG_DIG, "[Type:2] map=0x11\n");
	/*@ 6b'010001
	* IGI:[4]up(0x28)->[3]down(0x26)->[2]down(0x24)->[1]down(0x22)->[0]up(0x28)->[new](Lock @ 0x28)
	* FA: [4]  <low  ->[3] <low     ->[2] <low     ->[1] >high3   ->[0] <low   ->[new]  <low
	*/
		if (dig_rc->igi_history[0] > dig_rc->igi_history[1])
			diff1 = dig_rc->igi_history[0] - dig_rc->igi_history[1];

		if (dig_rc->igi_history[4] > dig_rc->igi_history[5])
			diff2 = dig_rc->igi_history[4] - dig_rc->igi_history[5];

		if (dig_rc->fa_history[0] < fa_low_th &&
		    dig_rc->fa_history[1] >= fa_high_th3 &&
		    dig_rc->fa_history[2] < fa_low_th &&
		    dig_rc->fa_history[3] < fa_low_th &&
		    dig_rc->fa_history[4] < fa_low_th) {
		    /*@Check each fa element*/
			fa_pattern_match = true;
		}
	}

	if (diff1 >= 2 && diff2 >= 2 && fa_pattern_match) {
		dig_rc->damping_lock_en = true;
		dig_rc->damping_limit_val = dig_rc->igi_history[0];
		dig_rc->limit_time = bb->bb_sys_up_time;
		dig_rc->limit_rssi = bb->bb_ch_i.rssi_min;

		BB_DBG(bb, DBG_DIG,
		       "[Start damping_limit!] IGI_dyn_min=0x%x, limit_time=%d, limit_rssi=%d\n",
		       dig_rc->damping_limit_val,
		       dig_rc->limit_time, dig_rc->limit_rssi >> 1);
	}
	BB_DBG(bb, DBG_DIG,  "[lock_en=%d] ptrn_match=%d, diff1=%d, diff2=%d\n",
	       dig_rc->damping_lock_en, fa_pattern_match, diff1, diff2);
}

void halbb_dig_damping_chk_init(struct bb_info *bb)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;
	struct bb_dig_record_info *dig_rc = &dig->bb_dig_record_i;

	halbb_dig_recorder_reset(bb);
	dig->dig_dl_en = true;
	dig->rls_rssi_diff_th = 6; /*6 >> 1 = 3dB*/
}
#endif

u8 halbb_get_lna_idx(struct bb_info *bb, enum rf_path path)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	const struct bb_dig_cr_info *cr = &bb_dig->bb_dig_cr_i;
	u8 lna_idx = LNA_IDX_MAX;

	/*lna initial gain index*/
	switch (path) {
	case RF_PATH_A:
		lna_idx = (u8)halbb_get_reg_cmn(bb, cr->path0_lna_init_idx,
					        cr->path0_lna_init_idx_m,
					        bb->bb_phy_idx);
		break;
	case RF_PATH_B:
		lna_idx = (u8)halbb_get_reg_cmn(bb, cr->path1_lna_init_idx,
					        cr->path1_lna_init_idx_m,
					        bb->bb_phy_idx);
		break;
	default:
		break;
	}

	return lna_idx;
}

u8 halbb_get_tia_idx(struct bb_info *bb, enum rf_path path)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	const struct bb_dig_cr_info *cr = &bb_dig->bb_dig_cr_i;
	u8 tia_idx = TIA_IDX_MAX;

	switch (path) {
	case RF_PATH_A:
		tia_idx = (u8)halbb_get_reg_cmn(bb, cr->path0_tia_init_idx,
						cr->path0_tia_init_idx_m,
						bb->bb_phy_idx);
		break;
	case RF_PATH_B:
		tia_idx = (u8)halbb_get_reg_cmn(bb, cr->path1_tia_init_idx,
					        cr->path1_tia_init_idx_m,
					        bb->bb_phy_idx);
		break;
	default:
		break;
	}

	return tia_idx;
}

u8 halbb_get_rxb_idx(struct bb_info *bb, enum rf_path path)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	const struct bb_dig_cr_info *cr = &bb_dig->bb_dig_cr_i;
	u8 rxb_idx = RXB_IDX_MAX;

	switch (path) {
	case RF_PATH_A:
		rxb_idx = (u8)halbb_get_reg_cmn(bb,
						cr->path0_rxb_init_idx,
					        cr->path0_rxb_init_idx_m,
					        bb->bb_phy_idx);
		break;
	case RF_PATH_B:
		rxb_idx = (u8)halbb_get_reg_cmn(bb,
						cr->path1_rxb_init_idx,
					        cr->path1_rxb_init_idx_m,
					        bb->bb_phy_idx);
		break;
	default:
		break;
	}

	return rxb_idx;
}

u8 halbb_igi_by_edcca(struct bb_info *bb, u8 igi)
{
#ifdef HALBB_EDCCA_SUPPORT
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	const u8 margin = IGI_EDCCA_GAP_LIMIT - 18; /* -128(dBm)+110(RSSI) */
	u8 bound = bb->bb_edcca_i.th_h;

	bound = margin > (EDCCA_MAX - bound) ? EDCCA_MAX : (bound + margin);
	if (igi > bound) {
		igi = bound;
		BB_DIG_DBG(bb, DIG_DBG_LV0, "EDCCA th_h = %d, IGI upper clamp to %d.\n",
			   bb->bb_edcca_i.th_h, bound);
	}
#endif
	return igi;
}

void halbb_dig_noisy_lv_decision(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	struct bb_dig_op_para_unit *para = &bb_dig_u->dig_op_para;
	u16 fa_ratio = bb_dig_u->fa_r_avg;

	if (bb_dig_u->fa_valid_state_cnt == 0) {
		bb_dig_u->cur_noisy_lv = DIG_NOISY_LV1;
		BB_DIG_DBG(bb, DIG_DBG_LV1, "fa_ratio N/A, set noisy_lv=%d\n", DIG_NOISY_LV1);
		return;
	}

	if (fa_ratio < para->fa_th[0])
		bb_dig_u->cur_noisy_lv = DIG_NOISY_LV0;
	else if (fa_ratio < para->fa_th[1])
		bb_dig_u->cur_noisy_lv = DIG_NOISY_LV1;
	else if (fa_ratio < para->fa_th[2])
		bb_dig_u->cur_noisy_lv = DIG_NOISY_LV2;
	else if (fa_ratio < para->fa_th[3])
		bb_dig_u->cur_noisy_lv = DIG_NOISY_LV3;
	else
		bb_dig_u->cur_noisy_lv = DIG_NOISY_LV_MAX;

	BB_DIG_DBG(bb, DIG_DBG_LV1, "fa_th: [+6 (%d) +4 (%d) +2 (%d) 0 (%d) -2 ]\n",
		   para->fa_th[3], para->fa_th[2], para->fa_th[1], para->fa_th[0]);

	BB_DIG_DBG(bb, DIG_DBG_LV1, "fa_avg=%d, noisy_lv=%d\n",
		   bb_dig_u->fa_r_avg, bb_dig_u->cur_noisy_lv);

	bb_dig_u->fa_valid_state_cnt = 0;
}

s8 halbb_dig_ofst_by_fa(struct bb_info *bb, u16 fa)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_para_unit *para = &bb_dig->p_cur_dig_unit->dig_op_para;
	//enum dig_noisy_level noisy_lv;
	s8 ofst = 0;

	if (fa < para->fa_th[0]) {
		//noisy_lv = DIG_NOISY_LV0;
		ofst = -2;
	} else if (fa < para->fa_th[1]) {
		//noisy_lv = DIG_NOISY_LV1;
		ofst = 0;
	} else if (fa < para->fa_th[2]) {
		//noisy_lv = DIG_NOISY_LV2;
		ofst = 2;
	} else if (fa < para->fa_th[3]) {
		//noisy_lv = DIG_NOISY_LV3;
		ofst = 4;
	} else {
		//noisy_lv = DIG_NOISY_LV_MAX;
		ofst = 6;
	}

	BB_DIG_DBG(bb, DIG_DBG_LV1, "fa_th: [+6 (%d) +4 (%d) +2 (%d) 0 (%d) -2 ]\n",
		   para->fa_th[3], para->fa_th[2], para->fa_th[1], para->fa_th[0]);

	BB_DIG_DBG(bb, DIG_DBG_LV1, "fa=%d, ofst=%d\n", fa, ofst);

	return ofst;
}

u8 halbb_dig_igi_by_ofst(struct bb_info *bb, u8 igi_pre, s8 ofst)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *dig_u = dig->p_cur_dig_unit;
	#ifdef HALBB_DIG_DAMPING_CHK
	struct bb_dig_record_info *dig_rc = &dig->bb_dig_record_i;
	#endif
	u8 joint_max, joint_min;
	u8 dyn_min, dyn_max;
	u8 igi_new;

	igi_new = (u8)((s8)igi_pre + ofst);
	dyn_min = SUBTRACT_TO_0(dig->igi_rssi, 10);
	dyn_max = dyn_min + IGI_OFFSET_MAX;

	#ifdef HALBB_DIG_DAMPING_CHK
	/*@Limit Dyn min by damping*/
	if (dig->dig_dl_en &&
	    dig_rc->damping_lock_en &&
	    dyn_min < dig_rc->damping_limit_val) {
		BB_DBG(bb, DBG_DIG, "[Limit by Damping] Dyn_min=0x%x -> 0x%x\n",
		       dyn_min, dig_rc->damping_limit_val);

		dyn_min = dig_rc->damping_limit_val;
	}
	#endif

	joint_max = MIN_2(dyn_max, dig_u->abs_igi_max);
	joint_min = MAX_2(dyn_min, dig_u->abs_igi_min);

	if (joint_max >= joint_min) {
	/*Check IGI exceed the max/in boundary or not*/
		if (igi_new > joint_max)
			igi_new = joint_max;
		else if (igi_new < joint_min)
			igi_new = joint_min;
	} else {
		igi_new = joint_max;
	}

	BB_DIG_DBG(bb, DIG_DBG_LV0,
		   "rssi=%02d, dyn(max,min)=(%d,%d), abs(max,min)=(%d,%d), Joint(max,min)=(%d,%d), igi=%d\n",
		   dig->igi_rssi,
		   dyn_max, dyn_min,
		   dig_u->abs_igi_max, dig_u->abs_igi_min,
		   joint_max, joint_min,
		   igi_new);

	return igi_new;
}

void halbb_dig_igi_ofst_by_env(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	u8 fa_rssi_ofst_pre = bb_dig_u->fa_rssi_ofst;

	switch (bb_dig_u->cur_noisy_lv) {
	case DIG_NOISY_LV0:
		if (bb_dig_u->fa_rssi_ofst < 2)
			bb_dig_u->fa_rssi_ofst = 0;
		else
			bb_dig_u->fa_rssi_ofst -= 2;
		break;
	case DIG_NOISY_LV2:
		bb_dig_u->fa_rssi_ofst += 2;
		break;
	case DIG_NOISY_LV3:
		bb_dig_u->fa_rssi_ofst += 4;
		break;
	case DIG_NOISY_LV_MAX:
		bb_dig_u->fa_rssi_ofst += 6;
		break;
	default:
		break;
	}

	if (bb_dig_u->fa_rssi_ofst > IGI_OFFSET_MAX)
		bb_dig_u->fa_rssi_ofst = IGI_OFFSET_MAX;

	BB_DIG_DBG(bb, DIG_DBG_LV0, "[noisy_lv=%d] ofst: %d -> %d (max: %d)\n",
		   bb_dig_u->cur_noisy_lv, fa_rssi_ofst_pre, bb_dig_u->fa_rssi_ofst, IGI_OFFSET_MAX);
}

u8 halbb_dig_igi_bound_decision(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	#ifdef HALBB_DIG_DAMPING_CHK
	struct bb_dig_record_info *dig_rc = &bb_dig->bb_dig_record_i;
	#endif
	u8 tmp_max_bound = bb_dig_u->abs_igi_max;
	u8 tmp_min_bound = bb_dig_u->abs_igi_min;
	u8 igi_new;

	if (bb_dig->igi_rssi < 10)
		bb_dig_u->dyn_igi_min = 0;
	else
		bb_dig_u->dyn_igi_min = bb_dig->igi_rssi - 10;

	bb_dig_u->dyn_igi_max = bb_dig_u->dyn_igi_min + IGI_OFFSET_MAX;
	igi_new = bb_dig_u->dyn_igi_min + bb_dig_u->fa_rssi_ofst;

	#ifdef HALBB_DIG_DAMPING_CHK
	/*@Limit Dyn min by damping*/
	if (bb_dig->dig_dl_en &&
	    dig_rc->damping_lock_en &&
	    bb_dig_u->dyn_igi_min < dig_rc->damping_limit_val) {
		BB_DBG(bb, DBG_DIG,
			  "[Limit by Damping] Dig_dyn_min=0x%x -> 0x%x\n",
			  bb_dig_u->dyn_igi_min, dig_rc->damping_limit_val);

		bb_dig_u->dyn_igi_min = dig_rc->damping_limit_val;
	}
	#endif

	tmp_max_bound = MIN_2(bb_dig_u->dyn_igi_max, tmp_max_bound);
	tmp_min_bound = MAX_2(bb_dig_u->dyn_igi_min, tmp_min_bound);

	if (igi_new > tmp_max_bound)
		igi_new = tmp_max_bound;
	else if (igi_new < tmp_min_bound)
		igi_new = tmp_min_bound;

	BB_DIG_DBG(bb, DIG_DBG_LV0, "rssi_min=%02d, dyn(max,min)=(%d,%d), abs(max,min)=(%d,%d), igi=%d\n",
		   bb_dig->igi_rssi,
		   bb_dig_u->dyn_igi_max, bb_dig_u->dyn_igi_min,
		   bb_dig_u->abs_igi_max, bb_dig_u->abs_igi_min,
		   igi_new);

	return igi_new;
}

bool halbb_dig_ifs_clm_trig(struct bb_info *bb, u16 mntr_time)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	bool is_trig_success = false;
#ifdef HALBB_ENV_MNTR_SUPPORT
	struct env_trig_rpt rpt = {0};

	/* trigger env_mntr_rpt */
	bb_dig->ccx_para_i.mntr_time = mntr_time - 15;
	if (halbb_env_mntr_trigger(bb, &bb_dig->ccx_para_i, &rpt)
	    & IFS_CLM_SUCCESS) {
		BB_DIG_DBG(bb, DIG_DBG_LV2, "ifs_clm trigger ok, timestamp %d, mntr_time %d ms.\n",
			   rpt.ccx_rpt_stamp, bb_dig->ccx_para_i.mntr_time);
		bb_dig->ccx_timestamp = rpt.ccx_rpt_stamp;
		bb_dig->ccx_is_triggered = true;
		is_trig_success = true;
	} else {
		BB_DIG_DBG(bb, DIG_DBG_LV1, "ifs_clm trigger fail.\n");
	}
#endif
	return is_trig_success;
}

bool halbb_dig_ifs_clm_latch(struct bb_info *bb)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *dig_u = dig->p_cur_dig_unit;
#ifdef HALBB_ENV_MNTR_SUPPORT
	struct env_mntr_rpt rpt = {0};
	u8 ifs_clm_rpt = halbb_env_mntr_result(bb, &rpt) & IFS_CLM_SUCCESS;

	/* get env_mntr_rpt and accumulate */
	if (!dig->ccx_is_triggered) {
		BB_DIG_DBG(bb, DIG_DBG_LV1, "[Latch Err] DIG not trigger.\n");
		return false;
	} else {
		dig->ccx_is_triggered = false;
	}

	if (ifs_clm_rpt == 0) {
		BB_DIG_DBG(bb, DIG_DBG_LV1, "[Latch Err] FA rpt not valid.\n");
		return false;
	}

	if (dig->ccx_timestamp != rpt.ccx_rpt_stamp) {
		BB_DIG_DBG(bb, DIG_DBG_LV1, "[Stamp Err] %d, mine: %d.\n",
			   rpt.ccx_rpt_stamp, dig->ccx_timestamp);
		return false;
	}

	dig_u->fa_r_acc += (rpt.ifs_clm_ofdm_fa_permil + rpt.ifs_clm_cck_fa_permil);
	dig_u->fa_valid_state_cnt++;

	BB_DIG_DBG(bb, DIG_DBG_LV2, "[FA] CCK(%d) + OFDM(%d) = ALL(%d)\n",
		   rpt.ifs_clm_cck_fa_permil, rpt.ifs_clm_ofdm_fa_permil,
		   rpt.ifs_clm_cck_fa_permil + rpt.ifs_clm_ofdm_fa_permil);

	BB_DIG_DBG(bb, DIG_DBG_LV2, "[FA] acc: %d, cnt: %d\n",
		   dig_u->fa_r_acc, dig_u->fa_valid_state_cnt);

#endif
	return true;
}

void halbb_sdagc_follow_pagc_config(struct bb_info *bb, bool set_en)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	const struct bb_dig_cr_info *cr = &bb_dig->bb_dig_cr_i;
	u32 val = (set_en) ? 1 : 0;
	u8 i = 0;

	if (bb_dig->p_cur_dig_unit->sdagc_follow_pagc_en == set_en)
		return;

	if (cr->path0_p20_follow_by_pagcugc_en_a == 0 && cr->path0_p20_follow_by_pagcugc_en_a_m == 0) {
		pr_warn_once("%s: skipped because path0_p20_follow_by_pagcugc_en not defined\n", __func__);
		return;
	}

	bb_dig->p_cur_dig_unit->sdagc_follow_pagc_en = set_en;

	halbb_set_reg_cmn(bb, cr->path0_p20_follow_by_pagcugc_en_a,
			  cr->path0_p20_follow_by_pagcugc_en_a_m, val, bb->bb_phy_idx);
	halbb_set_reg_cmn(bb, cr->path0_s20_follow_by_pagcugc_en_a,
			  cr->path0_s20_follow_by_pagcugc_en_a_m, val, bb->bb_phy_idx);
	halbb_set_reg_cmn(bb, cr->path1_p20_follow_by_pagcugc_en_a,
			  cr->path1_p20_follow_by_pagcugc_en_a_m, val, bb->bb_phy_idx);
	halbb_set_reg_cmn(bb, cr->path1_s20_follow_by_pagcugc_en_a,
			  cr->path1_s20_follow_by_pagcugc_en_a_m, val, bb->bb_phy_idx);

	BB_DIG_DBG(bb, DIG_DBG_LV1, "sdagc_follow_pagc=%d\n", val);
}

void halbb_dyn_pd_th_cck(struct bb_info *bb, u8 rssi, bool set_en)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	const struct bb_dig_cr_info *cr = &bb_dig->bb_dig_cr_i;
	u8 pd_dyn_max = bb_dig->igi_rssi + 5; /* PD_low upper bound */
	u8 margin = bb_dig_u->pd_low_th_ofst; /* backoff of CCA ability */
	u8 phy = bb->bb_phy_idx == HW_PHY_1 ? 1 : 0;
	enum channel_width cbw = bb->hal_com->band[phy].cur_chandef.bw;

	BB_DIG_DBG(bb, DIG_DBG_LV1, "%s ======>\n", __func__);

	rssi = MIN_2(rssi, pd_dyn_max);
	rssi -= MIN_2(rssi, margin);

	if(!set_en) {
		halbb_set_pd_lower_bound_cck(bb, RSSI_MIN, cbw, bb->bb_phy_idx);
		BB_DIG_DBG(bb, DIG_DBG_LV0, "Dynamic CCK PD th dsiabled\n");
	} else {
		if(!halbb_set_pd_lower_bound_cck(bb, RSSI_MAX - rssi, cbw,
		   bb->bb_phy_idx))
			BB_DIG_DBG(bb, DIG_DBG_LV0, "CCK PD th set warning.\n");
		else
			BB_DIG_DBG(bb, DIG_DBG_LV1, "dyn_max=%d, backoff=%d, pd_th=%d(-%ddBm)\n",
				   pd_dyn_max, margin, rssi, RSSI_MAX - rssi);
	}
}

void halbb_dyn_pd_th_ofdm(struct bb_info *bb, u8 rssi, bool set_en)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	const struct bb_dig_cr_info *cr = &bb_dig->bb_dig_cr_i;
	u8 pd_dyn_max = bb_dig->igi_rssi + 5; /* PD_low upper bound */
	u8 margin = bb_dig_u->pd_low_th_ofst; /* backoff of CCA ability */
	u8 phy = bb->bb_phy_idx == HW_PHY_1 ? 1 : 0;
	enum channel_width cbw = bb->hal_com->band[phy].cur_chandef.bw;

	BB_DIG_DBG(bb, DIG_DBG_LV1, "%s ======>\n", __func__);

	rssi = MIN_2(rssi, pd_dyn_max);
	rssi -= MIN_2(rssi, margin);

	if(!set_en) {
		halbb_set_pd_lower_bound(bb, RSSI_MIN, cbw, bb->bb_phy_idx);
		BB_DIG_DBG(bb, DIG_DBG_LV0, "Dynamic PD th dsiabled\n");
	} else {
		if(!halbb_set_pd_lower_bound(bb, RSSI_MAX - rssi, cbw,
		   bb->bb_phy_idx))
			BB_DIG_DBG(bb, DIG_DBG_LV0, "PD th set warning.\n");
		else
			BB_DIG_DBG(bb, DIG_DBG_LV1, "pd_dyn_max=%d, backoff=%d, pd_th_eq_rssi=%d(-%ddBm)\n",
				   pd_dyn_max, margin, rssi, RSSI_MAX - rssi);
	}
}

void halbb_dig_mode_update(struct bb_info *bb, enum dig_op_mode mode)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;

	switch (mode) {
	case DIG_ORIGIN:
	case DIG_SIMPLE:
#ifdef HALBB_DIG_TDMA_SUPPORT
	case DIG_TDMA:
	case DIG_TDMA_ADV:
#endif
		bb_dig->dig_mode = mode;
		break;
	default:
		bb_dig->dig_mode = DIG_ORIGIN;
	}

	BB_DIG_DBG(bb, DIG_DBG_LV0, "Set DIG op mode %d\n", bb_dig->dig_mode);
}

void halbb_dig_gain_para_init(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_cr_info *cr = &bb_dig->bb_dig_cr_i;
	s8 *gain_arr = NULL;
	u32 tmp_val, i = 0;

	if (cr->path0_ib_pkpwr == 0 &&
	    cr->path0_ib_pkpwr_m == 0) {
		pr_warn_once("%s: skipped because ib_pbk not defined\n", __func__);
		return;
	}

	tmp_val = halbb_get_reg_cmn(bb, cr->path0_ib_pkpwr,
				    cr->path0_ib_pkpwr_m, bb->bb_phy_idx);
	bb_dig->ib_pkpwr = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 8);

	bb_dig->ib_pbk = (u8)halbb_get_reg_cmn(bb, cr->path0_ib_pbk,
					       cr->path0_ib_pbk_m,
					       bb->bb_phy_idx);

	/*=== [2G Gain Table] =================*/
	/*LNA*/
	gain_arr = bb_dig->lna_gain_g;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g0_g,
				    cr->path0_lna_err_g0_g_m, bb->bb_phy_idx);
	gain_arr[0] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA0_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g1_g,
				    cr->path0_lna_err_g1_g_m, bb->bb_phy_idx);
	gain_arr[1] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA1_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g2_g,
				    cr->path0_lna_err_g2_g_m, bb->bb_phy_idx);
	gain_arr[2] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA2_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g3_g,
				    cr->path0_lna_err_g3_g_m, bb->bb_phy_idx);
	gain_arr[3] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA3_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g4_g,
				    cr->path0_lna_err_g4_g_m, bb->bb_phy_idx);
	gain_arr[4] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA4_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g5_g,
				    cr->path0_lna_err_g5_g_m, bb->bb_phy_idx);
	gain_arr[5] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA5_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g6_g,
				    cr->path0_lna_err_g6_g_m, bb->bb_phy_idx);
	gain_arr[6] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA6_GAIN;

	/*TIA*/
	gain_arr = bb_dig->tia_gain_g;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_tia_err_g0_g,
				    cr->path0_tia_err_g0_g_m, bb->bb_phy_idx);
	gain_arr[0] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + TIA0_GAIN_G;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_tia_err_g1_g,
				    cr->path0_tia_err_g1_g_m, bb->bb_phy_idx);
	gain_arr[1] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + TIA1_GAIN_G;

	/*=== [5G Gain Table] =================*/
	/*LNA*/
	gain_arr = bb_dig->lna_gain_a;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g0_a,
				    cr->path0_lna_err_g0_a_m, bb->bb_phy_idx);
	gain_arr[0] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA0_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g1_a,
				    cr->path0_lna_err_g1_a_m, bb->bb_phy_idx);
	gain_arr[1] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA1_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g2_a,
				    cr->path0_lna_err_g2_a_m, bb->bb_phy_idx);
	gain_arr[2] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA2_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g3_a,
				    cr->path0_lna_err_g3_a_m, bb->bb_phy_idx);
	gain_arr[3] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA3_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g4_a,
				    cr->path0_lna_err_g4_a_m, bb->bb_phy_idx);
	gain_arr[4] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA4_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g5_a,
				    cr->path0_lna_err_g5_a_m, bb->bb_phy_idx);
	gain_arr[5] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA5_GAIN;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_lna_err_g6_a,
				    cr->path0_lna_err_g6_a_m, bb->bb_phy_idx);
	gain_arr[6] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + LNA6_GAIN;

	/*TIA*/
	gain_arr = bb_dig->tia_gain_a;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_tia_err_g0_a,
				    cr->path0_tia_err_g0_a_m, bb->bb_phy_idx);
	gain_arr[0] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + TIA0_GAIN_A;
	tmp_val = halbb_get_reg_cmn(bb, cr->path0_tia_err_g1_a,
				    cr->path0_tia_err_g1_a_m, bb->bb_phy_idx);
	gain_arr[1] = (s8)halbb_cnvrt_2_sign(tmp_val >> 2, 4) + TIA1_GAIN_A;

	BB_DIG_DBG(bb, DIG_DBG_LV0, "ib_pkpwr=%d, ib_pbk=%d\n",
		   bb_dig->ib_pkpwr, bb_dig->ib_pbk);

	for (i = 0; i < BB_LNA_SIZE; i++)
		BB_DIG_DBG(bb, DIG_DBG_LV0, "lna_gain_g[%d]=%d\n",
			   i, bb_dig->lna_gain_g[i]);
	for (i = 0; i < BB_TIA_SIZE; i++)
		BB_DIG_DBG(bb, DIG_DBG_LV0, "tia_gain_g[%d]=%d\n",
			   i, bb_dig->tia_gain_g[i]);
	for (i = 0; i < BB_LNA_SIZE; i++)
		BB_DIG_DBG(bb, DIG_DBG_LV0, "lna_gain_a[%d]=%d\n",
			   i, bb_dig->lna_gain_a[i]);
	for (i = 0; i < BB_TIA_SIZE; i++)
		BB_DIG_DBG(bb, DIG_DBG_LV0, "tia_gain_a[%d]=%d\n",
			   i, bb_dig->tia_gain_a[i]);

	/*lna initial gain index*/
	bb_dig->max_gaincode.lna_idx = halbb_get_lna_idx(bb, RF_PATH_A);
	bb_dig->max_gaincode.tia_idx = halbb_get_tia_idx(bb, RF_PATH_A);
	bb_dig->max_gaincode.rxb_idx = halbb_get_rxb_idx(bb, RF_PATH_A);

	BB_DIG_DBG(bb, DIG_DBG_LV0, "Read max gaincode = (%d,%d,%2d)\n",
		   bb_dig->max_gaincode.lna_idx, bb_dig->max_gaincode.tia_idx,
		   bb_dig->max_gaincode.rxb_idx);
}


/* fa_cnt 2000/4000/5000/8000 */
static const u16 fa_th_no_link[FA_TH_NUM] = {196, 352, 440, 528};
static const u16 fa_th_linked[FA_TH_NUM] = {4, 8, 12, 16};

void halbb_dig_para_update(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_link_info *bb_link = &bb->bb_link_i;
	struct bb_dig_op_para_unit *para_dst;

	BB_DIG_DBG(bb, DIG_DBG_LV1, "%s ======>\n", __func__);

	/* IGI and PT_low enable control */
	para_dst = &bb_dig->dig_state_h_i.dig_op_para;
	para_dst->dyn_pd_th_en = true;

#ifdef BB_8852A_2_SUPPORT
	if (bb->ic_type == BB_RTL8852A)
		halbb_dig_agc_update_8852a(bb, para_dst);
#endif

	/* fa th update */
	if (!bb->bb_link_i.is_linked)
		halbb_mem_cpy(bb, &para_dst->fa_th, fa_th_no_link,
			      sizeof(u16) * FA_TH_NUM);
	else
		halbb_mem_cpy(bb, &para_dst->fa_th, fa_th_linked,
			      sizeof(u16) * FA_TH_NUM);

	BB_DIG_DBG(bb, DIG_DBG_LV1, "is_linked=%d, fa_th[3:0] = %d,%d,%d,%d\n",
		   bb->bb_link_i.is_linked,
		   para_dst->fa_th[3], para_dst->fa_th[2], para_dst->fa_th[1],
		   para_dst->fa_th[0]);

#ifdef HALBB_DIG_TDMA_SUPPORT
	para_dst = &bb_dig->dig_state_l_i.dig_op_para;
	halbb_mem_cpy(bb, para_dst, &bb_dig->dig_state_h_i.dig_op_para,
		      sizeof(struct bb_dig_op_para_unit));
#endif
}

void halbb_dig_fa_info_update(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;

	/* average from env_mntr_rpt */
	bb_dig_u->fa_r_avg = HALBB_DIV(bb_dig_u->fa_r_acc, bb_dig_u->fa_valid_state_cnt);
	bb_dig_u->fa_r_acc = 0;
}

void halbb_dig_op_unit_para_reset_h(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *unit_cur = &bb_dig->dig_state_h_i;
	u8 i = 0;

	unit_cur->cur_gaincode = bb_dig->max_gaincode;
	unit_cur->force_gaincode = bb_dig->max_gaincode;
	unit_cur->abs_igi_max = IGI_MAX_PERFORMANCE_MODE;
	unit_cur->abs_igi_min = 0xc;
	unit_cur->pd_low_th_ofst = 16;
#ifdef HALBB_DIG_TDMA_SUPPORT
	unit_cur->state_identifier = DIG_TDMA_HIGH;
#endif
}

#ifdef HALBB_DIG_TDMA_SUPPORT
void halbb_dig_op_unit_para_reset_l(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *unit_cur = &bb_dig->dig_state_l_i;
	u8 i = 0;

	unit_cur->cur_gaincode = bb_dig->max_gaincode;
	unit_cur->force_gaincode = bb_dig->max_gaincode;
	unit_cur->abs_igi_max = 0x26;
	unit_cur->abs_igi_min = 0xc;
	unit_cur->pd_low_th_ofst = 16;
	unit_cur->state_identifier = DIG_TDMA_LOW;
}
#endif

void halbb_dig_ifs_clm_para_init(struct bb_info *bb)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;
#ifdef HALBB_ENV_MNTR_SUPPORT
	struct ccx_para_info *para = &dig->ccx_para_i;

	para->rac_lv = RAC_LV_2;
	para->mntr_time = DIG_CCX_WD_TRIGTIME;

	para->clm_app = CLM_DIG;
	para->clm_input_opt = CLM_CCA_S80_S40_S20;

	para->nhm_app = NHM_DIG;
	para->nhm_incld_cca = NHM_EXCLUDE_CCA;

	para->fahm_app = FAHM_DIG;
	para->fahm_numer_opt = FAHM_INCLU_FA;
	para->fahm_denom_opt = FAHM_INCLU_CRC_ERR;

	para->ifs_clm_app = IFS_CLM_DIG;

	para->edcca_clm_app = EDCCA_CLM_DIG;
	para->ccx_edcca_opt_sc_idx = CCX_EDCCA_SEG0_P0;
#endif
	dig->ccx_is_triggered = false;
}

void halbb_dig_para_reset(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;

	bb_dig->pre_dig_mode = bb_dig->dig_mode;
	bb_dig->p_cur_dig_unit = &bb_dig->dig_state_h_i;
	bb_dig->need_update = false;
	halbb_dig_op_unit_para_reset_h(bb); /* dig_op_unit para reset */
#ifdef HALBB_DIG_TDMA_SUPPORT
	halbb_dig_op_unit_para_reset_l(bb); /* dig_op_unit para reset */
	bb_dig->gaincode_update_en = false;
	bb_dig->tdma_passed_time_acc = 0;
	bb_dig->tdma_timestamp_cur = 0;
	bb_dig->tdma_timestamp_pre = bb_dig->tdma_timestamp_cur;
#endif
#ifdef HALBB_ENV_MNTR_SUPPORT
	bb_dig->ccx_timestamp = 0;
	bb_dig->ccx_is_triggered = false;
#endif
}

void halbb_dig_reset(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;

	BB_DIG_DBG(bb, DIG_DBG_LV0, "[%s]=========>\n", __func__);

	halbb_mem_set(bb, &bb_dig->dig_fa_i, 0, sizeof(struct bb_dig_fa_info));
	halbb_dig_para_reset(bb);
#ifdef BB_8852A_2_SUPPORT
	halbb_dig_set_igi_cr_8852a(bb, bb_dig->max_gaincode);
#endif
	halbb_dyn_pd_th_ofdm(bb, IGI_NOLINK, false);
	halbb_dyn_pd_th_cck(bb, IGI_NOLINK, false);
	halbb_sdagc_follow_pagc_config(bb, false);
}

void halbb_dig_init(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	u8 igi_new;

	if(phl_is_mp_mode(bb->phl_com))
		return;

	BB_DIG_DBG(bb, DIG_DBG_LV0, "[%s]=========>\n", __func__);

	/* DIG sub-DM configurations */
	halbb_dig_mode_update(bb, DIG_ORIGIN);
	bb_dig->igi_pause_cnt = 0;
	bb_dig->le_igi_ofst = 0;
	bb_dig->dbg_lv = DIG_DBG_LV2;
	bb_dig->dig_state_h_i.state_num_lmt = 3;
	bb_dig->dig_state_h_i.sdagc_follow_pagc_en = false;
#ifdef HALBB_DIG_TDMA_SUPPORT
	bb_dig->dig_state_l_i.state_num_lmt = 1;
	bb_dig->dig_state_l_i.sdagc_follow_pagc_en = false;
	bb_dig->dig_timer_i.cb_time = 50;
#endif
	halbb_dig_ifs_clm_para_init(bb);
	halbb_dig_gain_para_init(bb);
	halbb_dig_reset(bb);
	bb_dig->dig_state_h_i.igi_fa_rssi = 1; /*init state*/
	halbb_dig_para_update(bb);

#ifdef HALBB_DIG_DAMPING_CHK
	halbb_dig_damping_chk_init(bb);
#endif
	igi_new = halbb_dig_igi_by_ofst(bb, IGI_NOLINK, 0);
	halbb_dig_cfg_bbcr(bb, igi_new);
}

void halbb_dig_deinit(struct bb_info *bb)
{
#ifdef HALBB_DIG_TDMA_SUPPORT
	BB_DBG(bb, DBG_INIT, "halbb_dig_deinit");
#endif
}

bool halbb_dig_abort(struct bb_info *bb)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;

	/* support_ability */
	if (!(bb->support_ability & BB_DIG)) {
		BB_DIG_DBG(bb, DIG_DBG_LV0, "%s ======> DISABLED\n", __func__);
		return true;
	}

	if (bb->pause_ability & BB_DIG) {
		dig->igi_pause_cnt++;
		BB_DIG_DBG(bb, DIG_DBG_LV0, "Return: Pause DIG in LV=%d, cnt=%d\n",
		       bb->pause_lv_table.lv_dig,
		       dig->igi_pause_cnt);

		return true;
	}

	if (dig->igi_pause_cnt) {
		dig->igi_pause_cnt = 0;
		BB_DIG_DBG(bb, DIG_DBG_LV0, "Skip 1 time after pause DIG\n");
		return true;
	}

	return false;
}

void halbb_dig_cfg_bbcr(struct bb_info *bb, u8 igi_new)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = dig->p_cur_dig_unit;
	struct bb_dig_op_unit *dig_u = &dig->dig_state_h_i;
	struct bb_dig_op_para_unit *para = &dig_u->dig_op_para;

	if (igi_new == dig_u->igi_fa_rssi) {
		BB_DIG_DBG(bb, DIG_DBG_LV0, "[IGI][hold_cnt:%d] %d\n", dig->dig_hold_cnt, igi_new);
		dig->dig_hold_cnt++;
		return;
	} else {
		BB_DIG_DBG(bb, DIG_DBG_LV0, "[IGI] %d -> %d\n", dig_u->igi_fa_rssi, igi_new);
		dig->dig_hold_cnt = 0;
	}

	dig_u->igi_fa_rssi = igi_new;

#ifdef BB_8852A_2_SUPPORT
	/* IGI decision */
	if (halbb_dig_gaincode_update_en_8852a(bb))
		halbb_dig_set_igi_cr_8852a(bb, bb_dig_u->cur_gaincode);
#endif

	/* Dynamic PD lower bound */
	halbb_dyn_pd_th_ofdm(bb, igi_new, para->dyn_pd_th_en);

	/* Dynamic CCK PD TH */
	halbb_dyn_pd_th_cck(bb, igi_new, para->dyn_pd_th_en);

	/* Dynamic sync-dagc follow pagc*/
	if (para->dyn_pd_th_en && igi_new > dig->igi_rssi)
		halbb_sdagc_follow_pagc_config(bb, true);
	else
		halbb_sdagc_follow_pagc_config(bb, false);
}

void halbb_dig_new_entry_connect(struct bb_info *bb)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;
	u8 igi_new;
	u8 rssi_min_new = halbb_get_rssi_min(bb);

	BB_DIG_DBG(bb, DIG_DBG_LV0, "%s ======>\n", __func__);
	if (rssi_min_new == 0)
		return;

	BB_DIG_DBG(bb, DIG_DBG_LV0, "rssi_min_new=%d\n", rssi_min_new);
	/* Update igi_rssi */
	dig->igi_rssi = rssi_min_new >> 1;
	igi_new = halbb_dig_igi_by_ofst(bb, dig->igi_rssi, 0);
	halbb_dig_cfg_bbcr(bb, igi_new);
	/*Update EDCCA threshold*/
	halbb_edcca_thre_calc(bb);
}

void halbb_dig_lps(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	struct bb_link_info *bb_link = &bb->bb_link_i;
	s16 final_rssi = 0;

	BB_DIG_DBG(bb, DIG_DBG_LV0, "%s ======>\n", __func__);

	/* Update igi_rssi */
	bb_dig->igi_rssi = (bb_link->is_linked) ? (bb->bb_ch_i.rssi_min >> 1) : IGI_NOLINK;

	final_rssi = MIN_2(bb_dig->igi_rssi + bb_dig->le_igi_ofst, RSSI_MAX);
	final_rssi = SUBTRACT_TO_0(final_rssi, 10);

	BB_DIG_DBG(bb, DIG_DBG_LV0, "rssi=%03d, le_ofst=(%03d)\n",
		   bb_dig->igi_rssi, bb_dig->le_igi_ofst);

	halbb_dig_cfg_bbcr(bb, (u8)final_rssi);
}

void halbb_dig(struct bb_info *bb)
{
	struct bb_dig_info *dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *dig_u = &dig->dig_state_h_i;
	struct bb_dig_op_para_unit *para = &dig_u->dig_op_para;
	struct bb_link_info *bb_link = &bb->bb_link_i;
	u16 fa_avg;
	u8 igi_new, igi_pre = dig_u->igi_fa_rssi;
	s8 ofst;

	BB_DIG_DBG(bb, DIG_DBG_LV0, "%s ======>\n", __func__);

	dig->need_update |= (bb_link->first_connect | bb_link->first_disconnect);

	if (halbb_dig_abort(bb))
		return;

	/* Update igi_rssi */
	dig->igi_rssi = (bb_link->is_linked) ? (bb->bb_ch_i.rssi_min >> 1) : IGI_NOLINK;
	BB_DIG_DBG(bb, DIG_DBG_LV0, "link=%d, rssi=%d\n", bb_link->is_linked, dig->igi_rssi);

	if (dig->need_update) {
		halbb_dig_para_update(bb);
		#ifdef HALBB_DIG_DAMPING_CHK
		halbb_dig_recorder_reset(bb);
		#endif

		BB_DIG_DBG(bb, DIG_DBG_LV0, "Connect/Disconnect\n");

		igi_new = halbb_dig_igi_by_ofst(bb, dig->igi_rssi, 0);
		halbb_dig_cfg_bbcr(bb, igi_new);
		dig->need_update = false;
		return;
	}

#ifdef HALBB_DIG_TDMA_SUPPORT
	if (dig->dig_mode == DIG_TDMA && bb_link->is_linked) {
		halbb_dig_timercheck_watchdog(bb);
		return;
	}

	dig->p_cur_dig_unit = &dig->dig_state_h_i;
#endif

	if (dig->dig_mode == DIG_SIMPLE) {
		halbb_dig_lps(bb);
		return;
	}

	/* FA info handling */
	if (!halbb_dig_ifs_clm_latch(bb)) {
		BB_DIG_DBG(bb, DIG_DBG_LV0, "IFS CLM Get Rpt Fail\n");
		goto DIG_END;
	}

	fa_avg = HALBB_DIV(dig_u->fa_r_acc, dig_u->fa_valid_state_cnt);
	dig_u->fa_r_acc = 0;
	dig_u->fa_valid_state_cnt = 0;

#ifdef HALBB_DIG_DAMPING_CHK
	/*Record IGI History*/
	halbb_dig_recorder(bb, igi_pre, fa_avg);
	/*DIG Damping Check*/
	halbb_dig_damping_chk(bb);
#endif
	ofst = halbb_dig_ofst_by_fa(bb, fa_avg);
	igi_new = halbb_dig_igi_by_ofst(bb, igi_pre, ofst);
	halbb_dig_cfg_bbcr(bb, igi_new);

DIG_END:
	if (!halbb_dig_ifs_clm_trig(bb, DIG_CCX_WD_TRIGTIME))
		BB_DIG_DBG(bb, DIG_DBG_LV0, "IFS CLM Trig Fail\n");
}

#ifdef HALBB_DIG_TDMA_SUPPORT
void halbb_tdma_dig(struct bb_info *bb) {
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	bool ifs_clm_op_status = false;
	bool igi_update_en_h = false, igi_update_en_l = false;

	bb_dig->tdma_timestamp_cur++;
	bb_dig->tdma_passed_time_acc += (u16)bb_dig->dig_timer_i.cb_time;

	BB_DIG_DBG(bb, DIG_DBG_LV2, "[IN]state_cnt=%d, state_lmt=%d\n",
		   bb_dig_u->passed_state_cnt, bb_dig_u->state_num_lmt);

	/* FA info handling */
	ifs_clm_op_status = halbb_dig_ifs_clm_latch(bb);

	/* Two seconds periodic procedure */
	if (bb_dig->tdma_passed_time_acc >= WACHDOG_PERIOD_IN_MS) {
		BB_DIG_DBG(bb, DIG_DBG_LV0, "Two seconds reached.\n");

		BB_DIG_DBG(bb, DIG_DBG_LV0, "[TDMA-H]============>\n");
		bb_dig->p_cur_dig_unit = &bb_dig->dig_state_h_i;
		/* FA info handling */
		halbb_dig_fa_info_update(bb);
		/* Noisy level decision */
		halbb_dig_noisy_lv_decision(bb);
		halbb_dig_igi_ofst_by_env(bb);
		/* IGI and boundary decision */
		bb_dig_u->igi_fa_rssi = halbb_dig_igi_bound_decision(bb);
#ifdef BB_8852A_2_SUPPORT
		/* IGI decision */
		igi_update_en_h = halbb_dig_gaincode_update_en_8852a(bb);
#endif

		BB_DIG_DBG(bb, DIG_DBG_LV0, "[TDMA-L]============>\n");
		bb_dig->p_cur_dig_unit = &bb_dig->dig_state_l_i;
		/* FA info handling */
		halbb_dig_fa_info_update(bb);
		/* Noisy level decision */
		halbb_dig_noisy_lv_decision(bb);
		halbb_dig_igi_ofst_by_env(bb);
		/* IGI and boundary decision */
		bb_dig_u->igi_fa_rssi = halbb_dig_igi_bound_decision(bb);
#ifdef BB_8852A_2_SUPPORT
		/* IGI decision */
		igi_update_en_l = halbb_dig_gaincode_update_en_8852a(bb);
#endif
		bb_dig->gaincode_update_en = igi_update_en_h | igi_update_en_l;
		bb_dig->p_cur_dig_unit = bb_dig_u;
		bb_dig->tdma_passed_time_acc = 0;
	}

	/* TDMA state transition */
	if (++bb_dig_u->passed_state_cnt >= bb_dig_u->state_num_lmt) {
		BB_DIG_DBG(bb, DIG_DBG_LV2, "[OUT]state_cnt=%d, state_lmt=%d\n",
			   bb_dig_u->passed_state_cnt,
			   bb_dig_u->state_num_lmt);
		bb_dig_u->passed_state_cnt = 0;
		switch (bb_dig_u->state_identifier) {
		case DIG_TDMA_LOW:
			bb_dig->p_cur_dig_unit = &bb_dig->dig_state_h_i;
			BB_DIG_DBG(bb, DIG_DBG_LV1, "[TDMA-L]->[TDMA-H].\n");
			break;
		case DIG_TDMA_HIGH:
			bb_dig->p_cur_dig_unit = &bb_dig->dig_state_l_i;
			BB_DIG_DBG(bb, DIG_DBG_LV1, "[TDMA-H]->[TDMA-L].\n");
			break;
		default:
			break;
		}
		bb_dig_u = bb_dig->p_cur_dig_unit;
#ifdef BB_8852A_2_SUPPORT
		/* To set lna, tia, rxbb index */
		if (bb_dig->gaincode_update_en)
			halbb_dig_set_igi_cr_8852a(bb, bb_dig_u->cur_gaincode);
#endif
		/* Dynamic PD lower bound */
		halbb_dyn_pd_th_ofdm(bb, bb_dig_u->igi_fa_rssi,
				     bb_dig_u->dig_op_para.dyn_pd_th_en);

		/* Dynamic CCK PD TH */
		halbb_dyn_pd_th_cck(bb, bb_dig_u->igi_fa_rssi,
				    bb_dig_u->dig_op_para.dyn_pd_th_en);

		/* Dynamic sync-dagc follow pagc*/
		if (bb_dig_u->dig_op_para.dyn_pd_th_en &&
		    (bb_dig_u->igi_fa_rssi > bb_dig->igi_rssi))
			halbb_sdagc_follow_pagc_config(bb, true);
		else
			halbb_sdagc_follow_pagc_config(bb, false);
	}

	ifs_clm_op_status = halbb_dig_ifs_clm_trig(bb, (u16)bb_dig->dig_timer_i.cb_time);
}

void halbb_dig_timercheck_watchdog(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;

	if (bb_dig->tdma_timestamp_cur == bb_dig->tdma_timestamp_pre) {
		BB_DIG_DBG(bb, DIG_DBG_LV0, "DIG TDMA timer check FAIL. Restart.\n");
		halbb_dig_reset(bb);
		halbb_cfg_timers(bb, BB_SET_TIMER, &bb->bb_dig_i.dig_timer_i);
	}
	bb_dig->tdma_timestamp_pre = bb_dig->tdma_timestamp_cur;
}

void halbb_tdmadig_io_en(struct bb_info *bb)
{
	struct bb_link_info *bb_link = &bb->bb_link_i;

	if (halbb_dig_abort(bb)) {
		return;
	}

	if (!bb_link->is_linked) {
		BB_DIG_DBG(bb, DIG_DBG_LV0, "is_linked=%d, one_entry_only=%d\n",
			   bb_link->is_linked, bb_link->is_one_entry_only);
		return;
	}

	if ((bb->bb_dig_i.dig_mode != DIG_TDMA) &&
	    (bb->bb_dig_i.dig_mode != DIG_TDMA_ADV))
	    return;

	halbb_tdma_dig(bb);
	halbb_cfg_timers(bb, BB_SET_TIMER, &bb->bb_dig_i.dig_timer_i);
}

void halbb_tdmadig_callback(void *context)
{
	struct bb_info *bb = (struct bb_info *)context;
	struct halbb_timer_info *timer = &bb->bb_dig_i.dig_timer_i;

	BB_DIG_DBG(bb, DIG_DBG_LV0, "[%s]===>\n", __func__);

	timer->timer_state = BB_TIMER_IDLE;

	if (bb->phl_com->hci_type == RTW_HCI_PCIE)
		halbb_tdmadig_io_en(bb);
	else
		rtw_hal_cmd_notify(bb->phl_com, MSG_EVT_NOTIFY_BB, (void *)(&timer->event_idx), bb->bb_phy_idx);
}

void halbb_dig_timer_init(struct bb_info *bb)
{
	struct halbb_timer_info *timer = &bb->bb_dig_i.dig_timer_i;

	BB_DBG(bb, DBG_DIG, "[%s]\n", __func__);

	timer->event_idx = BB_EVENT_TIMER_DIG;
	timer->timer_state = BB_TIMER_IDLE;

	halbb_init_timer(bb, &timer->timer_list, halbb_tdmadig_callback, bb, "halbb_dig_timer");
}

#endif /*#ifdef HALBB_DIG_TDMA_SUPPORT*/

void halbb_set_dig_pause_val(struct bb_info *bb, u32 *buf, u8 val_len)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *dig_u = bb_dig->p_cur_dig_unit;
	struct agc_gaincode_set gaincode = bb_dig->max_gaincode;
	u8 phy = bb->bb_phy_idx == HW_PHY_1 ? 1 : 0;
	enum channel_width cbw = bb->hal_com->band[phy].cur_chandef.bw;
	u8 target_pwr, margin = dig_u->pd_low_th_ofst;

	if (val_len != DIG_PAUSE_INFO_SIZE) {
		BB_DIG_DBG(bb, DIG_DBG_LV0, "[Error][DIG]Need val_len=%d\n",
			   DIG_PAUSE_INFO_SIZE);
		return;
	}
	BB_DIG_DBG(bb, DIG_DBG_LV0, "[%s] Pd=-%d dB\n", __func__, buf[0]);

#ifdef BB_8852A_2_SUPPORT
	/* write igi or keep max gaincode */
	if (bb->ic_type == BB_RTL8852A) {
		if ((buf[1] == PAUSE_OFDM_CCK) && (bb->hal_com->cv < CCV)) {
			BB_DIG_DBG(bb, DIG_DBG_LV0, "[52A] igi_en=1\n");
			halbb_gaincode_by_rssi_8852a(bb, &gaincode, RSSI_MAX - (u8)buf[0]);
		}
		halbb_dig_set_igi_cr_8852a(bb, gaincode);
	}
#endif

	/* write pd lower bound anyway */
	target_pwr = MIN_2((u8)buf[0] + margin, RSSI_MAX);
	halbb_set_pd_lower_bound(bb, target_pwr, cbw, bb->bb_phy_idx);
	if (buf[1] == PAUSE_OFDM)
		target_pwr = 0;
	halbb_set_pd_lower_bound_cck(bb, target_pwr, cbw, bb->bb_phy_idx);
}

void* halbb_get_dig_fa_statistic(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;

	return &bb_dig->dig_fa_i;
}

void halbb_dig_dbg(struct bb_info *bb, char input[][16], u32 *_used,
		   char *output, u32 *_out_len)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = &bb_dig->dig_state_h_i;
	struct agc_gaincode_set set_tmp;
	u32 var[10] = {0};
	u8 i = 0;

	if (_os_strcmp(input[1], "-h") == 0) {
#ifdef HALBB_DIG_TDMA_SUPPORT
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "DIG-H state\n");
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{0} {dig op mode = %d(0:DIG,1:TDMA,2:A-TDMA,3:low IO)}\n",
			    bb_dig->dig_mode);
#else
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{0} {dig op mode = %d(0:DIG,3:low IO)}\n",
			    bb_dig->dig_mode);
#endif
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{1} {fix_lna = %d} {fix_tia = %d} {fix_rxb = %d}\n",
			    bb_dig_u->force_gaincode.lna_idx,
			    bb_dig_u->force_gaincode.tia_idx,
			    bb_dig_u->force_gaincode.rxb_idx);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{2: get current IGI} {path(0/1)}\n");
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{3: show rssi threshold of IGI}\n");
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{4: modify rssi threshold} {TH idx(0-4)} {value}\n");
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{5: show fa ratio vs. noisy level.}\n");
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{6: modify fa ratio threshold} {TH idx(0-3)} {value}\n");
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{7: dyn PD low bound en = %d} {0:disable, 1:enable}\n",
			    bb_dig_u->dig_op_para.dyn_pd_th_en);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{8: dyn PD low bound backoff = %d} {value}\n",
			    bb_dig_u->pd_low_th_ofst);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{9: reset rssi, fa_ratio TH}\n");
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{10: show AGC table}\n");
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{11: Update gain parameters}\n");
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{12: simple mode IGI offset = (%d)} {0:-, 1:+} {val}\n",
			    bb_dig->le_igi_ofst);
#ifdef HALBB_DIG_TDMA_SUPPORT
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{13: tdma timer = %d ms} {val(ms)}\n",
			    bb_dig->dig_timer_i.cb_time);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{14: state limit (L,H) = (%d,%d)} {0:L,1:H} {state num}\n",
			    bb_dig->dig_state_l_i.state_num_lmt,
			    bb_dig->dig_state_h_i.state_num_lmt);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{15} {0:L,1:H} {fix_lna = %d} {fix_tia = %d} {fix_rxb = %d}\n",
			    bb_dig_u->force_gaincode.lna_idx,
			    bb_dig_u->force_gaincode.tia_idx,
			    bb_dig_u->force_gaincode.rxb_idx);
#endif
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "{20: dbg level = %d} {0/1/2}\n",
			    bb_dig->dbg_lv);
#ifdef HALBB_DIG_DAMPING_CHK
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "damping en {val}\n");
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "damping th {s(8,1)}\n");
#endif
		return;
	}

#ifdef HALBB_DIG_DAMPING_CHK
	if (_os_strcmp(input[1], "damping") == 0) {
		HALBB_SCAN(input[3], DCMD_DECIMAL, &var[0]);
		if (_os_strcmp(input[2], "en") == 0) {
			bb_dig->dig_dl_en = (bool)var[0];

			if (!bb_dig->dig_dl_en)
				halbb_dig_recorder_reset(bb);

			BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
				    "dig_dl_en = %d\n", bb_dig->dig_dl_en);
		} else if (_os_strcmp(input[2], "th") == 0) {
			bb_dig->rls_rssi_diff_th = (u8)var[0];
			BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
				    "rls_rssi_diff_th = %d.%d\n",
				    var[0] >> 1, (var[0] & 1) * 5);
		}
		return;
	}
#endif

	HALBB_SCAN(input[1], DCMD_DECIMAL, &var[0]);
	if (var[0] == 0) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		halbb_dig_mode_update(bb, (enum dig_op_mode)var[1]);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "Set DIG op mode = %d\n", bb_dig->dig_mode);
	} else if (var[0] == 1) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		HALBB_SCAN(input[3], DCMD_DECIMAL, &var[2]);
		HALBB_SCAN(input[4], DCMD_DECIMAL, &var[3]);

		bb_dig_u->force_gaincode.lna_idx = (u8)var[1];
		bb_dig_u->force_gaincode.tia_idx = (u8)var[2];
		bb_dig_u->force_gaincode.rxb_idx = (u8)var[3];

		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			 "IGI: fix(lna,tia,rxb)=(%d,%d,%d)\n",
			 bb_dig_u->force_gaincode.lna_idx,
			 bb_dig_u->force_gaincode.tia_idx,
			 bb_dig_u->force_gaincode.rxb_idx);
#ifdef BB_8852A_2_SUPPORT
		halbb_dig_set_igi_cr_8852a(bb, bb_dig_u->force_gaincode);
#endif
	} else if (var[0] == 2) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			 "current(lna,tia,rxb)=((%d,%d,%d))\n",
			 halbb_get_lna_idx(bb,(enum rf_path)var[1]),
			 halbb_get_tia_idx(bb,(enum rf_path)var[1]),
			 halbb_get_rxb_idx(bb,(enum rf_path)var[1]));
	} else if (var[0] == 3) {
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "rssi TH: -----%03d-----%03d-----%03d-----%03d-----%03d-----\n",
			    bb_dig_u->dig_op_para.igi_rssi_th[0],
			    bb_dig_u->dig_op_para.igi_rssi_th[1],
			    bb_dig_u->dig_op_para.igi_rssi_th[2],
			    bb_dig_u->dig_op_para.igi_rssi_th[3],
			    bb_dig_u->dig_op_para.igi_rssi_th[4]);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "lna idx: --%1d--|||--%1d--|||--%1d--|||--%1d--|||--%1d--|||--%1d--\n",
			    6,5,4,3,2,1);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "tia idx: --%1d--|||--%1d--|||--%1d--|||--%1d--|||--%1d--|||--%1d--\n",
			    1,0,0,0,0,0);
	} else if (var[0] == 4) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		HALBB_SCAN(input[3], DCMD_DECIMAL, &var[2]);
		if (var[1] < 5) {
			bb_dig_u->dig_op_para.igi_rssi_th[var[1]] = (u8)var[2];
			BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "Set rssi_TH[%d]=%d\n", var[1],
			    bb_dig_u->dig_op_para.igi_rssi_th[var[1]]);
		}
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "rssi TH: -----%03d-----%03d-----%03d-----%03d-----%03d-----\n",
			    bb_dig_u->dig_op_para.igi_rssi_th[0],
			    bb_dig_u->dig_op_para.igi_rssi_th[1],
			    bb_dig_u->dig_op_para.igi_rssi_th[2],
			    bb_dig_u->dig_op_para.igi_rssi_th[3],
			    bb_dig_u->dig_op_para.igi_rssi_th[4]);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "lna idx: --%1d--|||--%1d--|||--%1d--|||--%1d--|||--%1d--|||--%1d--\n",
			    6,5,4,3,2,1);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "tia idx: --%1d--|||--%1d--|||--%1d--|||--%1d--|||--%1d--|||--%1d--\n",
			    1,0,0,0,0,0);
	} else if (var[0] == 5) {
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "fa ratio TH: -----%03d-----%03d-----%03d-----%03d-----\n",
			    bb_dig_u->dig_op_para.fa_th[0],
			    bb_dig_u->dig_op_para.fa_th[1],
			    bb_dig_u->dig_op_para.fa_th[2],
			    bb_dig_u->dig_op_para.fa_th[3]);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "noisy level: --%1d--|||--%1d--|||--%1d--|||--%1d--|||-%s-\n",
			    0,1,2,3,"MAX");
	} else if (var[0] == 6) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		HALBB_SCAN(input[3], DCMD_DECIMAL, &var[2]);
		if (var[1] < 4) {
			bb_dig_u->dig_op_para.fa_th[var[1]] = (u16)var[2];
			BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "Set FA ratio TH[%d]=%d\n", var[1],
			    bb_dig_u->dig_op_para.fa_th[var[1]]);
		}
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "fa ratio TH: -----%03d-----%03d-----%03d-----%03d-----\n",
			    bb_dig_u->dig_op_para.fa_th[0],
			    bb_dig_u->dig_op_para.fa_th[1],
			    bb_dig_u->dig_op_para.fa_th[2],
			    bb_dig_u->dig_op_para.fa_th[3]);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "noisy level: --%1d--|||--%1d--|||--%1d--|||--%1d--|||-%s-\n",
			    0,1,2,3,"MAX");
	} else if (var[0] == 7) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		bb_dig_u->dig_op_para.dyn_pd_th_en = (bool)var[1];
		if (bb_dig_u->dig_op_para.dyn_pd_th_en)
			BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
				    "Enabled dyn PD low bound\n");
		else
			BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
				    "Disabled dyn PD low bound\n");
	} else if (var[0] == 8) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		bb_dig_u->pd_low_th_ofst = (u8)var[1];
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "Set dyn PD low bound backoff=%d\n",
			    bb_dig_u->pd_low_th_ofst);
	} else if (var[0] == 9) {
		halbb_dig_reset(bb);
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "Reset state machine parameters\n");
#ifdef BB_8852A_2_SUPPORT
	} else if (var[0] == 10) {
		for (i = RSSI_MIN; i <= RSSI_MAX; i++)
			halbb_gaincode_by_rssi_8852a(bb, &set_tmp, i);
#endif
	} else if (var[0] == 11) {
		halbb_dig_gain_para_init(bb);
	} else if (var[0] == 12) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		HALBB_SCAN(input[3], DCMD_DECIMAL, &var[2]);
		if (var[1] == 0)
			bb_dig->le_igi_ofst = -(s8)var[2];
		else if (var[1] == 1)
			bb_dig->le_igi_ofst = (s8)var[2];
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
		    "simple mode IGI offset set to (%d)\n",
		    bb_dig->le_igi_ofst);
#ifdef HALBB_DIG_TDMA_SUPPORT
	} else if (var[0] == 13) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
			bb_dig->dig_timer_i.cb_time = (u16)var[1];
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
		    "tdma timer set to %d ms\n",
		    bb_dig->dig_timer_i.cb_time);
	} else if (var[0] == 14) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		HALBB_SCAN(input[3], DCMD_DECIMAL, &var[2]);
		if (var[1] == 0)
			bb_dig_u = &bb_dig->dig_state_l_i;
		else if (var[1] == 1)
			bb_dig_u = &bb_dig->dig_state_h_i;
		bb_dig_u->state_num_lmt = (u8)var[2];
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "set TDMA-%d state limit to %d\n",
			    bb_dig_u->state_identifier,
			    bb_dig_u->state_num_lmt);
	} else if (var[0] == 15) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		HALBB_SCAN(input[3], DCMD_DECIMAL, &var[2]);
		HALBB_SCAN(input[4], DCMD_DECIMAL, &var[3]);
		HALBB_SCAN(input[5], DCMD_DECIMAL, &var[4]);
		HALBB_SCAN(input[6], DCMD_DECIMAL, &var[5]);
		if (var[1] == 0)
			bb_dig_u = &bb_dig->dig_state_l_i;
		else if (var[1] == 1)
			bb_dig_u = &bb_dig->dig_state_h_i;

		bb_dig_u->force_gaincode.lna_idx = (u8)var[2];
		bb_dig_u->force_gaincode.tia_idx = (u8)var[3];
		bb_dig_u->force_gaincode.rxb_idx = (u8)var[4];

		bb_dig_u = &bb_dig->dig_state_l_i;
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			 "[TDMA-L]IGI: fix(lna,tia,rxb)=(%d,%d,%d)\n",
			 bb_dig_u->force_gaincode.lna_idx,
			 bb_dig_u->force_gaincode.tia_idx,
			 bb_dig_u->force_gaincode.rxb_idx);
		bb_dig_u = &bb_dig->dig_state_h_i;
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			 "[TDMA-H]IGI: fix(lna,tia,rxb)=(%d,%d,%d)\n",
			 bb_dig_u->force_gaincode.lna_idx,
			 bb_dig_u->force_gaincode.tia_idx,
			 bb_dig_u->force_gaincode.rxb_idx);
#endif
	} else if (var[0] == 20) {
		HALBB_SCAN(input[2], DCMD_DECIMAL, &var[1]);
		if ((enum dig_dbg_level)var[1] <= DIG_DBG_LV2)
			bb_dig->dbg_lv = (enum dig_dbg_level)var[1];
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
		    "dbg level set to lv%d\n",
		    bb_dig->dbg_lv);
	} else {
		BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used,
			    "Set Err\n");
	}
}

void halbb_cr_cfg_dig_init(struct bb_info *bb)
{
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_cr_info *cr = &bb_dig->bb_dig_cr_i;

	switch (bb->cr_type) {
#ifdef BB_8852A_CAV_SUPPORT
	case BB_52AA:
		/*cr->path0_ib_pbk = PATH0_R_IB_PBK_52AA;
		 *cr->path0_ib_pbk_m = PATH0_R_IB_PBK_52AA_M;
		 *cr->path0_ib_pkpwr = PATH0_R_IB_PKPW_52AA;
		 *cr->path0_ib_pkpwr_m = PATH0_R_IB_PKPW_52AA_M;
		 *cr->path1_ib_pbk = PATH1_R_IB_PBK_52AA;
		 *cr->path1_ib_pbk_m = PATH1_R_IB_PBK_52AA_M;
		 *cr->path1_ib_pkpwr = PATH1_R_IB_PKPW_52AA;
		 *cr->path1_ib_pkpwr_m = PATH1_R_IB_PKPW_52AA_M;
		 */
		cr->path0_lna_init_idx = PATH0_R_LNA_INIT_IDX_52AA;
		cr->path0_lna_init_idx_m = PATH0_R_LNA_INIT_IDX_52AA_M;
		cr->path1_lna_init_idx = PATH0_R_LNA_INIT_IDX_52AA;
		cr->path1_lna_init_idx_m = PATH0_R_LNA_INIT_IDX_52AA_M;
		cr->path0_tia_init_idx = PATH0_R_TIA_INIT_IDX_52AA;
		cr->path0_tia_init_idx_m = PATH0_R_TIA_INIT_IDX_52AA_M;
		cr->path1_tia_init_idx = PATH0_R_TIA_INIT_IDX_52AA;
		cr->path1_tia_init_idx_m = PATH0_R_TIA_INIT_IDX_52AA_M;
		cr->path0_rxb_init_idx = PATH0_R_RXB_INIT_IDX_52AA;
		cr->path0_rxb_init_idx_m = PATH0_R_RXB_INIT_IDX_52AA_M;
		cr->path1_rxb_init_idx = PATH0_R_RXB_INIT_IDX_52AA;
		cr->path1_rxb_init_idx_m = PATH0_R_RXB_INIT_IDX_52AA_M;
		/*cr->seg0r_pd_spatial_reuse_en_a = SEG0R_PD_SPATIAL_REUSE_EN_52AA;
		 *cr->seg0r_pd_spatial_reuse_en_a_m = SEG0R_PD_SPATIAL_REUSE_EN_52AA_M;
		 *cr->seg0r_pd_lower_bound_a = SEG0R_PD_LOWER_BOUND_52AA;
		 *cr->seg0r_pd_lower_bound_a_m = SEG0R_PD_LOWER_BOUND_52AA_M;
		 *cr->path0_p20_follow_by_pagcugc_en_a = PATH0_P20_R_FOLLOW_BY_PAGCUGC_EN_52AA;
		 *cr->path0_p20_follow_by_pagcugc_en_a_m = PATH0_P20_R_FOLLOW_BY_PAGCUGC_EN_52AA_M;
		 *cr->path0_s20_follow_by_pagcugc_en_a = PATH0_S20_R_FOLLOW_BY_PAGCUGC_EN_52AA;
		 *cr->path0_s20_follow_by_pagcugc_en_a_m = PATH0_S20_R_FOLLOW_BY_PAGCUGC_EN_52AA_M;
		 *cr->path1_p20_follow_by_pagcugc_en_a = PATH1_P20_R_FOLLOW_BY_PAGCUGC_EN_52AA;
		 *cr->path1_p20_follow_by_pagcugc_en_a_m = PATH1_P20_R_FOLLOW_BY_PAGCUGC_EN_52AA_M;
		 *cr->path1_s20_follow_by_pagcugc_en_a = PATH1_S20_R_FOLLOW_BY_PAGCUGC_EN_52AA;
		 *cr->path1_s20_follow_by_pagcugc_en_a_m = PATH1_S20_R_FOLLOW_BY_PAGCUGC_EN_52AA_M;
		 *cr->path0_lna_err_g0_a = PATH0_R_LNA_ERR_G0_A_52AA;
		 *cr->path0_lna_err_g0_a_m = PATH0_R_LNA_ERR_G0_A_52AA_M;
		 *cr->path0_lna_err_g0_g = PATH0_R_LNA_ERR_G0_G_52AA;
		 *cr->path0_lna_err_g0_g_m = PATH0_R_LNA_ERR_G0_G_52AA_M;
		 *cr->path0_lna_err_g1_a = PATH0_R_LNA_ERR_G1_A_52AA;
		 *cr->path0_lna_err_g1_a_m = PATH0_R_LNA_ERR_G1_A_52AA_M;
		 *cr->path0_lna_err_g1_g = PATH0_R_LNA_ERR_G1_G_52AA;
		 *cr->path0_lna_err_g1_g_m = PATH0_R_LNA_ERR_G1_G_52AA_M;
		 *cr->path0_lna_err_g2_a = PATH0_R_LNA_ERR_G2_A_52AA;
		 *cr->path0_lna_err_g2_a_m = PATH0_R_LNA_ERR_G2_A_52AA_M;
		 *cr->path0_lna_err_g2_g = PATH0_R_LNA_ERR_G2_G_52AA;
		 *cr->path0_lna_err_g2_g_m = PATH0_R_LNA_ERR_G2_G_52AA_M;
		 *cr->path0_lna_err_g3_a = PATH0_R_LNA_ERR_G3_A_52AA;
		 *cr->path0_lna_err_g3_a_m = PATH0_R_LNA_ERR_G3_A_52AA_M;
		 *cr->path0_lna_err_g3_g = PATH0_R_LNA_ERR_G3_G_52AA;
		 *cr->path0_lna_err_g3_g_m = PATH0_R_LNA_ERR_G3_G_52AA_M;
		 *cr->path0_lna_err_g4_a = PATH0_R_LNA_ERR_G4_A_52AA;
		 *cr->path0_lna_err_g4_a_m = PATH0_R_LNA_ERR_G4_A_52AA_M;
		 *cr->path0_lna_err_g4_g = PATH0_R_LNA_ERR_G4_G_52AA;
		 *cr->path0_lna_err_g4_g_m = PATH0_R_LNA_ERR_G4_G_52AA_M;
		 *cr->path0_lna_err_g5_a = PATH0_R_LNA_ERR_G5_A_52AA;
		 *cr->path0_lna_err_g5_a_m = PATH0_R_LNA_ERR_G5_A_52AA_M;
		 *cr->path0_lna_err_g5_g = PATH0_R_LNA_ERR_G5_G_52AA;
		 *cr->path0_lna_err_g5_g_m = PATH0_R_LNA_ERR_G5_G_52AA_M;
		 *cr->path0_lna_err_g6_a = PATH0_R_LNA_ERR_G6_A_52AA;
		 *cr->path0_lna_err_g6_a_m = PATH0_R_LNA_ERR_G6_A_52AA_M;
		 *cr->path0_lna_err_g6_g = PATH0_R_LNA_ERR_G6_G_52AA;
		 *cr->path0_lna_err_g6_g_m = PATH0_R_LNA_ERR_G6_G_52AA_M;
		 *cr->path0_tia_err_g0_a = PATH0_R_TIA_ERR_G0_A_52AA;
		 *cr->path0_tia_err_g0_a_m = PATH0_R_TIA_ERR_G0_A_52AA_M;
		 *cr->path0_tia_err_g0_g = PATH0_R_TIA_ERR_G0_G_52AA;
		 *cr->path0_tia_err_g0_g_m = PATH0_R_TIA_ERR_G0_G_52AA_M;
		 *cr->path0_tia_err_g1_a = PATH0_R_TIA_ERR_G1_A_52AA;
		 *cr->path0_tia_err_g1_a_m = PATH0_R_TIA_ERR_G1_A_52AA_M;
		 *cr->path0_tia_err_g1_g = PATH0_R_TIA_ERR_G1_G_52AA;
		 *cr->path0_tia_err_g1_g_m = PATH0_R_TIA_ERR_G1_G_52AA_M;
		 *cr->path1_lna_err_g0_a = PATH1_R_LNA_ERR_G0_A_52AA;
		 *cr->path1_lna_err_g0_a_m = PATH1_R_LNA_ERR_G0_A_52AA_M;
		 *cr->path1_lna_err_g0_g = PATH1_R_LNA_ERR_G0_G_52AA;
		 *cr->path1_lna_err_g0_g_m = PATH1_R_LNA_ERR_G0_G_52AA_M;
		 *cr->path1_lna_err_g1_a = PATH1_R_LNA_ERR_G1_A_52AA;
		 *cr->path1_lna_err_g1_a_m = PATH1_R_LNA_ERR_G1_A_52AA_M;
		 *cr->path1_lna_err_g1_g = PATH1_R_LNA_ERR_G1_G_52AA;
		 *cr->path1_lna_err_g1_g_m = PATH1_R_LNA_ERR_G1_G_52AA_M;
		 *cr->path1_lna_err_g2_a = PATH1_R_LNA_ERR_G2_A_52AA;
		 *cr->path1_lna_err_g2_a_m = PATH1_R_LNA_ERR_G2_A_52AA_M;
		 *cr->path1_lna_err_g2_g = PATH1_R_LNA_ERR_G2_G_52AA;
		 *cr->path1_lna_err_g2_g_m = PATH1_R_LNA_ERR_G2_G_52AA_M;
		 *cr->path1_lna_err_g3_a = PATH1_R_LNA_ERR_G3_A_52AA;
		 *cr->path1_lna_err_g3_a_m = PATH1_R_LNA_ERR_G3_A_52AA_M;
		 *cr->path1_lna_err_g3_g = PATH1_R_LNA_ERR_G3_G_52AA;
		 *cr->path1_lna_err_g3_g_m = PATH1_R_LNA_ERR_G3_G_52AA_M;
		 *cr->path1_lna_err_g4_a = PATH1_R_LNA_ERR_G4_A_52AA;
		 *cr->path1_lna_err_g4_a_m = PATH1_R_LNA_ERR_G4_A_52AA_M;
		 *cr->path1_lna_err_g4_g = PATH1_R_LNA_ERR_G4_G_52AA;
		 *cr->path1_lna_err_g4_g_m = PATH1_R_LNA_ERR_G4_G_52AA_M;
		 *cr->path1_lna_err_g5_a = PATH1_R_LNA_ERR_G5_A_52AA;
		 *cr->path1_lna_err_g5_a_m = PATH1_R_LNA_ERR_G5_A_52AA_M;
		 *cr->path1_lna_err_g5_g = PATH1_R_LNA_ERR_G5_G_52AA;
		 *cr->path1_lna_err_g5_g_m = PATH1_R_LNA_ERR_G5_G_52AA_M;
		 *cr->path1_lna_err_g6_a = PATH1_R_LNA_ERR_G6_A_52AA;
		 *cr->path1_lna_err_g6_a_m = PATH1_R_LNA_ERR_G6_A_52AA_M;
		 *cr->path1_lna_err_g6_g = PATH1_R_LNA_ERR_G6_G_52AA;
		 *cr->path1_lna_err_g6_g_m = PATH1_R_LNA_ERR_G6_G_52AA_M;
		 *cr->path1_tia_err_g0_a = PATH1_R_TIA_ERR_G0_A_52AA;
		 *cr->path1_tia_err_g0_a_m = PATH1_R_TIA_ERR_G0_A_52AA_M;
		 *cr->path1_tia_err_g0_g = PATH1_R_TIA_ERR_G0_G_52AA;
		 *cr->path1_tia_err_g0_g_m = PATH1_R_TIA_ERR_G0_G_52AA_M;
		 *cr->path1_tia_err_g1_a = PATH1_R_TIA_ERR_G1_A_52AA;
		 *cr->path1_tia_err_g1_a_m = PATH1_R_TIA_ERR_G1_A_52AA_M;
		 *cr->path1_tia_err_g1_g = PATH1_R_TIA_ERR_G1_G_52AA;
		 *cr->path1_tia_err_g1_g_m = PATH1_R_TIA_ERR_G1_G_52AA_M;
		 */
		break;
#endif
#ifdef HALBB_COMPILE_AP_SERIES
	case BB_AP:
		cr->path0_ib_pbk = PATH0_R_IB_PBK_A;
		cr->path0_ib_pbk_m = PATH0_R_IB_PBK_A_M;
		cr->path0_ib_pkpwr = PATH0_R_IB_PKPW_A;
		cr->path0_ib_pkpwr_m = PATH0_R_IB_PKPW_A_M;
		cr->path1_ib_pbk = PATH1_R_IB_PBK_A;
		cr->path1_ib_pbk_m = PATH1_R_IB_PBK_A_M;
		cr->path1_ib_pkpwr = PATH1_R_IB_PKPW_A;
		cr->path1_ib_pkpwr_m = PATH1_R_IB_PKPW_A_M;
		cr->path0_lna_init_idx = PATH0_R_LNA_INIT_IDX_A;
		cr->path0_lna_init_idx_m = PATH0_R_LNA_INIT_IDX_A_M;
		cr->path1_lna_init_idx = PATH1_R_LNA_INIT_IDX_A;
		cr->path1_lna_init_idx_m = PATH1_R_LNA_INIT_IDX_A_M;
		cr->path0_tia_init_idx = PATH0_R_TIA_INIT_IDX_A;
		cr->path0_tia_init_idx_m = PATH0_R_TIA_INIT_IDX_A_M;
		cr->path1_tia_init_idx = PATH1_R_TIA_INIT_IDX_A;
		cr->path1_tia_init_idx_m = PATH1_R_TIA_INIT_IDX_A_M;
		cr->path0_rxb_init_idx = PATH0_R_RXB_INIT_IDX_A;
		cr->path0_rxb_init_idx_m = PATH0_R_RXB_INIT_IDX_A_M;
		cr->path1_rxb_init_idx = PATH1_R_RXB_INIT_IDX_A;
		cr->path1_rxb_init_idx_m = PATH1_R_RXB_INIT_IDX_A_M;
		cr->seg0r_pd_spatial_reuse_en_a = SEG0R_PD_SPATIAL_REUSE_EN_A;
		cr->seg0r_pd_spatial_reuse_en_a_m = SEG0R_PD_SPATIAL_REUSE_EN_A_M;
		cr->seg0r_pd_lower_bound_a = SEG0R_PD_LOWER_BOUND_A;
		cr->seg0r_pd_lower_bound_a_m = SEG0R_PD_LOWER_BOUND_A_M;
		cr->path0_p20_follow_by_pagcugc_en_a = PATH0_P20_R_FOLLOW_BY_PAGCUGC_EN_A;
		cr->path0_p20_follow_by_pagcugc_en_a_m = PATH0_P20_R_FOLLOW_BY_PAGCUGC_EN_A_M;
		cr->path0_s20_follow_by_pagcugc_en_a = PATH0_S20_R_FOLLOW_BY_PAGCUGC_EN_A;
		cr->path0_s20_follow_by_pagcugc_en_a_m = PATH0_S20_R_FOLLOW_BY_PAGCUGC_EN_A_M;
		cr->path1_p20_follow_by_pagcugc_en_a = PATH1_P20_R_FOLLOW_BY_PAGCUGC_EN_A;
		cr->path1_p20_follow_by_pagcugc_en_a_m = PATH1_P20_R_FOLLOW_BY_PAGCUGC_EN_A_M;
		cr->path1_s20_follow_by_pagcugc_en_a = PATH1_S20_R_FOLLOW_BY_PAGCUGC_EN_A;
		cr->path1_s20_follow_by_pagcugc_en_a_m = PATH1_S20_R_FOLLOW_BY_PAGCUGC_EN_A_M;
		cr->path0_lna_err_g0_a = PATH0_R_LNA_ERR_G0_A_A;
		cr->path0_lna_err_g0_a_m = PATH0_R_LNA_ERR_G0_A_A_M;
		cr->path0_lna_err_g0_g = PATH0_R_LNA_ERR_G0_G_A;
		cr->path0_lna_err_g0_g_m = PATH0_R_LNA_ERR_G0_G_A_M;
		cr->path0_lna_err_g1_a = PATH0_R_LNA_ERR_G1_A_A;
		cr->path0_lna_err_g1_a_m = PATH0_R_LNA_ERR_G1_A_A_M;
		cr->path0_lna_err_g1_g = PATH0_R_LNA_ERR_G1_G_A;
		cr->path0_lna_err_g1_g_m = PATH0_R_LNA_ERR_G1_G_A_M;
		cr->path0_lna_err_g2_a = PATH0_R_LNA_ERR_G2_A_A;
		cr->path0_lna_err_g2_a_m = PATH0_R_LNA_ERR_G2_A_A_M;
		cr->path0_lna_err_g2_g = PATH0_R_LNA_ERR_G2_G_A;
		cr->path0_lna_err_g2_g_m = PATH0_R_LNA_ERR_G2_G_A_M;
		cr->path0_lna_err_g3_a = PATH0_R_LNA_ERR_G3_A_A;
		cr->path0_lna_err_g3_a_m = PATH0_R_LNA_ERR_G3_A_A_M;
		cr->path0_lna_err_g3_g = PATH0_R_LNA_ERR_G3_G_A;
		cr->path0_lna_err_g3_g_m = PATH0_R_LNA_ERR_G3_G_A_M;
		cr->path0_lna_err_g4_a = PATH0_R_LNA_ERR_G4_A_A;
		cr->path0_lna_err_g4_a_m = PATH0_R_LNA_ERR_G4_A_A_M;
		cr->path0_lna_err_g4_g = PATH0_R_LNA_ERR_G4_G_A;
		cr->path0_lna_err_g4_g_m = PATH0_R_LNA_ERR_G4_G_A_M;
		cr->path0_lna_err_g5_a = PATH0_R_LNA_ERR_G5_A_A;
		cr->path0_lna_err_g5_a_m = PATH0_R_LNA_ERR_G5_A_A_M;
		cr->path0_lna_err_g5_g = PATH0_R_LNA_ERR_G5_G_A;
		cr->path0_lna_err_g5_g_m = PATH0_R_LNA_ERR_G5_G_A_M;
		cr->path0_lna_err_g6_a = PATH0_R_LNA_ERR_G6_A_A;
		cr->path0_lna_err_g6_a_m = PATH0_R_LNA_ERR_G6_A_A_M;
		cr->path0_lna_err_g6_g = PATH0_R_LNA_ERR_G6_G_A;
		cr->path0_lna_err_g6_g_m = PATH0_R_LNA_ERR_G6_G_A_M;
		cr->path0_tia_err_g0_a = PATH0_R_TIA_ERR_G0_A_A;
		cr->path0_tia_err_g0_a_m = PATH0_R_TIA_ERR_G0_A_A_M;
		cr->path0_tia_err_g0_g = PATH0_R_TIA_ERR_G0_G_A;
		cr->path0_tia_err_g0_g_m = PATH0_R_TIA_ERR_G0_G_A_M;
		cr->path0_tia_err_g1_a = PATH0_R_TIA_ERR_G1_A_A;
		cr->path0_tia_err_g1_a_m = PATH0_R_TIA_ERR_G1_A_A_M;
		cr->path0_tia_err_g1_g = PATH0_R_TIA_ERR_G1_G_A;
		cr->path0_tia_err_g1_g_m = PATH0_R_TIA_ERR_G1_G_A_M;
		cr->path1_lna_err_g0_a = PATH1_R_LNA_ERR_G0_A_A;
		cr->path1_lna_err_g0_a_m = PATH1_R_LNA_ERR_G0_A_A_M;
		cr->path1_lna_err_g0_g = PATH1_R_LNA_ERR_G0_G_A;
		cr->path1_lna_err_g0_g_m = PATH1_R_LNA_ERR_G0_G_A_M;
		cr->path1_lna_err_g1_a = PATH1_R_LNA_ERR_G1_A_A;
		cr->path1_lna_err_g1_a_m = PATH1_R_LNA_ERR_G1_A_A_M;
		cr->path1_lna_err_g1_g = PATH1_R_LNA_ERR_G1_G_A;
		cr->path1_lna_err_g1_g_m = PATH1_R_LNA_ERR_G1_G_A_M;
		cr->path1_lna_err_g2_a = PATH1_R_LNA_ERR_G2_A_A;
		cr->path1_lna_err_g2_a_m = PATH1_R_LNA_ERR_G2_A_A_M;
		cr->path1_lna_err_g2_g = PATH1_R_LNA_ERR_G2_G_A;
		cr->path1_lna_err_g2_g_m = PATH1_R_LNA_ERR_G2_G_A_M;
		cr->path1_lna_err_g3_a = PATH1_R_LNA_ERR_G3_A_A;
		cr->path1_lna_err_g3_a_m = PATH1_R_LNA_ERR_G3_A_A_M;
		cr->path1_lna_err_g3_g = PATH1_R_LNA_ERR_G3_G_A;
		cr->path1_lna_err_g3_g_m = PATH1_R_LNA_ERR_G3_G_A_M;
		cr->path1_lna_err_g4_a = PATH1_R_LNA_ERR_G4_A_A;
		cr->path1_lna_err_g4_a_m = PATH1_R_LNA_ERR_G4_A_A_M;
		cr->path1_lna_err_g4_g = PATH1_R_LNA_ERR_G4_G_A;
		cr->path1_lna_err_g4_g_m = PATH1_R_LNA_ERR_G4_G_A_M;
		cr->path1_lna_err_g5_a = PATH1_R_LNA_ERR_G5_A_A;
		cr->path1_lna_err_g5_a_m = PATH1_R_LNA_ERR_G5_A_A_M;
		cr->path1_lna_err_g5_g = PATH1_R_LNA_ERR_G5_G_A;
		cr->path1_lna_err_g5_g_m = PATH1_R_LNA_ERR_G5_G_A_M;
		cr->path1_lna_err_g6_a = PATH1_R_LNA_ERR_G6_A_A;
		cr->path1_lna_err_g6_a_m = PATH1_R_LNA_ERR_G6_A_A_M;
		cr->path1_lna_err_g6_g = PATH1_R_LNA_ERR_G6_G_A;
		cr->path1_lna_err_g6_g_m = PATH1_R_LNA_ERR_G6_G_A_M;
		cr->path1_tia_err_g0_a = PATH1_R_TIA_ERR_G0_A_A;
		cr->path1_tia_err_g0_a_m = PATH1_R_TIA_ERR_G0_A_A_M;
		cr->path1_tia_err_g0_g = PATH1_R_TIA_ERR_G0_G_A;
		cr->path1_tia_err_g0_g_m = PATH1_R_TIA_ERR_G0_G_A_M;
		cr->path1_tia_err_g1_a = PATH1_R_TIA_ERR_G1_A_A;
		cr->path1_tia_err_g1_a_m = PATH1_R_TIA_ERR_G1_A_A_M;
		cr->path1_tia_err_g1_g = PATH1_R_TIA_ERR_G1_G_A;
		cr->path1_tia_err_g1_g_m = PATH1_R_TIA_ERR_G1_G_A_M;
		break;
#endif
#ifdef HALBB_COMPILE_CLIENT_SERIES
	case BB_CLIENT:
		cr->path0_lna_init_idx = PATH0_R_LNA_IDX_INIT_C;
		cr->path0_lna_init_idx_m = PATH0_R_LNA_IDX_INIT_C_M;
		cr->path1_lna_init_idx = PATH1_R_LNA_IDX_INIT_C;
		cr->path1_lna_init_idx_m = PATH1_R_LNA_IDX_INIT_C_M;
		cr->path0_tia_init_idx = PATH0_R_TIA_IDX_INIT_C;
		cr->path0_tia_init_idx_m = PATH0_R_TIA_IDX_INIT_C_M;
		cr->path1_tia_init_idx = PATH1_R_TIA_IDX_INIT_C;
		cr->path1_tia_init_idx_m = PATH1_R_TIA_IDX_INIT_C_M;
		cr->path0_rxb_init_idx = PATH0_R_RXIDX_INIT_C;
		cr->path0_rxb_init_idx_m = PATH0_R_RXIDX_INIT_C_M;
		cr->path1_rxb_init_idx = PATH1_R_RXIDX_INIT_C;
		cr->path1_rxb_init_idx_m = PATH1_R_RXIDX_INIT_C_M;
		cr->seg0r_pd_spatial_reuse_en_a = SEG0R_PD_SPATIAL_REUSE_EN_C;
		cr->seg0r_pd_spatial_reuse_en_a_m = SEG0R_PD_SPATIAL_REUSE_EN_C_M;
		cr->seg0r_pd_lower_bound_a = SEG0R_PD_LOWER_BOUND_C;
		cr->seg0r_pd_lower_bound_a_m = SEG0R_PD_LOWER_BOUND_C_M;
#if 0
		cr->path0_ib_pbk = PATH0_R_IB_PBK_C;
		cr->path0_ib_pbk_m = PATH0_R_IB_PBK_C_M;
		cr->path0_ib_pkpwr = PATH0_R_IB_PKPW_C;
		cr->path0_ib_pkpwr_m = PATH0_R_IB_PKPW_C_M;
		cr->path1_ib_pbk = PATH1_R_IB_PBK_C;
		cr->path1_ib_pbk_m = PATH1_R_IB_PBK_C_M;
		cr->path1_ib_pkpwr = PATH1_R_IB_PKPW_C;
		cr->path1_ib_pkpwr_m = PATH1_R_IB_PKPW_C_M;
		cr->path0_lna_init_idx = PATH0_R_LNA_INIT_IDX_C;
		cr->path0_lna_init_idx_m = PATH0_R_LNA_INIT_IDX_C_M;
		cr->path1_lna_init_idx = PATH1_R_LNA_INIT_IDX_C;
		cr->path1_lna_init_idx_m = PATH1_R_LNA_INIT_IDX_C_M;
		cr->path0_tia_init_idx = PATH0_R_TIA_INIT_IDX_C;
		cr->path0_tia_init_idx_m = PATH0_R_TIA_INIT_IDX_C_M;
		cr->path1_tia_init_idx = PATH1_R_TIA_INIT_IDX_C;
		cr->path1_tia_init_idx_m = PATH1_R_TIA_INIT_IDX_C_M;
		cr->path0_rxb_init_idx = PATH0_R_RXB_INIT_IDX_C;
		cr->path0_rxb_init_idx_m = PATH0_R_RXB_INIT_IDX_C_M;
		cr->path1_rxb_init_idx = PATH1_R_RXB_INIT_IDX_C;
		cr->path1_rxb_init_idx_m = PATH1_R_RXB_INIT_IDX_C_M;
		cr->seg0r_pd_spatial_reuse_en_a = SEG0R_PD_SPATIAL_REUSE_EN_C;
		cr->seg0r_pd_spatial_reuse_en_a_m = SEG0R_PD_SPATIAL_REUSE_EN_C_M;
		cr->seg0r_pd_lower_bound_a = SEG0R_PD_LOWER_BOUND_C;
		cr->seg0r_pd_lower_bound_a_m = SEG0R_PD_LOWER_BOUND_C_M;
		cr->path0_p20_follow_by_pagcugc_en_a = PATH0_P20_R_FOLLOW_BY_PAGCUGC_EN_C;
		cr->path0_p20_follow_by_pagcugc_en_a_m = PATH0_P20_R_FOLLOW_BY_PAGCUGC_EN_C_M;
		cr->path0_s20_follow_by_pagcugc_en_a = PATH0_S20_R_FOLLOW_BY_PAGCUGC_EN_C;
		cr->path0_s20_follow_by_pagcugc_en_a_m = PATH0_S20_R_FOLLOW_BY_PAGCUGC_EN_C_M;
		cr->path1_p20_follow_by_pagcugc_en_a = PATH1_P20_R_FOLLOW_BY_PAGCUGC_EN_C;
		cr->path1_p20_follow_by_pagcugc_en_a_m = PATH1_P20_R_FOLLOW_BY_PAGCUGC_EN_C_M;
		cr->path1_s20_follow_by_pagcugc_en_a = PATH1_S20_R_FOLLOW_BY_PAGCUGC_EN_C;
		cr->path1_s20_follow_by_pagcugc_en_a_m = PATH1_S20_R_FOLLOW_BY_PAGCUGC_EN_C_M;
		cr->path0_lna_err_g0_a = PATH0_R_LNA_ERR_G0_C_C;
		cr->path0_lna_err_g0_a_m = PATH0_R_LNA_ERR_G0_C_C_M;
		cr->path0_lna_err_g0_g = PATH0_R_LNA_ERR_G0_G_C;
		cr->path0_lna_err_g0_g_m = PATH0_R_LNA_ERR_G0_G_C_M;
		cr->path0_lna_err_g1_a = PATH0_R_LNA_ERR_G1_C_C;
		cr->path0_lna_err_g1_a_m = PATH0_R_LNA_ERR_G1_C_C_M;
		cr->path0_lna_err_g1_g = PATH0_R_LNA_ERR_G1_G_C;
		cr->path0_lna_err_g1_g_m = PATH0_R_LNA_ERR_G1_G_C_M;
		cr->path0_lna_err_g2_a = PATH0_R_LNA_ERR_G2_C_C;
		cr->path0_lna_err_g2_a_m = PATH0_R_LNA_ERR_G2_C_C_M;
		cr->path0_lna_err_g2_g = PATH0_R_LNA_ERR_G2_G_C;
		cr->path0_lna_err_g2_g_m = PATH0_R_LNA_ERR_G2_G_C_M;
		cr->path0_lna_err_g3_a = PATH0_R_LNA_ERR_G3_C_C;
		cr->path0_lna_err_g3_a_m = PATH0_R_LNA_ERR_G3_C_C_M;
		cr->path0_lna_err_g3_g = PATH0_R_LNA_ERR_G3_G_C;
		cr->path0_lna_err_g3_g_m = PATH0_R_LNA_ERR_G3_G_C_M;
		cr->path0_lna_err_g4_a = PATH0_R_LNA_ERR_G4_C_C;
		cr->path0_lna_err_g4_a_m = PATH0_R_LNA_ERR_G4_C_C_M;
		cr->path0_lna_err_g4_g = PATH0_R_LNA_ERR_G4_G_C;
		cr->path0_lna_err_g4_g_m = PATH0_R_LNA_ERR_G4_G_C_M;
		cr->path0_lna_err_g5_a = PATH0_R_LNA_ERR_G5_C_C;
		cr->path0_lna_err_g5_a_m = PATH0_R_LNA_ERR_G5_C_C_M;
		cr->path0_lna_err_g5_g = PATH0_R_LNA_ERR_G5_G_C;
		cr->path0_lna_err_g5_g_m = PATH0_R_LNA_ERR_G5_G_C_M;
		cr->path0_lna_err_g6_a = PATH0_R_LNA_ERR_G6_C_C;
		cr->path0_lna_err_g6_a_m = PATH0_R_LNA_ERR_G6_C_C_M;
		cr->path0_lna_err_g6_g = PATH0_R_LNA_ERR_G6_G_C;
		cr->path0_lna_err_g6_g_m = PATH0_R_LNA_ERR_G6_G_C_M;
		cr->path0_tia_err_g0_a = PATH0_R_TIA_ERR_G0_C_C;
		cr->path0_tia_err_g0_a_m = PATH0_R_TIA_ERR_G0_C_C_M;
		cr->path0_tia_err_g0_g = PATH0_R_TIA_ERR_G0_G_C;
		cr->path0_tia_err_g0_g_m = PATH0_R_TIA_ERR_G0_G_C_M;
		cr->path0_tia_err_g1_a = PATH0_R_TIA_ERR_G1_C_C;
		cr->path0_tia_err_g1_a_m = PATH0_R_TIA_ERR_G1_C_C_M;
		cr->path0_tia_err_g1_g = PATH0_R_TIA_ERR_G1_G_C;
		cr->path0_tia_err_g1_g_m = PATH0_R_TIA_ERR_G1_G_C_M;
		cr->path1_lna_err_g0_a = PATH1_R_LNA_ERR_G0_C_C;
		cr->path1_lna_err_g0_a_m = PATH1_R_LNA_ERR_G0_C_C_M;
		cr->path1_lna_err_g0_g = PATH1_R_LNA_ERR_G0_G_C;
		cr->path1_lna_err_g0_g_m = PATH1_R_LNA_ERR_G0_G_C_M;
		cr->path1_lna_err_g1_a = PATH1_R_LNA_ERR_G1_C_C;
		cr->path1_lna_err_g1_a_m = PATH1_R_LNA_ERR_G1_C_C_M;
		cr->path1_lna_err_g1_g = PATH1_R_LNA_ERR_G1_G_C;
		cr->path1_lna_err_g1_g_m = PATH1_R_LNA_ERR_G1_G_C_M;
		cr->path1_lna_err_g2_a = PATH1_R_LNA_ERR_G2_C_C;
		cr->path1_lna_err_g2_a_m = PATH1_R_LNA_ERR_G2_C_C_M;
		cr->path1_lna_err_g2_g = PATH1_R_LNA_ERR_G2_G_C;
		cr->path1_lna_err_g2_g_m = PATH1_R_LNA_ERR_G2_G_C_M;
		cr->path1_lna_err_g3_a = PATH1_R_LNA_ERR_G3_C_C;
		cr->path1_lna_err_g3_a_m = PATH1_R_LNA_ERR_G3_C_C_M;
		cr->path1_lna_err_g3_g = PATH1_R_LNA_ERR_G3_G_C;
		cr->path1_lna_err_g3_g_m = PATH1_R_LNA_ERR_G3_G_C_M;
		cr->path1_lna_err_g4_a = PATH1_R_LNA_ERR_G4_C_C;
		cr->path1_lna_err_g4_a_m = PATH1_R_LNA_ERR_G4_C_C_M;
		cr->path1_lna_err_g4_g = PATH1_R_LNA_ERR_G4_G_C;
		cr->path1_lna_err_g4_g_m = PATH1_R_LNA_ERR_G4_G_C_M;
		cr->path1_lna_err_g5_a = PATH1_R_LNA_ERR_G5_C_C;
		cr->path1_lna_err_g5_a_m = PATH1_R_LNA_ERR_G5_C_C_M;
		cr->path1_lna_err_g5_g = PATH1_R_LNA_ERR_G5_G_C;
		cr->path1_lna_err_g5_g_m = PATH1_R_LNA_ERR_G5_G_C_M;
		cr->path1_lna_err_g6_a = PATH1_R_LNA_ERR_G6_C_C;
		cr->path1_lna_err_g6_a_m = PATH1_R_LNA_ERR_G6_C_C_M;
		cr->path1_lna_err_g6_g = PATH1_R_LNA_ERR_G6_G_C;
		cr->path1_lna_err_g6_g_m = PATH1_R_LNA_ERR_G6_G_C_M;
		cr->path1_tia_err_g0_a = PATH1_R_TIA_ERR_G0_C_C;
		cr->path1_tia_err_g0_a_m = PATH1_R_TIA_ERR_G0_C_C_M;
		cr->path1_tia_err_g0_g = PATH1_R_TIA_ERR_G0_G_C;
		cr->path1_tia_err_g0_g_m = PATH1_R_TIA_ERR_G0_G_C_M;
		cr->path1_tia_err_g1_a = PATH1_R_TIA_ERR_G1_C_C;
		cr->path1_tia_err_g1_a_m = PATH1_R_TIA_ERR_G1_C_C_M;
		cr->path1_tia_err_g1_g = PATH1_R_TIA_ERR_G1_G_C;
		cr->path1_tia_err_g1_g_m = PATH1_R_TIA_ERR_G1_G_C_M;
#endif
		break;
#endif
	default:
		break;
	}
}
#endif
#ifdef HALBB_DIG_MCC_SUPPORT
void Halbb_init_mccdm(struct bb_info *bb)
{
	struct halbb_mcc_dm *mcc_dm = &bb->mcc_dm;
	u8 i = 0;

	BB_DBG(bb, DBG_DIG, "[%s]=========>\n", __func__);

	mcc_dm->softap_macid = INVALID_INIT_VAL;

	for (i = 0; i < MCC_BAND_NUM; i++) {
		mcc_dm->mcc_reg_id[i] = INVALID_INIT_VAL;
		mcc_dm->mcc_dm_reg[i] = 0;
		mcc_dm->mcc_dm_val[i][0] = 0;
		mcc_dm->mcc_dm_val[i][1] = 0;
	}
}

u32 halbb_c2h_mccdm_check(struct bb_info *bb, u16 len, u8 *c2h)
{
	bool fw_mccdm_en = false;

	if (!c2h) {
		BB_WARNING("Error fw mcc dig c2h failed!!\n");
		return _FAIL;
	}

	fw_mccdm_en = (bool)c2h[0];
	BB_DBG(bb, DBG_DIG, "FW MCC DIG : %s\n", fw_mccdm_en ? "true" : "false");

	return _SUCCESS;
}

void halbb_mccdm_h2ccmd_rst(struct bb_info *bb)
{
	struct mcc_h2c *mcc_cfg;
	bool ret_val = false;
	u8 cmdlen = sizeof(struct mcc_h2c);
	u32 *bb_h2c;

	mcc_cfg = hal_mem_alloc(bb->hal_com, cmdlen);

	if (!mcc_cfg) {
		BB_WARNING(" Error mcc_cfg allocat failed!!\n");
		return;
	}
	halbb_mem_set(bb, mcc_cfg, 0, cmdlen);
	bb_h2c = (u32*) mcc_cfg;
	//u8 h2c_mcc[H2C_MAX_LENGTH];

	/* RST MCC */
	mcc_cfg->mcc_dm_en = 0;
	mcc_cfg->reg_cnt = 0;
	mcc_cfg->mcc_set = 0;
	ret_val = halbb_fill_h2c_cmd(bb, cmdlen, DM_H2C_FW_MCC,
					   HALBB_H2C_DM, bb_h2c);
	BB_DBG(bb, DBG_DIG, "MCC H2C RST\n");

	if (mcc_cfg)
		hal_mem_free(bb->hal_com, mcc_cfg, cmdlen);
}

void Halbb_mccdm_h2c_handler(struct bb_info *bb)
{
	struct halbb_mcc_dm *mcc_dm = &bb->mcc_dm;
	struct mcc_h2c_reg_content *reg_cont;
	struct mcc_h2c *mcc_cfg;
	bool ret_val = false;
	u8 cmdlen = sizeof(struct mcc_h2c);
	u8 i;
	u8 regid;
	u8 ch_idx;
	u8 reg_cnt;
	u32 *bb_h2c;

	mcc_cfg = hal_mem_alloc(bb->hal_com, cmdlen);

	if (!mcc_cfg) {
		BB_WARNING(" Error mcc_cfg allocat failed!!\n");
		return;
	}
	bb_h2c = (u32*) mcc_cfg;

	if (mcc_dm->mcc_rf_ch[0].center_ch == INVALID_INIT_VAL &&
	    mcc_dm->mcc_rf_ch[1].center_ch == INVALID_INIT_VAL) {
		BB_DBG(bb, DBG_DIG, "MCC channel Error\n");
		mcc_cfg->mcc_dm_en = 0;
		mcc_cfg->reg_cnt = 0;
		mcc_cfg->mcc_set = 0;
		ret_val = halbb_fill_h2c_cmd(bb, cmdlen, DM_H2C_FW_MCC,
					     HALBB_H2C_DM, bb_h2c);
		if (mcc_cfg)
			hal_mem_free(bb->hal_com, mcc_cfg, cmdlen);
		return;
	}

	/* Set Channel number, reg, and val*/
	for (ch_idx = 0; ch_idx < MCC_BAND_NUM; ch_idx++) {
		halbb_mem_set(bb, mcc_cfg, 0, cmdlen);
		reg_cnt = 0;
		mcc_cfg->mcc_dm_en = 1;
		mcc_cfg->mcc_ch_idx = ch_idx;
		mcc_cfg->mcc_set = 1;
		mcc_cfg->phy0_en = 1;
		mcc_cfg->phy1_en = 0;
		mcc_cfg->ch_lsb = (u8)mcc_dm->mcc_rf_ch[ch_idx].center_ch;
		mcc_cfg->ch_msb = (u8)mcc_dm->mcc_rf_ch[ch_idx].band;
		for (i = 0; i < NUM_MAX_IGI_CNT; i++) {
			regid = mcc_dm->mcc_reg_id[i];
			if (regid == INVALID_INIT_VAL)
				break;
			reg_cont = &mcc_cfg->mcc_reg_content[i];
			reg_cont->addr_lsb = (u8)mcc_dm->mcc_dm_reg[i];
			reg_cont->addr_msb = (u8)(mcc_dm->mcc_dm_reg[i] >> 8);
			reg_cont->bmask_lsb = (u8)(mcc_dm->mcc_dm_mask[i]);
			reg_cont->bmask_msb = (u8)(mcc_dm->mcc_dm_mask[i] >> 8);
			reg_cont->val_lsb = (u8)(mcc_dm->mcc_dm_val[i][ch_idx]);
			reg_cont->val_msb = (u8)(mcc_dm->mcc_dm_val[i][ch_idx] >> 8);
			reg_cnt++;
		}
		mcc_cfg->reg_cnt = reg_cnt;
		BB_DBG(bb, DBG_DIG, "MCC H2C SetCH: 0x%x 0x%x 0x%x\n",
		       bb_h2c[0], bb_h2c[1], bb_h2c[2]);
		ret_val = halbb_fill_h2c_cmd(bb, cmdlen, DM_H2C_FW_MCC,
					     HALBB_H2C_DM, bb_h2c);
	}

	if (mcc_cfg)
		hal_mem_free(bb->hal_com, mcc_cfg, cmdlen);
}

void halbb_mccdm_ctrl(struct bb_info *bb)
{
	struct halbb_mcc_dm *mcc_dm = &bb->mcc_dm;
	u32 val[2] = {0};

	BB_DBG(bb, DBG_DIG, "MCC status: %x\n", mcc_dm->mcc_status_en);
	/*MCC stage no change*/
	if (mcc_dm->mcc_status_en == mcc_dm->mcc_pre_status_en)
		return;

	/*Not in MCC stage*/
	if (mcc_dm->mcc_status_en != 0) {
		/* Disable normal DIG */
		halbb_pause_func(bb, F_DIG, HALBB_PAUSE_NO_SET, HALBB_PAUSE_LV_2,
				 2, val);
	}
	if (mcc_dm->mcc_status_en == 0 && mcc_dm->mcc_pre_status_en != 0) {
		Halbb_init_mccdm(bb);
		halbb_mccdm_h2ccmd_rst(bb);
		/* Enable normal DIG */
		halbb_pause_func(bb, F_DIG, HALBB_RESUME, HALBB_PAUSE_LV_2, 2,
				 val);
	}

	mcc_dm->mcc_pre_status_en = mcc_dm->mcc_status_en;
}

void halbb_fill_mcccmd(struct bb_info *bb, u8 regid, u16 reg_add, u16 mask,
		       u8 band, u16 val)
{
	struct halbb_mcc_dm *mcc_dm = &bb->mcc_dm;

	mcc_dm->mcc_reg_id[regid] = regid;
	mcc_dm->mcc_dm_reg[regid] = reg_add;
	mcc_dm->mcc_dm_mask[regid] = mask;
	mcc_dm->mcc_dm_val[regid][band] = val;
}

void halbb_mccdm_igi_rst(struct bb_info *bb, u8 clr_port)
{
	struct halbb_mcc_dm *mcc_dm = &bb->mcc_dm;

	mcc_dm->mcc_dm_val[0][clr_port] = PD_IDX_MIN; //-102dBm
	//mcc_dm->mcc_dm_val[1][clr_port] = 0xff;
}

#if 0
void halbb_mcc_igi_chk(struct bb_info *bb)
{
	struct halbb_mcc_dm *mcc_dm = &bb->mcc_dm;

	if (mcc_dm->mcc_dm_val[0][0] == 0xffff &&
	    mcc_dm->mcc_dm_val[0][1] == 0xffff) {
		mcc_dm->mcc_dm_reg[0] = 0xffff;
		mcc_dm->mcc_reg_id[0] = 0xff;
	}

	if (mcc_dm->mcc_dm_val[1][0] == 0xffff &&
	    mcc_dm->mcc_dm_val[1][1] == 0xffff) {
		mcc_dm->mcc_dm_reg[1] = 0xffff;
		mcc_dm->mcc_reg_id[1] = 0xff;
	}
}
#endif

u8 halbb_mccdm_pd_lower_bound_cal(struct bb_info *bb, u8 bound,
				      enum channel_width bw)
{
	/*
	Range of bound value:
	BW20: 95~33
	BW40: 92~30
	BW80: 89~27
	*/
	u8 bw_attenuation = 0;
	u8 subband_filter_atteniation = 7;
	u8 bound_idx = 0;

	if (bound == 0) {
		BB_DBG(bb, DBG_DIG,
		       "[PD Bound] Set Boundary to default!\n");
		return 0;
	}

	if (bw == CHANNEL_WIDTH_20) {
		bw_attenuation = 0;
	} else if (bw == CHANNEL_WIDTH_40) {
		bw_attenuation = 3;
	} else if (bw == CHANNEL_WIDTH_80) {
		bw_attenuation = 6;
	} else {
		BB_DBG(bb, DBG_DIG,
		       "[PD Bound] Only support BW20/40/80 !\n");
		return 0;
	}

	bound += (bw_attenuation + subband_filter_atteniation);
	// If Boundary dbm is odd, set it to even number
	bound = bound % 2 ? bound + 1 : bound;

	if (bound < 40) {
		BB_DBG(bb, DBG_DIG,
		       "[PD Bound] Threshold too high, set to highest level!\n");
		bound = 40;
	}

	if (bound > 102) {
		BB_DBG(bb, DBG_DIG,
		       "[PD Bound] Threshold too low, disable PD lower bound function!\n");
		bound = 102;
	}

	bound_idx =  (102 - bound) >> 1;

	return bound_idx;
}

void halbb_mccdm_pd_cal(struct bb_info *bb)
{
	struct halbb_mcc_dm *mcc_dm = &bb->mcc_dm;
	struct bb_dig_info *bb_dig = &bb->bb_dig_i;
	struct bb_dig_op_unit *bb_dig_u = bb_dig->p_cur_dig_unit;
	struct bb_dig_cr_info *cr = &bb_dig->bb_dig_cr_i;
	u8 shift = 10;
	u8 igi_val;
	u8 pd_val;
	u8 i;
	u16 mask0;
	u16 reg0;
	enum channel_width cbw = CHANNEL_WIDTH_20;

	for (i = 0; i < MCC_BAND_NUM; i++) {
		igi_val = mcc_dm->rssi_min[i] >> 1;
		igi_val = SUBTRACT_TO_0(igi_val, shift);
		igi_val = MIN_2(igi_val, IGI_MAX_PERFORMANCE_MODE);
		igi_val = MAX_2(igi_val, 0xc);
		igi_val -= MIN_2(igi_val, bb_dig_u->pd_low_th_ofst);

		cbw = mcc_dm->mcc_rf_ch[i].bw;

		pd_val = halbb_mccdm_pd_lower_bound_cal(bb, RSSI_MAX - igi_val,
							cbw);

		reg0 = (u16)cr->seg0r_pd_lower_bound_a;
		mask0 = (u16)cr->seg0r_pd_lower_bound_a_m;

		halbb_fill_mcccmd(bb, 0, reg0, mask0, i, (u16)pd_val);

		if (mcc_dm->sta_cnt[i] == 0)
			halbb_mccdm_igi_rst(bb, i);
	}

	BB_DBG(bb, DBG_DIG, "STA cnt %d %d, RSSI_min: %d %d, BW: %d %d, MCC_pd_idx: %d %d\n",
	       mcc_dm->sta_cnt[0], mcc_dm->sta_cnt[1],
	       mcc_dm->rssi_min[0] >> 1, mcc_dm->rssi_min[1] >> 1,
	       mcc_dm->mcc_rf_ch[0].bw, mcc_dm->mcc_rf_ch[1].bw,
	       mcc_dm->mcc_dm_val[0][0], mcc_dm->mcc_dm_val[0][1]);
}

void halbb_mccdm_switch(struct bb_info *bb)
{
	struct halbb_mcc_dm *mcc_dm = &bb->mcc_dm;

	if (!(bb->ic_type & HALBB_DIG_MCC_SUPPORT_IC)) {
		BB_DBG(bb, DBG_DIG, "IC type is not supported\n");
		return;
	}

	halbb_mccdm_ctrl(bb);

	if (mcc_dm->mcc_status_en == 0)
		return;
	BB_DBG(bb, DBG_DIG, "<====== %s ======>\n", __func__);

	/* Set IGI*/
	halbb_mccdm_pd_cal(bb);

	/* Set H2C Cmd*/
	Halbb_mccdm_h2c_handler(bb);
}
#endif
