/* SPDX-License-Identifier: GPL-2.0 */
/******************************************************************************
 *
 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 *
 ******************************************************************************/

/* ************************************************************
 * include files
 * ************************************************************ */

#include "mp_precomp.h"
#include "phydm_precomp.h"

void
phydm_init_debug_setting(
	struct PHY_DM_STRUCT		*p_dm_odm
)
{
	p_dm_odm->debug_level = ODM_DBG_TRACE;

	p_dm_odm->fw_debug_components = 0;
	p_dm_odm->debug_components			=
		/*BB Functions*/
		/*									ODM_COMP_DIG					|*/
		/*									ODM_COMP_RA_MASK				|*/
		/*									ODM_COMP_DYNAMIC_TXPWR			|*/
		/*									ODM_COMP_FA_CNT				|*/
		/*									ODM_COMP_RSSI_MONITOR			|*/
		/*									ODM_COMP_SNIFFER				|*/
		/*									ODM_COMP_ANT_DIV				|*/
		/*									ODM_COMP_NOISY_DETECT			|*/
		/*									ODM_COMP_RATE_ADAPTIVE			|*/
		/*									ODM_COMP_PATH_DIV				|*/
		/*									ODM_COMP_DYNAMIC_PRICCA		|*/
		/*									ODM_COMP_MP					|*/
		/*									ODM_COMP_CFO_TRACKING			|*/
		/*									ODM_COMP_ACS					|*/
		/*									PHYDM_COMP_ADAPTIVITY			|*/
		/*									PHYDM_COMP_RA_DBG				|*/
		/*									PHYDM_COMP_TXBF					|*/

		/*MAC Functions*/
		/*									ODM_COMP_EDCA_TURBO			|*/
		/*									ODM_COMP_DYNAMIC_RX_PATH		|*/
		/*									ODM_FW_DEBUG_TRACE				|*/

		/*RF Functions*/
		/*									ODM_COMP_TX_PWR_TRACK			|*/
		/*									ODM_COMP_CALIBRATION			|*/

		/*Common*/
		/*									ODM_PHY_CONFIG					|*/
		/*									ODM_COMP_INIT					|*/
		/*									ODM_COMP_COMMON				|*/
		/*									ODM_COMP_API				|*/

		0;

	p_dm_odm->fw_buff_is_enpty = true;
	p_dm_odm->pre_c2h_seq = 0;
}

void
phydm_bb_dbg_port_header_sel(
	void			*p_dm_void,
	u32			header_idx
) {
	struct PHY_DM_STRUCT		*p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
	
	if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) {
		
		odm_set_bb_reg(p_dm_odm, 0x8f8, (BIT(25) | BIT(24) | BIT(23) | BIT(22)), header_idx);
		
		/*
		header_idx:
			(0:) '{ofdm_dbg[31:0]}'
			(1:) '{cca,crc32_fail,dbg_ofdm[29:0]}'
			(2:) '{vbon,crc32_fail,dbg_ofdm[29:0]}'
			(3:) '{cca,crc32_ok,dbg_ofdm[29:0]}'
			(4:) '{vbon,crc32_ok,dbg_ofdm[29:0]}'
			(5:) '{dbg_iqk_anta}'
			(6:) '{cca,ofdm_crc_ok,dbg_dp_anta[29:0]}'
			(7:) '{dbg_iqk_antb}'
			(8:) '{DBGOUT_RFC_b[31:0]}'
			(9:) '{DBGOUT_RFC_a[31:0]}'
			(a:) '{dbg_ofdm}'
			(b:) '{dbg_cck}'
		*/
	}
}

void
phydm_bb_dbg_port_clock_en(
	void			*p_dm_void,
	u8			enable
) {
	struct PHY_DM_STRUCT		*p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
	u32		reg_value = (enable == TRUE) ? 0x7 : 0;
	
	if (p_dm_odm->support_ic_type & (ODM_RTL8822B | ODM_RTL8821C | ODM_RTL8814A | ODM_RTL8814B)) {
		
		odm_set_bb_reg(p_dm_odm, 0x198c, 0x7, reg_value); /*enable/disable debug port clock, for power saving*/
	}
}

u8
phydm_set_bb_dbg_port(
	void			*p_dm_void,
	u8			curr_dbg_priority,
	u32			debug_port
)
{
	struct PHY_DM_STRUCT		*p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
	u8	dbg_port_result = FALSE;
		
	if (curr_dbg_priority > p_dm_odm->pre_dbg_priority) {

		if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) {
			
			phydm_bb_dbg_port_clock_en(p_dm_odm, TRUE);
			
			odm_set_bb_reg(p_dm_odm, 0x8fc, MASKDWORD, debug_port);
			/**/
		} else /*if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES)*/ {
			odm_set_bb_reg(p_dm_odm, 0x908, MASKDWORD, debug_port);
			/**/
		}
		ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("DbgPort set success, Reg((0x%x)), Cur_priority=((%d)), Pre_priority=((%d))\n", debug_port, curr_dbg_priority, p_dm_odm->pre_dbg_priority));
		p_dm_odm->pre_dbg_priority = curr_dbg_priority;
		dbg_port_result = TRUE;
	}
		
	return dbg_port_result;
}

void
phydm_release_bb_dbg_port(
	void			*p_dm_void
)
{
	struct PHY_DM_STRUCT		*p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;

	phydm_bb_dbg_port_clock_en(p_dm_odm, FALSE);
	phydm_bb_dbg_port_header_sel(p_dm_odm, 0);

	p_dm_odm->pre_dbg_priority = BB_DBGPORT_RELEASE;
	ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("Release BB dbg_port\n"));
}

u32
phydm_get_bb_dbg_port_value(
	void			*p_dm_void
)
{
	struct PHY_DM_STRUCT		*p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
	u32	dbg_port_value = 0;

	if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) {
		dbg_port_value = odm_get_bb_reg(p_dm_odm, 0xfa0, MASKDWORD);
		/**/
	} else /*if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES)*/ {
		dbg_port_value = odm_get_bb_reg(p_dm_odm, 0xdf4, MASKDWORD);
		/**/
	}
	ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("dbg_port_value = 0x%x\n", dbg_port_value));
	return	dbg_port_value;
}

void
phydm_basic_dbg_message
(
	void			*p_dm_void
)
{
	struct PHY_DM_STRUCT		*p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
	struct _FALSE_ALARM_STATISTICS *false_alm_cnt = (struct _FALSE_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_FALSEALMCNT);
	struct _CFO_TRACKING_				*p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
	struct _dynamic_initial_gain_threshold_	*p_dm_dig_table = &p_dm_odm->dm_dig_table;
	struct _rate_adaptive_table_	*p_ra_table = &p_dm_odm->dm_ra_table;
	u16	macid, phydm_macid, client_cnt = 0;
	struct sta_info	*p_entry;
	u8	tmp_val_u1 = 0;

	ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[PHYDM Common MSG] System up time: ((%d sec))----->\n", p_dm_odm->phydm_sys_up_time));

	if (p_dm_odm->is_linked) {
		ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ID=%d, BW=((%d)), CH=((%d))\n", p_dm_odm->curr_station_id, 20<<(*(p_dm_odm->p_band_width)), *(p_dm_odm->p_channel)));

		/*Print RX rate*/
		if (p_dm_odm->rx_rate <= ODM_RATE11M) {
			ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[CCK AGC Report] LNA_idx = 0x%x, VGA_idx = 0x%x\n",
				p_dm_odm->cck_lna_idx, p_dm_odm->cck_vga_idx));
		} else {
			ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[OFDM AGC Report] { 0x%x, 0x%x, 0x%x, 0x%x }\n",
				p_dm_odm->ofdm_agc_idx[0], p_dm_odm->ofdm_agc_idx[1], p_dm_odm->ofdm_agc_idx[2], p_dm_odm->ofdm_agc_idx[3]));
		}

		ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RSSI: { %d,  %d,  %d,  %d },    rx_rate:",
			(p_dm_odm->RSSI_A == 0xff) ? 0 : p_dm_odm->RSSI_A,
			(p_dm_odm->RSSI_B == 0xff) ? 0 : p_dm_odm->RSSI_B,
			(p_dm_odm->RSSI_C == 0xff) ? 0 : p_dm_odm->RSSI_C,
			(p_dm_odm->RSSI_D == 0xff) ? 0 : p_dm_odm->RSSI_D));

		phydm_print_rate(p_dm_odm, p_dm_odm->rx_rate, ODM_COMP_COMMON);

		/*Print TX rate*/
		for (macid = 0; macid < ODM_ASSOCIATE_ENTRY_NUM; macid++) {

			p_entry = p_dm_odm->p_odm_sta_info[macid];
			if (IS_STA_VALID(p_entry)) {

				phydm_macid = (p_dm_odm->platform2phydm_macid_table[macid]);
				ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("TXRate [%d]:", macid));
				phydm_print_rate(p_dm_odm, p_ra_table->link_tx_rate[macid], ODM_COMP_COMMON);

				client_cnt++;

				if (client_cnt == p_dm_odm->number_linked_client)
					break;
			}
		}

		ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("TP { TX, RX, total} = {%d, %d, %d }Mbps, traffic_load = (%d))\n",
			p_dm_odm->tx_tp, p_dm_odm->rx_tp, p_dm_odm->total_tp, p_dm_odm->traffic_load));

		tmp_val_u1 = (p_cfo_track->crystal_cap > p_cfo_track->def_x_cap) ? (p_cfo_track->crystal_cap - p_cfo_track->def_x_cap) : (p_cfo_track->def_x_cap - p_cfo_track->crystal_cap);
		ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("CFO_avg = ((%d kHz)) , CrystalCap_tracking = ((%s%d))\n",
			p_cfo_track->CFO_ave_pre, ((p_cfo_track->crystal_cap > p_cfo_track->def_x_cap) ? "+" : "-"), tmp_val_u1));

		/* Condition number */

		/*STBC or LDPC pkt*/
		ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("LDPC = %s, STBC = %s\n", (p_dm_odm->phy_dbg_info.is_ldpc_pkt) ? "Y" : "N", (p_dm_odm->phy_dbg_info.is_stbc_pkt) ? "Y" : "N"));
	} else
		ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("No Link !!!\n"));

	ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[CCA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n",
		false_alm_cnt->cnt_cck_cca, false_alm_cnt->cnt_ofdm_cca, false_alm_cnt->cnt_cca_all));

	ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[FA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n",
		false_alm_cnt->cnt_cck_fail, false_alm_cnt->cnt_ofdm_fail, false_alm_cnt->cnt_all));


	ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("is_linked = %d, Num_client = %d, rssi_min = %d, current_igi = 0x%x, bNoisy=%d\n\n",
		p_dm_odm->is_linked, p_dm_odm->number_linked_client, p_dm_odm->rssi_min, p_dm_dig_table->cur_ig_value, p_dm_odm->noisy_decision));
}


s32
phydm_cmd(
	struct PHY_DM_STRUCT	*p_dm_odm,
	char		*input,
	u32	in_len,
	u8	flag,
	char	*output,
	u32	out_len
)
{
	char *token;
	u32	argc = 0;
	char		argv[MAX_ARGC][MAX_ARGV];

	do {
		token = strsep(&input, ", ");
		if (token) {
			strcpy(argv[argc], token);
			argc++;
		} else
			break;
	} while (argc < MAX_ARGC);

	if (argc == 1)
		argv[0][strlen(argv[0]) - 1] = '\0';

	return 0;
}

void
phydm_fw_trace_handler(
	void	*p_dm_void,
	u8	*cmd_buf,
	u8	cmd_len
)
{
}

void
phydm_fw_trace_handler_code(
	void	*p_dm_void,
	u8	*buffer,
	u8	cmd_len
)
{
}

void
phydm_fw_trace_handler_8051(
	void	*p_dm_void,
	u8	*buffer,
	u8	cmd_len
)
{
}
